@mhalder/qdrant-mcp-server 3.3.3 → 3.3.4

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 (168) hide show
  1. package/.github/workflows/ci.yml +0 -2
  2. package/.github/workflows/claude-code-review.yml +1 -1
  3. package/CHANGELOG.md +6 -0
  4. package/README.md +1 -1
  5. package/biome.json +3 -2
  6. package/build/code/chunker/tree-sitter-chunker.d.ts.map +1 -1
  7. package/build/code/chunker/tree-sitter-chunker.js +2 -12
  8. package/build/code/chunker/tree-sitter-chunker.js.map +1 -1
  9. package/build/code/indexer.d.ts.map +1 -1
  10. package/build/code/indexer.js +12 -18
  11. package/build/code/indexer.js.map +1 -1
  12. package/build/code/scanner.js +1 -1
  13. package/build/code/scanner.js.map +1 -1
  14. package/build/embeddings/cohere.d.ts +1 -1
  15. package/build/embeddings/cohere.d.ts.map +1 -1
  16. package/build/embeddings/cohere.js +2 -2
  17. package/build/embeddings/cohere.js.map +1 -1
  18. package/build/embeddings/cohere.test.js +1 -5
  19. package/build/embeddings/cohere.test.js.map +1 -1
  20. package/build/embeddings/factory.d.ts +1 -1
  21. package/build/embeddings/factory.d.ts.map +1 -1
  22. package/build/embeddings/factory.js +7 -9
  23. package/build/embeddings/factory.js.map +1 -1
  24. package/build/embeddings/factory.test.js +3 -3
  25. package/build/embeddings/factory.test.js.map +1 -1
  26. package/build/embeddings/ollama.d.ts +1 -1
  27. package/build/embeddings/ollama.d.ts.map +1 -1
  28. package/build/embeddings/ollama.js +6 -8
  29. package/build/embeddings/ollama.js.map +1 -1
  30. package/build/embeddings/ollama.test.js +2 -6
  31. package/build/embeddings/ollama.test.js.map +1 -1
  32. package/build/embeddings/openai.d.ts +1 -1
  33. package/build/embeddings/openai.d.ts.map +1 -1
  34. package/build/embeddings/openai.js +4 -7
  35. package/build/embeddings/openai.js.map +1 -1
  36. package/build/embeddings/openai.test.js +3 -12
  37. package/build/embeddings/openai.test.js.map +1 -1
  38. package/build/embeddings/sparse.test.js +12 -2
  39. package/build/embeddings/sparse.test.js.map +1 -1
  40. package/build/embeddings/voyage.d.ts +1 -1
  41. package/build/embeddings/voyage.d.ts.map +1 -1
  42. package/build/embeddings/voyage.js +2 -3
  43. package/build/embeddings/voyage.js.map +1 -1
  44. package/build/embeddings/voyage.test.js +2 -6
  45. package/build/embeddings/voyage.test.js.map +1 -1
  46. package/build/git/chunker.d.ts.map +1 -1
  47. package/build/git/chunker.js +2 -2
  48. package/build/git/chunker.js.map +1 -1
  49. package/build/git/chunker.test.js +1 -1
  50. package/build/git/chunker.test.js.map +1 -1
  51. package/build/git/extractor.d.ts.map +1 -1
  52. package/build/git/extractor.integration.test.js +9 -5
  53. package/build/git/extractor.integration.test.js.map +1 -1
  54. package/build/git/extractor.js +1 -1
  55. package/build/git/extractor.js.map +1 -1
  56. package/build/git/extractor.test.js +2 -2
  57. package/build/git/extractor.test.js.map +1 -1
  58. package/build/git/index.d.ts +4 -4
  59. package/build/git/index.d.ts.map +1 -1
  60. package/build/git/index.js +3 -3
  61. package/build/git/index.js.map +1 -1
  62. package/build/git/indexer.d.ts.map +1 -1
  63. package/build/git/indexer.js +9 -21
  64. package/build/git/indexer.js.map +1 -1
  65. package/build/git/indexer.test.js +4 -8
  66. package/build/git/indexer.test.js.map +1 -1
  67. package/build/git/sync/synchronizer.d.ts.map +1 -1
  68. package/build/git/sync/synchronizer.js.map +1 -1
  69. package/build/git/sync/synchronizer.test.js +4 -2
  70. package/build/git/sync/synchronizer.test.js.map +1 -1
  71. package/build/index.js +5 -9
  72. package/build/index.js.map +1 -1
  73. package/build/index.test.js +3 -3
  74. package/build/index.test.js.map +1 -1
  75. package/build/logger.d.ts.map +1 -1
  76. package/build/logger.js +1 -9
  77. package/build/logger.js.map +1 -1
  78. package/build/prompts/register.d.ts.map +1 -1
  79. package/build/prompts/register.js.map +1 -1
  80. package/build/qdrant/client.d.ts.map +1 -1
  81. package/build/qdrant/client.js.map +1 -1
  82. package/build/qdrant/client.test.js +10 -34
  83. package/build/qdrant/client.test.js.map +1 -1
  84. package/build/resources/index.d.ts +1 -1
  85. package/build/resources/index.d.ts.map +1 -1
  86. package/build/resources/index.js +1 -1
  87. package/build/resources/index.js.map +1 -1
  88. package/build/tools/code.d.ts.map +1 -1
  89. package/build/tools/code.js +3 -9
  90. package/build/tools/code.js.map +1 -1
  91. package/build/tools/collection.d.ts.map +1 -1
  92. package/build/tools/collection.js +1 -3
  93. package/build/tools/collection.js.map +1 -1
  94. package/build/tools/document.d.ts.map +1 -1
  95. package/build/tools/document.js +1 -1
  96. package/build/tools/document.js.map +1 -1
  97. package/build/tools/federated.d.ts.map +1 -1
  98. package/build/tools/federated.js +15 -6
  99. package/build/tools/federated.js.map +1 -1
  100. package/build/tools/federated.test.js +18 -22
  101. package/build/tools/federated.test.js.map +1 -1
  102. package/build/tools/git-history.d.ts.map +1 -1
  103. package/build/tools/git-history.js +3 -7
  104. package/build/tools/git-history.js.map +1 -1
  105. package/build/tools/index.d.ts.map +1 -1
  106. package/build/tools/index.js.map +1 -1
  107. package/build/tools/logging.d.ts.map +1 -1
  108. package/build/tools/logging.js +1 -3
  109. package/build/tools/logging.js.map +1 -1
  110. package/build/tools/logging.test.js +1 -1
  111. package/build/tools/logging.test.js.map +1 -1
  112. package/build/tools/schemas.d.ts.map +1 -1
  113. package/build/tools/schemas.js +17 -64
  114. package/build/tools/schemas.js.map +1 -1
  115. package/build/tools/search.d.ts.map +1 -1
  116. package/build/tools/search.js +1 -1
  117. package/build/tools/search.js.map +1 -1
  118. package/commitlint.config.js +12 -23
  119. package/package.json +1 -1
  120. package/scripts/verify-providers.js +12 -32
  121. package/src/code/chunker/tree-sitter-chunker.ts +9 -35
  122. package/src/code/indexer.ts +45 -107
  123. package/src/code/scanner.ts +1 -1
  124. package/src/embeddings/cohere.test.ts +17 -45
  125. package/src/embeddings/cohere.ts +10 -17
  126. package/src/embeddings/factory.test.ts +18 -18
  127. package/src/embeddings/factory.ts +18 -25
  128. package/src/embeddings/ollama.test.ts +38 -67
  129. package/src/embeddings/ollama.ts +15 -27
  130. package/src/embeddings/openai.test.ts +17 -53
  131. package/src/embeddings/openai.ts +11 -22
  132. package/src/embeddings/sparse.test.ts +12 -2
  133. package/src/embeddings/voyage.test.ts +39 -80
  134. package/src/embeddings/voyage.ts +9 -13
  135. package/src/git/chunker.test.ts +1 -1
  136. package/src/git/chunker.ts +6 -22
  137. package/src/git/extractor.integration.test.ts +12 -16
  138. package/src/git/extractor.test.ts +21 -35
  139. package/src/git/extractor.ts +14 -36
  140. package/src/git/index.ts +9 -10
  141. package/src/git/indexer.test.ts +29 -57
  142. package/src/git/indexer.ts +38 -86
  143. package/src/git/sync/synchronizer.test.ts +6 -9
  144. package/src/git/sync/synchronizer.ts +2 -5
  145. package/src/index.test.ts +7 -9
  146. package/src/index.ts +34 -80
  147. package/src/logger.ts +3 -14
  148. package/src/prompts/register.ts +3 -10
  149. package/src/qdrant/client.test.ts +63 -169
  150. package/src/qdrant/client.ts +19 -45
  151. package/src/resources/index.ts +4 -10
  152. package/src/tools/code.ts +43 -66
  153. package/src/tools/collection.ts +19 -38
  154. package/src/tools/document.ts +10 -19
  155. package/src/tools/federated.test.ts +34 -57
  156. package/src/tools/federated.ts +88 -108
  157. package/src/tools/git-history.ts +32 -60
  158. package/src/tools/index.ts +1 -4
  159. package/src/tools/logging.test.ts +10 -10
  160. package/src/tools/logging.ts +8 -18
  161. package/src/tools/schemas.ts +23 -78
  162. package/src/tools/search.ts +77 -94
  163. package/tests/code/chunker/tree-sitter-chunker.test.ts +6 -19
  164. package/tests/code/indexer.test.ts +100 -192
  165. package/tests/code/integration.test.ts +61 -117
  166. package/tests/code/scanner.test.ts +12 -39
  167. package/tests/code/sync/snapshot.test.ts +4 -14
  168. package/tests/code/sync/synchronizer.test.ts +10 -40
@@ -32,7 +32,7 @@ class MockQdrantManager implements Partial<QdrantManager> {
32
32
  name: string,
33
33
  _vectorSize: number,
34
34
  _distance: "Cosine" | "Euclid" | "Dot" = "Cosine",
35
- _enableHybrid?: boolean,
35
+ _enableHybrid?: boolean
36
36
  ): Promise<void> {
37
37
  this.collections.set(name, {
38
38
  vectorSize: _vectorSize,
@@ -54,10 +54,7 @@ class MockQdrantManager implements Partial<QdrantManager> {
54
54
  this.points.set(collectionName, [...filtered, ...points]);
55
55
  }
56
56
 
57
- async addPointsWithSparse(
58
- collectionName: string,
59
- points: any[],
60
- ): Promise<void> {
57
+ async addPointsWithSparse(collectionName: string, points: any[]): Promise<void> {
61
58
  await this.addPoints(collectionName, points);
62
59
  }
63
60
 
@@ -65,7 +62,7 @@ class MockQdrantManager implements Partial<QdrantManager> {
65
62
  collectionName: string,
66
63
  _vector: number[],
67
64
  limit: number,
68
- _filter?: any,
65
+ _filter?: any
69
66
  ): Promise<any[]> {
70
67
  const points = this.points.get(collectionName) || [];
71
68
  return points.slice(0, limit).map((p, idx) => ({
@@ -80,7 +77,7 @@ class MockQdrantManager implements Partial<QdrantManager> {
80
77
  _vector: number[],
81
78
  _sparseVector: any,
82
79
  limit: number,
83
- _filter?: any,
80
+ _filter?: any
84
81
  ): Promise<any[]> {
85
82
  return this.search(collectionName, _vector, limit, _filter);
86
83
  }
@@ -97,7 +94,7 @@ class MockQdrantManager implements Partial<QdrantManager> {
97
94
 
98
95
  async getPoint(
99
96
  collectionName: string,
100
- id: string | number,
97
+ id: string | number
101
98
  ): Promise<{ id: string | number; payload?: Record<string, any> } | null> {
102
99
  const points = this.points.get(collectionName) || [];
103
100
  const point = points.find((p) => p.id === id);
@@ -110,16 +107,11 @@ class MockQdrantManager implements Partial<QdrantManager> {
110
107
  };
111
108
  }
112
109
 
113
- async deletePointsByFilter(
114
- collectionName: string,
115
- filter: Record<string, any>,
116
- ): Promise<void> {
110
+ async deletePointsByFilter(collectionName: string, filter: Record<string, any>): Promise<void> {
117
111
  const points = this.points.get(collectionName) || [];
118
112
  const pathToDelete = filter?.must?.[0]?.match?.value;
119
113
  if (pathToDelete) {
120
- const filtered = points.filter(
121
- (p) => p.payload?.relativePath !== pathToDelete,
122
- );
114
+ const filtered = points.filter((p) => p.payload?.relativePath !== pathToDelete);
123
115
  this.points.set(collectionName, filtered);
124
116
  }
125
117
  }
@@ -134,15 +126,11 @@ class MockEmbeddingProvider implements EmbeddingProvider {
134
126
  return "mock-model";
135
127
  }
136
128
 
137
- async embed(
138
- _text: string,
139
- ): Promise<{ embedding: number[]; dimensions: number }> {
129
+ async embed(_text: string): Promise<{ embedding: number[]; dimensions: number }> {
140
130
  return { embedding: new Array(384).fill(0.1), dimensions: 384 };
141
131
  }
142
132
 
143
- async embedBatch(
144
- texts: string[],
145
- ): Promise<Array<{ embedding: number[]; dimensions: number }>> {
133
+ async embedBatch(texts: string[]): Promise<Array<{ embedding: number[]; dimensions: number }>> {
146
134
  return texts.map(() => ({
147
135
  embedding: new Array(384).fill(0.1),
148
136
  dimensions: 384,
@@ -162,7 +150,7 @@ describe("CodeIndexer", () => {
162
150
  // Create temporary test directory
163
151
  tempDir = join(
164
152
  tmpdir(),
165
- `qdrant-mcp-test-${Date.now()}-${Math.random().toString(36).substring(7)}`,
153
+ `qdrant-mcp-test-${Date.now()}-${Math.random().toString(36).substring(7)}`
166
154
  );
167
155
  codebaseDir = join(tempDir, "codebase");
168
156
  await fs.mkdir(codebaseDir, { recursive: true });
@@ -197,7 +185,7 @@ describe("CodeIndexer", () => {
197
185
  await createTestFile(
198
186
  codebaseDir,
199
187
  "hello.ts",
200
- 'export function hello(name: string): string {\n console.log("Greeting user");\n return `Hello, ${name}!`;\n}',
188
+ 'export function hello(name: string): string {\n console.log("Greeting user");\n return `Hello, ${name}!`;\n}'
201
189
  );
202
190
 
203
191
  const stats = await indexer.indexCodebase(codebaseDir);
@@ -231,7 +219,7 @@ describe("CodeIndexer", () => {
231
219
  await createTestFile(
232
220
  codebaseDir,
233
221
  "test.ts",
234
- "export const configuration = {\n apiKey: process.env.API_KEY,\n timeout: 5000\n};",
222
+ "export const configuration = {\n apiKey: process.env.API_KEY,\n timeout: 5000\n};"
235
223
  );
236
224
 
237
225
  const createCollectionSpy = vi.spyOn(qdrant, "createCollection");
@@ -242,7 +230,7 @@ describe("CodeIndexer", () => {
242
230
  expect.stringContaining("code_"),
243
231
  384,
244
232
  "Cosine",
245
- false,
233
+ false
246
234
  );
247
235
  });
248
236
 
@@ -250,7 +238,7 @@ describe("CodeIndexer", () => {
250
238
  await createTestFile(
251
239
  codebaseDir,
252
240
  "test.ts",
253
- "export function calculateTotal(items: number[]): number {\n return items.reduce((sum, item) => sum + item, 0);\n}",
241
+ "export function calculateTotal(items: number[]): number {\n return items.reduce((sum, item) => sum + item, 0);\n}"
254
242
  );
255
243
 
256
244
  await indexer.indexCodebase(codebaseDir);
@@ -265,7 +253,7 @@ describe("CodeIndexer", () => {
265
253
  await createTestFile(
266
254
  codebaseDir,
267
255
  "test.ts",
268
- "export interface User {\n id: string;\n name: string;\n email: string;\n}",
256
+ "export interface User {\n id: string;\n name: string;\n email: string;\n}"
269
257
  );
270
258
 
271
259
  const progressCallback = vi.fn();
@@ -273,16 +261,8 @@ describe("CodeIndexer", () => {
273
261
  await indexer.indexCodebase(codebaseDir, undefined, progressCallback);
274
262
 
275
263
  expect(progressCallback).toHaveBeenCalled();
276
- expect(
277
- progressCallback.mock.calls.some(
278
- (call) => call[0].phase === "scanning",
279
- ),
280
- ).toBe(true);
281
- expect(
282
- progressCallback.mock.calls.some(
283
- (call) => call[0].phase === "chunking",
284
- ),
285
- ).toBe(true);
264
+ expect(progressCallback.mock.calls.some((call) => call[0].phase === "scanning")).toBe(true);
265
+ expect(progressCallback.mock.calls.some((call) => call[0].phase === "chunking")).toBe(true);
286
266
  });
287
267
 
288
268
  it("should respect custom extensions", async () => {
@@ -300,7 +280,7 @@ describe("CodeIndexer", () => {
300
280
  await createTestFile(
301
281
  codebaseDir,
302
282
  "secrets.ts",
303
- 'const apiKey = "sk_test_FAKE_KEY_FOR_TESTING_ONLY_NOT_REAL";',
283
+ 'const apiKey = "sk_test_FAKE_KEY_FOR_TESTING_ONLY_NOT_REAL";'
304
284
  );
305
285
 
306
286
  const stats = await indexer.indexCodebase(codebaseDir);
@@ -311,16 +291,12 @@ describe("CodeIndexer", () => {
311
291
 
312
292
  it("should enable hybrid search when configured", async () => {
313
293
  const hybridConfig = { ...config, enableHybridSearch: true };
314
- const hybridIndexer = new CodeIndexer(
315
- qdrant as any,
316
- embeddings,
317
- hybridConfig,
318
- );
294
+ const hybridIndexer = new CodeIndexer(qdrant as any, embeddings, hybridConfig);
319
295
 
320
296
  await createTestFile(
321
297
  codebaseDir,
322
298
  "test.ts",
323
- "export class DataService {\n async fetchData(): Promise<any[]> {\n return [];\n }\n}",
299
+ "export class DataService {\n async fetchData(): Promise<any[]> {\n return [];\n }\n}"
324
300
  );
325
301
 
326
302
  const createCollectionSpy = vi.spyOn(qdrant, "createCollection");
@@ -331,7 +307,7 @@ describe("CodeIndexer", () => {
331
307
  expect.stringContaining("code_"),
332
308
  384,
333
309
  "Cosine",
334
- true,
310
+ true
335
311
  );
336
312
  });
337
313
 
@@ -340,20 +316,16 @@ describe("CodeIndexer", () => {
340
316
 
341
317
  // Mock fs.readFile to throw error for this specific file
342
318
  const originalReadFile = fs.readFile;
343
- vi.spyOn(fs, "readFile").mockImplementation(
344
- async (path: any, ...args: any[]) => {
345
- if (path.includes("test.ts")) {
346
- throw new Error("Permission denied");
347
- }
348
- return originalReadFile(path, ...args);
349
- },
350
- );
319
+ vi.spyOn(fs, "readFile").mockImplementation(async (path: any, ...args: any[]) => {
320
+ if (path.includes("test.ts")) {
321
+ throw new Error("Permission denied");
322
+ }
323
+ return originalReadFile(path, ...args);
324
+ });
351
325
 
352
326
  const stats = await indexer.indexCodebase(codebaseDir);
353
327
 
354
- expect(stats.errors?.some((e) => e.includes("Permission denied"))).toBe(
355
- true,
356
- );
328
+ expect(stats.errors?.some((e) => e.includes("Permission denied"))).toBe(true);
357
329
 
358
330
  vi.restoreAllMocks();
359
331
  });
@@ -364,7 +336,7 @@ describe("CodeIndexer", () => {
364
336
  await createTestFile(
365
337
  codebaseDir,
366
338
  `file${i}.ts`,
367
- `export function test${i}() {\n console.log('Test function ${i}');\n return ${i};\n}`,
339
+ `export function test${i}() {\n console.log('Test function ${i}');\n return ${i};\n}`
368
340
  );
369
341
  }
370
342
 
@@ -381,7 +353,7 @@ describe("CodeIndexer", () => {
381
353
  await createTestFile(
382
354
  codebaseDir,
383
355
  "test.ts",
384
- "export function hello(name: string): string {\n const greeting = `Hello, ${name}!`;\n return greeting;\n}",
356
+ "export function hello(name: string): string {\n const greeting = `Hello, ${name}!`;\n return greeting;\n}"
385
357
  );
386
358
  await indexer.indexCodebase(codebaseDir);
387
359
  });
@@ -397,9 +369,7 @@ describe("CodeIndexer", () => {
397
369
  const nonIndexedDir = join(tempDir, "non-indexed");
398
370
  await fs.mkdir(nonIndexedDir, { recursive: true });
399
371
 
400
- await expect(indexer.searchCode(nonIndexedDir, "test")).rejects.toThrow(
401
- "not indexed",
402
- );
372
+ await expect(indexer.searchCode(nonIndexedDir, "test")).rejects.toThrow("not indexed");
403
373
  });
404
374
 
405
375
  it("should respect limit option", async () => {
@@ -434,11 +404,7 @@ describe("CodeIndexer", () => {
434
404
 
435
405
  it("should use hybrid search when enabled", async () => {
436
406
  const hybridConfig = { ...config, enableHybridSearch: true };
437
- const hybridIndexer = new CodeIndexer(
438
- qdrant as any,
439
- embeddings,
440
- hybridConfig,
441
- );
407
+ const hybridIndexer = new CodeIndexer(qdrant as any, embeddings, hybridConfig);
442
408
 
443
409
  await createTestFile(
444
410
  codebaseDir,
@@ -455,7 +421,7 @@ function performValidation(): boolean {
455
421
  }
456
422
  function checkStatus(): boolean {
457
423
  return true;
458
- }`,
424
+ }`
459
425
  );
460
426
  // Force reindex to recreate collection with hybrid search enabled
461
427
  await hybridIndexer.indexCodebase(codebaseDir, { forceReindex: true });
@@ -487,12 +453,12 @@ function checkStatus(): boolean {
487
453
  await createTestFile(
488
454
  join(codebaseDir, "src", "services"),
489
455
  "auth.ts",
490
- "export function authenticate() { return true; }",
456
+ "export function authenticate() { return true; }"
491
457
  );
492
458
  await createTestFile(
493
459
  join(codebaseDir, "src", "utils"),
494
460
  "helpers.ts",
495
- "export function authenticate() { return false; }",
461
+ "export function authenticate() { return false; }"
496
462
  );
497
463
  await indexer.indexCodebase(codebaseDir, { forceReindex: true });
498
464
 
@@ -519,11 +485,7 @@ function checkStatus(): boolean {
519
485
 
520
486
  it("should combine pathPattern with fileTypes filter", async () => {
521
487
  await fs.mkdir(join(codebaseDir, "src"), { recursive: true });
522
- await createTestFile(
523
- join(codebaseDir, "src"),
524
- "code.ts",
525
- "export const x = 1;",
526
- );
488
+ await createTestFile(join(codebaseDir, "src"), "code.ts", "export const x = 1;");
527
489
  await createTestFile(join(codebaseDir, "src"), "code.py", "x = 1");
528
490
  await indexer.indexCodebase(codebaseDir, { forceReindex: true });
529
491
 
@@ -575,7 +537,7 @@ function checkStatus(): boolean {
575
537
  await createTestFile(
576
538
  codebaseDir,
577
539
  "test.ts",
578
- "export const APP_CONFIG = {\n port: 3000,\n host: 'localhost',\n debug: true,\n apiUrl: 'https://api.example.com',\n timeout: 5000\n};\nconsole.log('Config loaded');",
540
+ "export const APP_CONFIG = {\n port: 3000,\n host: 'localhost',\n debug: true,\n apiUrl: 'https://api.example.com',\n timeout: 5000\n};\nconsole.log('Config loaded');"
579
541
  );
580
542
  await indexer.indexCodebase(codebaseDir);
581
543
 
@@ -591,7 +553,7 @@ function checkStatus(): boolean {
591
553
  await createTestFile(
592
554
  codebaseDir,
593
555
  "test.ts",
594
- "export const value = 1;\nconsole.log('Testing timestamp');\nfunction test() { return value; }",
556
+ "export const value = 1;\nconsole.log('Testing timestamp');\nfunction test() { return value; }"
595
557
  );
596
558
 
597
559
  const beforeIndexing = new Date();
@@ -603,19 +565,15 @@ function checkStatus(): boolean {
603
565
  expect(status.status).toBe("indexed");
604
566
  expect(status.lastUpdated).toBeDefined();
605
567
  expect(status.lastUpdated).toBeInstanceOf(Date);
606
- expect(status.lastUpdated!.getTime()).toBeGreaterThanOrEqual(
607
- beforeIndexing.getTime(),
608
- );
609
- expect(status.lastUpdated!.getTime()).toBeLessThanOrEqual(
610
- afterIndexing.getTime(),
611
- );
568
+ expect(status.lastUpdated?.getTime()).toBeGreaterThanOrEqual(beforeIndexing.getTime());
569
+ expect(status.lastUpdated?.getTime()).toBeLessThanOrEqual(afterIndexing.getTime());
612
570
  });
613
571
 
614
572
  it("should return correct chunks count excluding metadata point", async () => {
615
573
  await createTestFile(
616
574
  codebaseDir,
617
575
  "test.ts",
618
- "export const a = 1;\nexport const b = 2;\nconsole.log('File with content');\nfunction helper() { return a + b; }",
576
+ "export const a = 1;\nexport const b = 2;\nconsole.log('File with content');\nfunction helper() { return a + b; }"
619
577
  );
620
578
  await indexer.indexCodebase(codebaseDir);
621
579
 
@@ -633,7 +591,7 @@ function checkStatus(): boolean {
633
591
  await createTestFile(
634
592
  codebaseDir,
635
593
  "test.ts",
636
- "export const data = { key: 'value' };\nconsole.log('Completion marker test');\nfunction process() { return data; }",
594
+ "export const data = { key: 'value' };\nconsole.log('Completion marker test');\nfunction process() { return data; }"
637
595
  );
638
596
  await indexer.indexCodebase(codebaseDir);
639
597
 
@@ -660,7 +618,7 @@ function checkStatus(): boolean {
660
618
  await createTestFile(
661
619
  codebaseDir,
662
620
  "test.ts",
663
- "export const v1 = 'first';\nconsole.log('First indexing');\nfunction init() { return v1; }",
621
+ "export const v1 = 'first';\nconsole.log('First indexing');\nfunction init() { return v1; }"
664
622
  );
665
623
 
666
624
  await indexer.indexCodebase(codebaseDir);
@@ -691,7 +649,7 @@ function checkStatus(): boolean {
691
649
  await createTestFile(
692
650
  codebaseDir,
693
651
  "test.ts",
694
- "export const test = true;\nconsole.log('Backwards compat test');\nfunction run() { return test; }",
652
+ "export const test = true;\nconsole.log('Backwards compat test');\nfunction run() { return test; }"
695
653
  );
696
654
  await indexer.indexCodebase(codebaseDir);
697
655
 
@@ -704,7 +662,7 @@ function checkStatus(): boolean {
704
662
  await createTestFile(
705
663
  codebaseDir,
706
664
  "test.ts",
707
- "export const consistency = 1;\nconsole.log('Consistency check');\nfunction check() { return consistency; }",
665
+ "export const consistency = 1;\nconsole.log('Consistency check');\nfunction check() { return consistency; }"
708
666
  );
709
667
  await indexer.indexCodebase(codebaseDir);
710
668
 
@@ -726,26 +684,19 @@ function checkStatus(): boolean {
726
684
  await createTestFile(
727
685
  codebaseDir,
728
686
  `file${i}.ts`,
729
- `export const value${i} = ${i};\nconsole.log('Processing file ${i}');\nfunction process${i}(x: number) {\n const result = x * ${i};\n console.log('Result:', result);\n return result;\n}`,
687
+ `export const value${i} = ${i};\nconsole.log('Processing file ${i}');\nfunction process${i}(x: number) {\n const result = x * ${i};\n console.log('Result:', result);\n return result;\n}`
730
688
  );
731
689
  }
732
690
 
733
691
  let statusDuringIndexing: any = null;
734
692
 
735
693
  // Use progress callback to check status mid-indexing
736
- const indexingPromise = indexer.indexCodebase(
737
- codebaseDir,
738
- undefined,
739
- async (progress) => {
740
- // Check status during the embedding phase (when we know indexing is in progress)
741
- if (
742
- progress.phase === "embedding" &&
743
- statusDuringIndexing === null
744
- ) {
745
- statusDuringIndexing = await indexer.getIndexStatus(codebaseDir);
746
- }
747
- },
748
- );
694
+ const indexingPromise = indexer.indexCodebase(codebaseDir, undefined, async (progress) => {
695
+ // Check status during the embedding phase (when we know indexing is in progress)
696
+ if (progress.phase === "embedding" && statusDuringIndexing === null) {
697
+ statusDuringIndexing = await indexer.getIndexStatus(codebaseDir);
698
+ }
699
+ });
749
700
 
750
701
  await indexingPromise;
751
702
 
@@ -767,25 +718,18 @@ function checkStatus(): boolean {
767
718
  await createTestFile(
768
719
  codebaseDir,
769
720
  `module${i}.ts`,
770
- `export class Module${i} {\n constructor() {\n console.log('Module ${i} initialized');\n }\n process(data: string): string {\n return data.toUpperCase();\n }\n}`,
721
+ `export class Module${i} {\n constructor() {\n console.log('Module ${i} initialized');\n }\n process(data: string): string {\n return data.toUpperCase();\n }\n}`
771
722
  );
772
723
  }
773
724
 
774
725
  let chunksCountDuringIndexing: number | undefined;
775
726
 
776
- await indexer.indexCodebase(
777
- codebaseDir,
778
- undefined,
779
- async (progress) => {
780
- if (
781
- progress.phase === "storing" &&
782
- chunksCountDuringIndexing === undefined
783
- ) {
784
- const status = await indexer.getIndexStatus(codebaseDir);
785
- chunksCountDuringIndexing = status.chunksCount;
786
- }
787
- },
788
- );
727
+ await indexer.indexCodebase(codebaseDir, undefined, async (progress) => {
728
+ if (progress.phase === "storing" && chunksCountDuringIndexing === undefined) {
729
+ const status = await indexer.getIndexStatus(codebaseDir);
730
+ chunksCountDuringIndexing = status.chunksCount;
731
+ }
732
+ });
789
733
 
790
734
  // chunksCount during indexing should be a number (could be 0 or more depending on progress)
791
735
  if (chunksCountDuringIndexing !== undefined) {
@@ -802,7 +746,7 @@ function checkStatus(): boolean {
802
746
  await createTestFile(
803
747
  codebaseDir,
804
748
  "legacy.ts",
805
- "export const legacy = true;\nconsole.log('Legacy test');\nfunction legacyFn() { return legacy; }",
749
+ "export const legacy = true;\nconsole.log('Legacy test');\nfunction legacyFn() { return legacy; }"
806
750
  );
807
751
  await indexer.indexCodebase(codebaseDir);
808
752
 
@@ -820,9 +764,7 @@ function checkStatus(): boolean {
820
764
 
821
765
  describe("reindexChanges", () => {
822
766
  it("should throw error if not previously indexed", async () => {
823
- await expect(indexer.reindexChanges(codebaseDir)).rejects.toThrow(
824
- "not indexed",
825
- );
767
+ await expect(indexer.reindexChanges(codebaseDir)).rejects.toThrow("not indexed");
826
768
  });
827
769
 
828
770
  it("should detect and index new files", async () => {
@@ -834,7 +776,7 @@ console.log('Initial file created');
834
776
  function helper(param: string): boolean {
835
777
  console.log('Processing:', param);
836
778
  return true;
837
- }`,
779
+ }`
838
780
  );
839
781
  await indexer.indexCodebase(codebaseDir);
840
782
 
@@ -861,7 +803,7 @@ function helper(param: string): boolean {
861
803
  " console.log('Valid input');",
862
804
  " return input.length > 5;",
863
805
  "}",
864
- ].join("\n"),
806
+ ].join("\n")
865
807
  );
866
808
 
867
809
  const stats = await indexer.reindexChanges(codebaseDir);
@@ -874,14 +816,14 @@ function helper(param: string): boolean {
874
816
  await createTestFile(
875
817
  codebaseDir,
876
818
  "test.ts",
877
- "export const originalValue = 1;\nconsole.log('Original');",
819
+ "export const originalValue = 1;\nconsole.log('Original');"
878
820
  );
879
821
  await indexer.indexCodebase(codebaseDir);
880
822
 
881
823
  await createTestFile(
882
824
  codebaseDir,
883
825
  "test.ts",
884
- "export const updatedValue = 2;\nconsole.log('Updated');",
826
+ "export const updatedValue = 2;\nconsole.log('Updated');"
885
827
  );
886
828
 
887
829
  const stats = await indexer.reindexChanges(codebaseDir);
@@ -893,7 +835,7 @@ function helper(param: string): boolean {
893
835
  await createTestFile(
894
836
  codebaseDir,
895
837
  "test.ts",
896
- "export const toBeDeleted = 1;\nconsole.log('Will be deleted');",
838
+ "export const toBeDeleted = 1;\nconsole.log('Will be deleted');"
897
839
  );
898
840
  await indexer.indexCodebase(codebaseDir);
899
841
 
@@ -908,7 +850,7 @@ function helper(param: string): boolean {
908
850
  await createTestFile(
909
851
  codebaseDir,
910
852
  "test.ts",
911
- "export const unchangedValue = 1;\nconsole.log('No changes');",
853
+ "export const unchangedValue = 1;\nconsole.log('No changes');"
912
854
  );
913
855
  await indexer.indexCodebase(codebaseDir);
914
856
 
@@ -923,14 +865,14 @@ function helper(param: string): boolean {
923
865
  await createTestFile(
924
866
  codebaseDir,
925
867
  "test.ts",
926
- "export const existingValue = 1;\nconsole.log('Existing');",
868
+ "export const existingValue = 1;\nconsole.log('Existing');"
927
869
  );
928
870
  await indexer.indexCodebase(codebaseDir);
929
871
 
930
872
  await createTestFile(
931
873
  codebaseDir,
932
874
  "new.ts",
933
- "export const newValue = 2;\nconsole.log('New file');",
875
+ "export const newValue = 2;\nconsole.log('New file');"
934
876
  );
935
877
 
936
878
  const progressCallback = vi.fn();
@@ -943,7 +885,7 @@ function helper(param: string): boolean {
943
885
  await createTestFile(
944
886
  codebaseDir,
945
887
  "test.ts",
946
- "export const originalValue = 1;\nconsole.log('Original version');",
888
+ "export const originalValue = 1;\nconsole.log('Original version');"
947
889
  );
948
890
  await indexer.indexCodebase(codebaseDir);
949
891
 
@@ -952,24 +894,21 @@ function helper(param: string): boolean {
952
894
  await createTestFile(
953
895
  codebaseDir,
954
896
  "test.ts",
955
- "export const modifiedValue = 2;\nconsole.log('Modified version');",
897
+ "export const modifiedValue = 2;\nconsole.log('Modified version');"
956
898
  );
957
899
 
958
900
  await indexer.reindexChanges(codebaseDir);
959
901
 
960
- expect(deletePointsByFilterSpy).toHaveBeenCalledWith(
961
- expect.stringContaining("code_"),
962
- {
963
- must: [{ key: "relativePath", match: { value: "test.ts" } }],
964
- },
965
- );
902
+ expect(deletePointsByFilterSpy).toHaveBeenCalledWith(expect.stringContaining("code_"), {
903
+ must: [{ key: "relativePath", match: { value: "test.ts" } }],
904
+ });
966
905
  });
967
906
 
968
907
  it("should delete all chunks when file is deleted", async () => {
969
908
  await createTestFile(
970
909
  codebaseDir,
971
910
  "test.ts",
972
- "export const toDelete = 1;\nconsole.log('Will be deleted');",
911
+ "export const toDelete = 1;\nconsole.log('Will be deleted');"
973
912
  );
974
913
  await indexer.indexCodebase(codebaseDir);
975
914
 
@@ -979,24 +918,21 @@ function helper(param: string): boolean {
979
918
 
980
919
  await indexer.reindexChanges(codebaseDir);
981
920
 
982
- expect(deletePointsByFilterSpy).toHaveBeenCalledWith(
983
- expect.stringContaining("code_"),
984
- {
985
- must: [{ key: "relativePath", match: { value: "test.ts" } }],
986
- },
987
- );
921
+ expect(deletePointsByFilterSpy).toHaveBeenCalledWith(expect.stringContaining("code_"), {
922
+ must: [{ key: "relativePath", match: { value: "test.ts" } }],
923
+ });
988
924
  });
989
925
 
990
926
  it("should not affect chunks from unchanged files", async () => {
991
927
  await createTestFile(
992
928
  codebaseDir,
993
929
  "unchanged.ts",
994
- "export const unchanged = 1;\nconsole.log('Unchanged');",
930
+ "export const unchanged = 1;\nconsole.log('Unchanged');"
995
931
  );
996
932
  await createTestFile(
997
933
  codebaseDir,
998
934
  "changed.ts",
999
- "export const original = 2;\nconsole.log('Original');",
935
+ "export const original = 2;\nconsole.log('Original');"
1000
936
  );
1001
937
  await indexer.indexCodebase(codebaseDir);
1002
938
 
@@ -1005,26 +941,23 @@ function helper(param: string): boolean {
1005
941
  await createTestFile(
1006
942
  codebaseDir,
1007
943
  "changed.ts",
1008
- "export const modified = 3;\nconsole.log('Modified');",
944
+ "export const modified = 3;\nconsole.log('Modified');"
1009
945
  );
1010
946
 
1011
947
  await indexer.reindexChanges(codebaseDir);
1012
948
 
1013
949
  // Should only delete chunks for changed.ts, not unchanged.ts
1014
950
  expect(deletePointsByFilterSpy).toHaveBeenCalledTimes(1);
1015
- expect(deletePointsByFilterSpy).toHaveBeenCalledWith(
1016
- expect.stringContaining("code_"),
1017
- {
1018
- must: [{ key: "relativePath", match: { value: "changed.ts" } }],
1019
- },
1020
- );
951
+ expect(deletePointsByFilterSpy).toHaveBeenCalledWith(expect.stringContaining("code_"), {
952
+ must: [{ key: "relativePath", match: { value: "changed.ts" } }],
953
+ });
1021
954
  });
1022
955
 
1023
956
  it("should handle deletion errors gracefully", async () => {
1024
957
  await createTestFile(
1025
958
  codebaseDir,
1026
959
  "test.ts",
1027
- "export const original = 1;\nconsole.log('Original');",
960
+ "export const original = 1;\nconsole.log('Original');"
1028
961
  );
1029
962
  await indexer.indexCodebase(codebaseDir);
1030
963
 
@@ -1036,7 +969,7 @@ function helper(param: string): boolean {
1036
969
  await createTestFile(
1037
970
  codebaseDir,
1038
971
  "test.ts",
1039
- "export const modified = 2;\nconsole.log('Modified');",
972
+ "export const modified = 2;\nconsole.log('Modified');"
1040
973
  );
1041
974
 
1042
975
  // Should not throw, should continue with reindexing
@@ -1073,7 +1006,7 @@ function helper(param: string): boolean {
1073
1006
  await createTestFile(
1074
1007
  codebaseDir,
1075
1008
  "test.ts",
1076
- "export const configValue = 1;\nconsole.log('Config loaded');",
1009
+ "export const configValue = 1;\nconsole.log('Config loaded');"
1077
1010
  );
1078
1011
  await indexer.indexCodebase(codebaseDir);
1079
1012
 
@@ -1091,7 +1024,7 @@ function helper(param: string): boolean {
1091
1024
  await createTestFile(
1092
1025
  codebaseDir,
1093
1026
  "test.ts",
1094
- "export const reindexValue = 1;\nconsole.log('Reindexing');",
1027
+ "export const reindexValue = 1;\nconsole.log('Reindexing');"
1095
1028
  );
1096
1029
  await indexer.indexCodebase(codebaseDir);
1097
1030
 
@@ -1116,7 +1049,7 @@ function helper(param: string): boolean {
1116
1049
  console.log('Button clicked');
1117
1050
  };
1118
1051
  return '<button>Click me</button>';
1119
- }`,
1052
+ }`
1120
1053
  );
1121
1054
 
1122
1055
  const stats = await indexer.indexCodebase(codebaseDir);
@@ -1125,11 +1058,7 @@ function helper(param: string): boolean {
1125
1058
  });
1126
1059
 
1127
1060
  it("should handle files with unicode content", async () => {
1128
- await createTestFile(
1129
- codebaseDir,
1130
- "test.ts",
1131
- "const greeting = '你好世界';",
1132
- );
1061
+ await createTestFile(codebaseDir, "test.ts", "const greeting = '你好世界';");
1133
1062
 
1134
1063
  const stats = await indexer.indexCodebase(codebaseDir);
1135
1064
 
@@ -1182,19 +1111,12 @@ function helper(param: string): boolean {
1182
1111
  ...config,
1183
1112
  maxChunksPerFile: 2,
1184
1113
  };
1185
- const limitedIndexer = new CodeIndexer(
1186
- qdrant as any,
1187
- embeddings,
1188
- limitedConfig,
1189
- );
1114
+ const limitedIndexer = new CodeIndexer(qdrant as any, embeddings, limitedConfig);
1190
1115
 
1191
1116
  // Create a large file that would generate many chunks
1192
1117
  const largeContent = Array(50)
1193
1118
  .fill(null)
1194
- .map(
1195
- (_, i) =>
1196
- `function test${i}() { console.log('test ${i}'); return ${i}; }`,
1197
- )
1119
+ .map((_, i) => `function test${i}() { console.log('test ${i}'); return ${i}; }`)
1198
1120
  .join("\n\n");
1199
1121
 
1200
1122
  await createTestFile(codebaseDir, "large.ts", largeContent);
@@ -1211,18 +1133,14 @@ function helper(param: string): boolean {
1211
1133
  ...config,
1212
1134
  maxTotalChunks: 3,
1213
1135
  };
1214
- const limitedIndexer = new CodeIndexer(
1215
- qdrant as any,
1216
- embeddings,
1217
- limitedConfig,
1218
- );
1136
+ const limitedIndexer = new CodeIndexer(qdrant as any, embeddings, limitedConfig);
1219
1137
 
1220
1138
  // Create multiple files
1221
1139
  for (let i = 0; i < 10; i++) {
1222
1140
  await createTestFile(
1223
1141
  codebaseDir,
1224
1142
  `file${i}.ts`,
1225
- `export function func${i}() { console.log('function ${i}'); return ${i}; }`,
1143
+ `export function func${i}() { console.log('function ${i}'); return ${i}; }`
1226
1144
  );
1227
1145
  }
1228
1146
 
@@ -1238,11 +1156,7 @@ function helper(param: string): boolean {
1238
1156
  ...config,
1239
1157
  maxTotalChunks: 1,
1240
1158
  };
1241
- const limitedIndexer = new CodeIndexer(
1242
- qdrant as any,
1243
- embeddings,
1244
- limitedConfig,
1245
- );
1159
+ const limitedIndexer = new CodeIndexer(qdrant as any, embeddings, limitedConfig);
1246
1160
 
1247
1161
  // Create a file with multiple chunks
1248
1162
  const content = `
@@ -1277,7 +1191,7 @@ function third() {
1277
1191
  await createTestFile(
1278
1192
  codebaseDir,
1279
1193
  "file1.ts",
1280
- "export const initial = 1;\nconsole.log('Initial');",
1194
+ "export const initial = 1;\nconsole.log('Initial');"
1281
1195
  );
1282
1196
  await indexer.indexCodebase(codebaseDir);
1283
1197
 
@@ -1291,7 +1205,7 @@ console.log('Added file');
1291
1205
  export function process() {
1292
1206
  console.log('Processing');
1293
1207
  return true;
1294
- }`,
1208
+ }`
1295
1209
  );
1296
1210
 
1297
1211
  const progressUpdates: string[] = [];
@@ -1319,11 +1233,7 @@ export function process() {
1319
1233
  // @ts-expect-error - Mocking for test
1320
1234
  fs.readFile = async (path: any, encoding: any) => {
1321
1235
  callCount++;
1322
- if (
1323
- callCount === 1 &&
1324
- typeof path === "string" &&
1325
- path.endsWith("test.ts")
1326
- ) {
1236
+ if (callCount === 1 && typeof path === "string" && path.endsWith("test.ts")) {
1327
1237
  // Throw a non-Error object
1328
1238
  throw "String error";
1329
1239
  }
@@ -1335,9 +1245,7 @@ export function process() {
1335
1245
 
1336
1246
  // Should handle the error gracefully
1337
1247
  expect(stats.status).toBe("completed");
1338
- expect(stats.errors?.some((e) => e.includes("String error"))).toBe(
1339
- true,
1340
- );
1248
+ expect(stats.errors?.some((e) => e.includes("String error"))).toBe(true);
1341
1249
  } finally {
1342
1250
  // Restore original function
1343
1251
  fs.readFile = originalReadFile;
@@ -1350,7 +1258,7 @@ export function process() {
1350
1258
  async function createTestFile(
1351
1259
  baseDir: string,
1352
1260
  relativePath: string,
1353
- content: string,
1261
+ content: string
1354
1262
  ): Promise<void> {
1355
1263
  const fullPath = join(baseDir, relativePath);
1356
1264
  const dir = join(fullPath, "..");