@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
@@ -3,12 +3,12 @@
3
3
  * These tests run against real git repositories (not mocked)
4
4
  */
5
5
 
6
- import { describe, it, expect, beforeAll } from "vitest";
7
- import { GitExtractor } from "./extractor.js";
8
- import { DEFAULT_GIT_CONFIG } from "./config.js";
9
- import type { GitConfig } from "./types.js";
10
6
  import { execFile } from "node:child_process";
11
7
  import { promisify } from "node:util";
8
+ import { beforeAll, describe, expect, it } from "vitest";
9
+ import { DEFAULT_GIT_CONFIG } from "./config.js";
10
+ import { GitExtractor } from "./extractor.js";
11
+ import type { GitConfig } from "./types.js";
12
12
 
13
13
  const execFileAsync = promisify(execFile);
14
14
 
@@ -93,11 +93,9 @@ describe("GitExtractor Integration Tests", () => {
93
93
 
94
94
  it("should return correct commit count matching git rev-list", async () => {
95
95
  // Get expected count from git directly
96
- const { stdout } = await execFileAsync(
97
- "git",
98
- ["rev-list", "--count", "-n", "50", "HEAD"],
99
- { cwd: repoPath },
100
- );
96
+ const { stdout } = await execFileAsync("git", ["rev-list", "--count", "-n", "50", "HEAD"], {
97
+ cwd: repoPath,
98
+ });
101
99
  const expectedCount = Math.min(parseInt(stdout.trim(), 10), 50);
102
100
 
103
101
  // Get commits via extractor
@@ -112,7 +110,7 @@ describe("GitExtractor Integration Tests", () => {
112
110
  const { stdout: logOutput } = await execFileAsync(
113
111
  "git",
114
112
  ["log", "--oneline", "--shortstat", "-n", "10", "HEAD"],
115
- { cwd: repoPath },
113
+ { cwd: repoPath }
116
114
  );
117
115
 
118
116
  // If there are commits with files changed, verify our extractor gets them
@@ -199,11 +197,9 @@ describe("GitExtractor Integration Tests", () => {
199
197
  const count = await extractor.getCommitCount();
200
198
 
201
199
  // Verify against git rev-list
202
- const { stdout } = await execFileAsync(
203
- "git",
204
- ["rev-list", "--count", "HEAD"],
205
- { cwd: repoPath },
206
- );
200
+ const { stdout } = await execFileAsync("git", ["rev-list", "--count", "HEAD"], {
201
+ cwd: repoPath,
202
+ });
207
203
  expect(count).toBe(parseInt(stdout.trim(), 10));
208
204
  });
209
205
 
@@ -218,7 +214,7 @@ describe("GitExtractor Integration Tests", () => {
218
214
  const { stdout } = await execFileAsync(
219
215
  "git",
220
216
  ["rev-list", "--count", `${sinceHash}..HEAD`],
221
- { cwd: repoPath },
217
+ { cwd: repoPath }
222
218
  );
223
219
  expect(count).toBe(parseInt(stdout.trim(), 10));
224
220
  }
@@ -1,6 +1,6 @@
1
- import { describe, it, expect, vi, beforeEach } from "vitest";
2
- import { GitExtractor, normalizeRemoteUrl } from "./extractor.js";
1
+ import { beforeEach, describe, expect, it, vi } from "vitest";
3
2
  import { DEFAULT_GIT_CONFIG, GIT_LOG_COMMIT_DELIMITER } from "./config.js";
3
+ import { GitExtractor, normalizeRemoteUrl } from "./extractor.js";
4
4
  import type { GitConfig } from "./types.js";
5
5
 
6
6
  // Mock child_process with promisify-compatible execFile
@@ -35,7 +35,7 @@ describe("GitExtractor", () => {
35
35
  expect(mockExecFile).toHaveBeenCalledWith(
36
36
  "git",
37
37
  ["rev-parse", "--git-dir"],
38
- expect.objectContaining({ cwd: "/test/repo" }),
38
+ expect.objectContaining({ cwd: "/test/repo" })
39
39
  );
40
40
  });
41
41
 
@@ -61,7 +61,7 @@ describe("GitExtractor", () => {
61
61
  expect(mockExecFile).toHaveBeenCalledWith(
62
62
  "git",
63
63
  ["rev-parse", "HEAD"],
64
- expect.objectContaining({ cwd: "/test/repo" }),
64
+ expect.objectContaining({ cwd: "/test/repo" })
65
65
  );
66
66
  });
67
67
  });
@@ -76,7 +76,7 @@ describe("GitExtractor", () => {
76
76
  expect(mockExecFile).toHaveBeenCalledWith(
77
77
  "git",
78
78
  ["rev-list", "--count", "HEAD"],
79
- expect.objectContaining({ cwd: "/test/repo" }),
79
+ expect.objectContaining({ cwd: "/test/repo" })
80
80
  );
81
81
  });
82
82
 
@@ -89,7 +89,7 @@ describe("GitExtractor", () => {
89
89
  expect(mockExecFile).toHaveBeenCalledWith(
90
90
  "git",
91
91
  ["rev-list", "--count", "abc123..HEAD"],
92
- expect.objectContaining({ cwd: "/test/repo" }),
92
+ expect.objectContaining({ cwd: "/test/repo" })
93
93
  );
94
94
  });
95
95
  });
@@ -202,7 +202,7 @@ describe("GitExtractor", () => {
202
202
  expect(mockExecFile).toHaveBeenCalledWith(
203
203
  "git",
204
204
  expect.arrayContaining(["-n100"]),
205
- expect.any(Object),
205
+ expect.any(Object)
206
206
  );
207
207
  });
208
208
 
@@ -214,7 +214,7 @@ describe("GitExtractor", () => {
214
214
  expect(mockExecFile).toHaveBeenCalledWith(
215
215
  "git",
216
216
  expect.arrayContaining(["abc123..HEAD"]),
217
- expect.any(Object),
217
+ expect.any(Object)
218
218
  );
219
219
  });
220
220
 
@@ -226,7 +226,7 @@ describe("GitExtractor", () => {
226
226
  expect(mockExecFile).toHaveBeenCalledWith(
227
227
  "git",
228
228
  expect.arrayContaining(["--since=2024-01-01"]),
229
- expect.any(Object),
229
+ expect.any(Object)
230
230
  );
231
231
  });
232
232
 
@@ -287,7 +287,7 @@ diff --git a/file.ts b/file.ts
287
287
  expect(mockExecFile).toHaveBeenCalledWith(
288
288
  "git",
289
289
  ["show", "--no-color", "-p", "abc123"],
290
- expect.objectContaining({ cwd: "/test/repo" }),
290
+ expect.objectContaining({ cwd: "/test/repo" })
291
291
  );
292
292
  });
293
293
 
@@ -326,14 +326,12 @@ diff --git a/file.ts b/file.ts
326
326
  expect(mockExecFile).toHaveBeenCalledWith(
327
327
  "git",
328
328
  ["remote", "get-url", "origin"],
329
- expect.objectContaining({ cwd: "/test/repo" }),
329
+ expect.objectContaining({ cwd: "/test/repo" })
330
330
  );
331
331
  });
332
332
 
333
333
  it("should return empty string when no remote configured", async () => {
334
- mockExecFile.mockRejectedValue(
335
- new Error("fatal: No such remote 'origin'"),
336
- );
334
+ mockExecFile.mockRejectedValue(new Error("fatal: No such remote 'origin'"));
337
335
 
338
336
  const result = await extractor.getRemoteUrl();
339
337
 
@@ -355,22 +353,16 @@ diff --git a/file.ts b/file.ts
355
353
 
356
354
  describe("normalizeRemoteUrl", () => {
357
355
  it("should normalize SSH URL", () => {
358
- expect(normalizeRemoteUrl("git@github.com:user/repo.git")).toBe(
359
- "user/repo",
360
- );
356
+ expect(normalizeRemoteUrl("git@github.com:user/repo.git")).toBe("user/repo");
361
357
  });
362
358
 
363
359
  it("should normalize HTTPS URL", () => {
364
- expect(normalizeRemoteUrl("https://github.com/user/repo.git")).toBe(
365
- "user/repo",
366
- );
360
+ expect(normalizeRemoteUrl("https://github.com/user/repo.git")).toBe("user/repo");
367
361
  });
368
362
 
369
363
  it("should handle URL without .git suffix", () => {
370
364
  expect(normalizeRemoteUrl("git@github.com:user/repo")).toBe("user/repo");
371
- expect(normalizeRemoteUrl("https://github.com/user/repo")).toBe(
372
- "user/repo",
373
- );
365
+ expect(normalizeRemoteUrl("https://github.com/user/repo")).toBe("user/repo");
374
366
  });
375
367
 
376
368
  it("should return empty string for empty input", () => {
@@ -378,26 +370,20 @@ describe("normalizeRemoteUrl", () => {
378
370
  });
379
371
 
380
372
  it("should handle GitLab SSH URL", () => {
381
- expect(normalizeRemoteUrl("git@gitlab.com:group/project.git")).toBe(
382
- "group/project",
383
- );
373
+ expect(normalizeRemoteUrl("git@gitlab.com:group/project.git")).toBe("group/project");
384
374
  });
385
375
 
386
376
  it("should handle Bitbucket SSH URL", () => {
387
- expect(normalizeRemoteUrl("git@bitbucket.org:team/repo.git")).toBe(
388
- "team/repo",
389
- );
377
+ expect(normalizeRemoteUrl("git@bitbucket.org:team/repo.git")).toBe("team/repo");
390
378
  });
391
379
 
392
380
  it("should handle HTTP URL (not HTTPS)", () => {
393
- expect(normalizeRemoteUrl("http://github.com/user/repo.git")).toBe(
394
- "user/repo",
395
- );
381
+ expect(normalizeRemoteUrl("http://github.com/user/repo.git")).toBe("user/repo");
396
382
  });
397
383
 
398
384
  it("should handle nested paths", () => {
399
- expect(
400
- normalizeRemoteUrl("https://github.com/org/group/subgroup/repo.git"),
401
- ).toBe("org/group/subgroup/repo");
385
+ expect(normalizeRemoteUrl("https://github.com/org/group/subgroup/repo.git")).toBe(
386
+ "org/group/subgroup/repo"
387
+ );
402
388
  });
403
389
  });
@@ -5,11 +5,7 @@
5
5
 
6
6
  import { execFile } from "node:child_process";
7
7
  import { promisify } from "node:util";
8
- import {
9
- GIT_LOG_COMMIT_DELIMITER,
10
- GIT_LOG_FORMAT,
11
- GIT_MAX_BUFFER,
12
- } from "./config.js";
8
+ import { GIT_LOG_COMMIT_DELIMITER, GIT_LOG_FORMAT, GIT_MAX_BUFFER } from "./config.js";
13
9
  import type { GitConfig, GitExtractOptions, RawCommit } from "./types.js";
14
10
 
15
11
  const execFileAsync = promisify(execFile);
@@ -34,7 +30,7 @@ export function normalizeRemoteUrl(url: string): string {
34
30
  export class GitExtractor {
35
31
  constructor(
36
32
  private repoPath: string,
37
- private config: GitConfig,
33
+ private config: GitConfig
38
34
  ) {}
39
35
 
40
36
  /**
@@ -70,15 +66,11 @@ export class GitExtractor {
70
66
  */
71
67
  async getRemoteUrl(): Promise<string> {
72
68
  try {
73
- const { stdout } = await execFileAsync(
74
- "git",
75
- ["remote", "get-url", "origin"],
76
- {
77
- cwd: this.repoPath,
78
- maxBuffer: GIT_MAX_BUFFER,
79
- timeout: this.config.gitTimeout,
80
- },
81
- );
69
+ const { stdout } = await execFileAsync("git", ["remote", "get-url", "origin"], {
70
+ cwd: this.repoPath,
71
+ maxBuffer: GIT_MAX_BUFFER,
72
+ timeout: this.config.gitTimeout,
73
+ });
82
74
  return stdout.trim();
83
75
  } catch {
84
76
  return ""; // No remote configured
@@ -144,15 +136,11 @@ export class GitExtractor {
144
136
  */
145
137
  async getCommitDiff(commitHash: string): Promise<string> {
146
138
  try {
147
- const { stdout } = await execFileAsync(
148
- "git",
149
- ["show", "--no-color", "-p", commitHash],
150
- {
151
- cwd: this.repoPath,
152
- maxBuffer: GIT_MAX_BUFFER,
153
- timeout: this.config.gitTimeout,
154
- },
155
- );
139
+ const { stdout } = await execFileAsync("git", ["show", "--no-color", "-p", commitHash], {
140
+ cwd: this.repoPath,
141
+ maxBuffer: GIT_MAX_BUFFER,
142
+ timeout: this.config.gitTimeout,
143
+ });
156
144
 
157
145
  // Truncate diff if it exceeds maxDiffSize
158
146
  if (stdout.length > this.config.maxDiffSize) {
@@ -204,15 +192,7 @@ export class GitExtractor {
204
192
 
205
193
  if (parts.length < 6) return null;
206
194
 
207
- const [
208
- hash,
209
- shortHash,
210
- author,
211
- authorEmail,
212
- dateStr,
213
- subject,
214
- ...bodyParts
215
- ] = parts;
195
+ const [hash, shortHash, author, authorEmail, dateStr, subject, ...bodyParts] = parts;
216
196
 
217
197
  // Parse files and stats from numstat output
218
198
  const { files, insertions, deletions } = this.parseNumstat(lines.slice(1));
@@ -266,9 +246,7 @@ export class GitExtractor {
266
246
  if (filename.includes(" => ")) {
267
247
  const renameParts = filename.match(/(.+)\{(.+) => (.+)\}(.+)?/);
268
248
  if (renameParts) {
269
- files.push(
270
- `${renameParts[1]}${renameParts[3]}${renameParts[4] || ""}`,
271
- );
249
+ files.push(`${renameParts[1]}${renameParts[3]}${renameParts[4] || ""}`);
272
250
  } else {
273
251
  const simpleRename = filename.split(" => ");
274
252
  files.push(simpleRename[1] || filename);
package/src/git/index.ts CHANGED
@@ -2,6 +2,14 @@
2
2
  * Git history indexing module - barrel export
3
3
  */
4
4
 
5
+ export { CommitChunker } from "./chunker.js";
6
+
7
+ // Config
8
+ export { COMMIT_TYPE_PATTERNS, DEFAULT_GIT_CONFIG } from "./config.js";
9
+ export { GitExtractor } from "./extractor.js";
10
+ // Main classes
11
+ export { GitHistoryIndexer } from "./indexer.js";
12
+ export { GitSynchronizer } from "./sync/synchronizer.js";
5
13
  // Types
6
14
  export type {
7
15
  CommitChunk,
@@ -9,10 +17,10 @@ export type {
9
17
  GitChangeStats,
10
18
  GitConfig,
11
19
  GitExtractOptions,
20
+ GitIndexingStatus,
12
21
  GitIndexOptions,
13
22
  GitIndexStats,
14
23
  GitIndexStatus,
15
- GitIndexingStatus,
16
24
  GitProgressCallback,
17
25
  GitProgressUpdate,
18
26
  GitSearchOptions,
@@ -20,12 +28,3 @@ export type {
20
28
  GitSnapshot,
21
29
  RawCommit,
22
30
  } from "./types.js";
23
-
24
- // Config
25
- export { DEFAULT_GIT_CONFIG, COMMIT_TYPE_PATTERNS } from "./config.js";
26
-
27
- // Main classes
28
- export { GitHistoryIndexer } from "./indexer.js";
29
- export { GitExtractor } from "./extractor.js";
30
- export { CommitChunker } from "./chunker.js";
31
- export { GitSynchronizer } from "./sync/synchronizer.js";
@@ -1,6 +1,6 @@
1
- import { describe, it, expect, vi, beforeEach } from "vitest";
2
- import { GitHistoryIndexer } from "./indexer.js";
1
+ import { beforeEach, describe, expect, it, vi } from "vitest";
3
2
  import { DEFAULT_GIT_CONFIG } from "./config.js";
3
+ import { GitHistoryIndexer } from "./indexer.js";
4
4
  import type { GitConfig } from "./types.js";
5
5
 
6
6
  // Create mock instances
@@ -100,9 +100,7 @@ describe("GitHistoryIndexer", () => {
100
100
  // Reset mock instances
101
101
  mockExtractorInstance.validateRepository.mockResolvedValue(true);
102
102
  mockExtractorInstance.getLatestCommitHash.mockResolvedValue("abc123def456");
103
- mockExtractorInstance.getRemoteUrl.mockResolvedValue(
104
- "git@github.com:test/repo.git",
105
- );
103
+ mockExtractorInstance.getRemoteUrl.mockResolvedValue("git@github.com:test/repo.git");
106
104
  mockExtractorInstance.getCommits.mockResolvedValue([]);
107
105
  mockExtractorInstance.getCommitDiff.mockResolvedValue("");
108
106
 
@@ -138,9 +136,7 @@ describe("GitHistoryIndexer", () => {
138
136
  collectionExists: vi.fn().mockResolvedValue(false),
139
137
  createCollection: vi.fn().mockResolvedValue(undefined),
140
138
  deleteCollection: vi.fn().mockResolvedValue(undefined),
141
- getCollectionInfo: vi
142
- .fn()
143
- .mockResolvedValue({ pointsCount: 0, hybridEnabled: false }),
139
+ getCollectionInfo: vi.fn().mockResolvedValue({ pointsCount: 0, hybridEnabled: false }),
144
140
  addPoints: vi.fn().mockResolvedValue(undefined),
145
141
  addPointsWithSparse: vi.fn().mockResolvedValue(undefined),
146
142
  search: vi.fn().mockResolvedValue([]),
@@ -151,9 +147,7 @@ describe("GitHistoryIndexer", () => {
151
147
  mockEmbeddings = {
152
148
  getDimensions: vi.fn().mockReturnValue(768),
153
149
  embed: vi.fn().mockResolvedValue({ embedding: Array(768).fill(0.5) }),
154
- embedBatch: vi
155
- .fn()
156
- .mockResolvedValue([{ embedding: Array(768).fill(0.5) }]),
150
+ embedBatch: vi.fn().mockResolvedValue([{ embedding: Array(768).fill(0.5) }]),
157
151
  };
158
152
 
159
153
  indexer = new GitHistoryIndexer(mockQdrant, mockEmbeddings, config);
@@ -196,9 +190,7 @@ describe("GitHistoryIndexer", () => {
196
190
  const stats = await indexer.indexHistory("/not/a/repo");
197
191
 
198
192
  expect(stats.status).toBe("failed");
199
- expect(
200
- stats.errors?.some((e) => e.includes("Not a valid git repository")),
201
- ).toBe(true);
193
+ expect(stats.errors?.some((e) => e.includes("Not a valid git repository"))).toBe(true);
202
194
  });
203
195
 
204
196
  it("should handle empty repository", async () => {
@@ -253,7 +245,7 @@ describe("GitHistoryIndexer", () => {
253
245
  expect(progressCallback).toHaveBeenCalledWith(
254
246
  expect.objectContaining({
255
247
  phase: expect.stringMatching(/extracting|chunking|embedding|storing/),
256
- }),
248
+ })
257
249
  );
258
250
  });
259
251
  });
@@ -291,9 +283,9 @@ describe("GitHistoryIndexer", () => {
291
283
  it("should throw error when history not indexed", async () => {
292
284
  mockQdrant.collectionExists.mockResolvedValue(false);
293
285
 
294
- await expect(
295
- indexer.searchHistory("/test/repo", "query"),
296
- ).rejects.toThrow("Git history not indexed");
286
+ await expect(indexer.searchHistory("/test/repo", "query")).rejects.toThrow(
287
+ "Git history not indexed"
288
+ );
297
289
  });
298
290
 
299
291
  it("should apply commit type filter", async () => {
@@ -314,7 +306,7 @@ describe("GitHistoryIndexer", () => {
314
306
  match: { any: ["fix", "feat"] },
315
307
  }),
316
308
  ]),
317
- }),
309
+ })
318
310
  );
319
311
  });
320
312
 
@@ -341,7 +333,7 @@ describe("GitHistoryIndexer", () => {
341
333
  range: { lte: "2024-12-31" },
342
334
  }),
343
335
  ]),
344
- }),
336
+ })
345
337
  );
346
338
  });
347
339
 
@@ -448,7 +440,7 @@ describe("GitHistoryIndexer", () => {
448
440
  mockSynchronizerInstance.initialize.mockResolvedValue(false);
449
441
 
450
442
  await expect(indexer.indexNewCommits("/test/repo")).rejects.toThrow(
451
- "No previous snapshot found",
443
+ "No previous snapshot found"
452
444
  );
453
445
  });
454
446
 
@@ -484,7 +476,7 @@ describe("GitHistoryIndexer", () => {
484
476
  it("should ignore snapshot deletion errors", async () => {
485
477
  mockQdrant.collectionExists.mockResolvedValue(true);
486
478
  mockSynchronizerInstance.deleteSnapshot.mockRejectedValue(
487
- new Error("Snapshot deletion failed"),
479
+ new Error("Snapshot deletion failed")
488
480
  );
489
481
 
490
482
  await expect(indexer.clearIndex("/test/repo")).resolves.not.toThrow();
@@ -568,7 +560,7 @@ describe("GitHistoryIndexer", () => {
568
560
  ]),
569
561
  }),
570
562
  ]),
571
- }),
563
+ })
572
564
  );
573
565
  });
574
566
  });
@@ -593,9 +585,7 @@ describe("GitHistoryIndexer", () => {
593
585
  mockExtractorInstance.validateRepository.mockResolvedValue(true);
594
586
  mockExtractorInstance.getLatestCommitHash.mockResolvedValue("abc123");
595
587
  mockExtractorInstance.getCommits.mockResolvedValue(mockCommits);
596
- mockExtractorInstance.getCommitDiff.mockRejectedValue(
597
- new Error("Diff extraction failed"),
598
- );
588
+ mockExtractorInstance.getCommitDiff.mockRejectedValue(new Error("Diff extraction failed"));
599
589
 
600
590
  const stats = await indexer.indexHistory("/test/repo");
601
591
 
@@ -623,9 +613,7 @@ describe("GitHistoryIndexer", () => {
623
613
  mockExtractorInstance.getLatestCommitHash.mockResolvedValue("abc123");
624
614
  mockExtractorInstance.getCommits.mockResolvedValue(mockCommits);
625
615
  mockExtractorInstance.getCommitDiff.mockResolvedValue("");
626
- mockEmbeddings.embedBatch.mockRejectedValue(
627
- new Error("Embedding API error"),
628
- );
616
+ mockEmbeddings.embedBatch.mockRejectedValue(new Error("Embedding API error"));
629
617
 
630
618
  const stats = await indexer.indexHistory("/test/repo");
631
619
 
@@ -653,9 +641,7 @@ describe("GitHistoryIndexer", () => {
653
641
  mockExtractorInstance.getLatestCommitHash.mockResolvedValue("abc123");
654
642
  mockExtractorInstance.getCommits.mockResolvedValue(mockCommits);
655
643
  mockExtractorInstance.getCommitDiff.mockResolvedValue("");
656
- mockSynchronizerInstance.updateSnapshot.mockRejectedValue(
657
- new Error("Snapshot write failed"),
658
- );
644
+ mockSynchronizerInstance.updateSnapshot.mockRejectedValue(new Error("Snapshot write failed"));
659
645
 
660
646
  const stats = await indexer.indexHistory("/test/repo");
661
647
 
@@ -684,11 +670,7 @@ describe("GitHistoryIndexer", () => {
684
670
  ...DEFAULT_GIT_CONFIG,
685
671
  enableHybridSearch: true,
686
672
  };
687
- const hybridIndexer = new GitHistoryIndexer(
688
- mockQdrant,
689
- mockEmbeddings,
690
- hybridConfig,
691
- );
673
+ const hybridIndexer = new GitHistoryIndexer(mockQdrant, mockEmbeddings, hybridConfig);
692
674
 
693
675
  const mockCommits = [
694
676
  {
@@ -720,7 +702,7 @@ describe("GitHistoryIndexer", () => {
720
702
  expect.any(String),
721
703
  768,
722
704
  "Cosine",
723
- true,
705
+ true
724
706
  );
725
707
  expect(mockQdrant.addPointsWithSparse).toHaveBeenCalled();
726
708
  });
@@ -758,7 +740,7 @@ describe("GitHistoryIndexer", () => {
758
740
  mockQdrant.collectionExists.mockResolvedValue(false);
759
741
 
760
742
  await expect(indexer.indexNewCommits("/test/repo")).rejects.toThrow(
761
- "Git history not indexed",
743
+ "Git history not indexed"
762
744
  );
763
745
  });
764
746
 
@@ -768,7 +750,7 @@ describe("GitHistoryIndexer", () => {
768
750
  mockSynchronizerInstance.getLastCommitHash.mockReturnValue(null);
769
751
 
770
752
  await expect(indexer.indexNewCommits("/test/repo")).rejects.toThrow(
771
- "Invalid snapshot: no last commit hash",
753
+ "Invalid snapshot: no last commit hash"
772
754
  );
773
755
  });
774
756
 
@@ -805,7 +787,7 @@ describe("GitHistoryIndexer", () => {
805
787
  expect(progressCallback).toHaveBeenCalledWith(
806
788
  expect.objectContaining({
807
789
  phase: expect.stringMatching(/extracting|chunking|embedding|storing/),
808
- }),
790
+ })
809
791
  );
810
792
  });
811
793
 
@@ -814,11 +796,7 @@ describe("GitHistoryIndexer", () => {
814
796
  ...DEFAULT_GIT_CONFIG,
815
797
  enableHybridSearch: true,
816
798
  };
817
- const hybridIndexer = new GitHistoryIndexer(
818
- mockQdrant,
819
- mockEmbeddings,
820
- hybridConfig,
821
- );
799
+ const hybridIndexer = new GitHistoryIndexer(mockQdrant, mockEmbeddings, hybridConfig);
822
800
 
823
801
  mockQdrant.collectionExists.mockResolvedValue(true);
824
802
 
@@ -900,9 +878,7 @@ describe("GitHistoryIndexer", () => {
900
878
  mockSynchronizerInstance.initialize.mockResolvedValue(true);
901
879
  mockSynchronizerInstance.getCommitsIndexed.mockReturnValue(100);
902
880
  mockSynchronizerInstance.getLastCommitHash.mockReturnValue("latest123");
903
- mockSynchronizerInstance.getLastIndexedAt.mockReturnValue(
904
- new Date("2024-01-15T10:00:00Z"),
905
- );
881
+ mockSynchronizerInstance.getLastIndexedAt.mockReturnValue(new Date("2024-01-15T10:00:00Z"));
906
882
 
907
883
  const status = await indexer.getIndexStatus("/test/repo");
908
884
 
@@ -945,9 +921,9 @@ describe("GitHistoryIndexer", () => {
945
921
  indexer.searchHistory("/test/repo", "query", {
946
922
  dateFrom: "2024-12-31",
947
923
  dateTo: "2024-01-01",
948
- }),
924
+ })
949
925
  ).rejects.toThrow(
950
- "Invalid date range: dateFrom (2024-12-31) must be before dateTo (2024-01-01)",
926
+ "Invalid date range: dateFrom (2024-12-31) must be before dateTo (2024-01-01)"
951
927
  );
952
928
  });
953
929
 
@@ -1076,9 +1052,7 @@ describe("GitHistoryIndexer", () => {
1076
1052
  mockChunkerInstance.generateChunkId.mockReturnValue("chunk-1");
1077
1053
 
1078
1054
  // All retries fail
1079
- mockEmbeddings.embedBatch.mockRejectedValue(
1080
- new Error("Persistent error"),
1081
- );
1055
+ mockEmbeddings.embedBatch.mockRejectedValue(new Error("Persistent error"));
1082
1056
 
1083
1057
  mockQdrant.collectionExists.mockResolvedValue(false);
1084
1058
  mockQdrant.getCollectionInfo.mockResolvedValue({ hybridEnabled: false });
@@ -1087,9 +1061,7 @@ describe("GitHistoryIndexer", () => {
1087
1061
 
1088
1062
  expect(stats.status).toBe("partial");
1089
1063
  expect(stats.errors).toBeDefined();
1090
- expect(stats.errors?.some((e) => e.includes("after 3 attempts"))).toBe(
1091
- true,
1092
- );
1064
+ expect(stats.errors?.some((e) => e.includes("after 3 attempts"))).toBe(true);
1093
1065
  });
1094
1066
  });
1095
1067
  });