@code-rag/core 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (347) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +19 -0
  3. package/dist/auth/audit-log.d.ts +35 -0
  4. package/dist/auth/audit-log.js +110 -0
  5. package/dist/auth/audit-log.js.map +1 -0
  6. package/dist/auth/audit-log.test.d.ts +1 -0
  7. package/dist/auth/audit-log.test.js +261 -0
  8. package/dist/auth/audit-log.test.js.map +1 -0
  9. package/dist/auth/index.d.ts +6 -0
  10. package/dist/auth/index.js +5 -0
  11. package/dist/auth/index.js.map +1 -0
  12. package/dist/auth/oidc-provider.d.ts +49 -0
  13. package/dist/auth/oidc-provider.js +358 -0
  14. package/dist/auth/oidc-provider.js.map +1 -0
  15. package/dist/auth/oidc-provider.test.d.ts +1 -0
  16. package/dist/auth/oidc-provider.test.js +520 -0
  17. package/dist/auth/oidc-provider.test.js.map +1 -0
  18. package/dist/auth/rbac.d.ts +29 -0
  19. package/dist/auth/rbac.js +75 -0
  20. package/dist/auth/rbac.js.map +1 -0
  21. package/dist/auth/rbac.test.d.ts +1 -0
  22. package/dist/auth/rbac.test.js +224 -0
  23. package/dist/auth/rbac.test.js.map +1 -0
  24. package/dist/auth/saml-provider.d.ts +51 -0
  25. package/dist/auth/saml-provider.js +355 -0
  26. package/dist/auth/saml-provider.js.map +1 -0
  27. package/dist/auth/saml-provider.test.d.ts +1 -0
  28. package/dist/auth/saml-provider.test.js +422 -0
  29. package/dist/auth/saml-provider.test.js.map +1 -0
  30. package/dist/auth/types.d.ts +81 -0
  31. package/dist/auth/types.js +11 -0
  32. package/dist/auth/types.js.map +1 -0
  33. package/dist/auth/types.test.d.ts +1 -0
  34. package/dist/auth/types.test.js +147 -0
  35. package/dist/auth/types.test.js.map +1 -0
  36. package/dist/backlog/ab-reference-scanner.d.ts +10 -0
  37. package/dist/backlog/ab-reference-scanner.js +22 -0
  38. package/dist/backlog/ab-reference-scanner.js.map +1 -0
  39. package/dist/backlog/ab-reference-scanner.test.d.ts +1 -0
  40. package/dist/backlog/ab-reference-scanner.test.js +83 -0
  41. package/dist/backlog/ab-reference-scanner.test.js.map +1 -0
  42. package/dist/backlog/azure-devops-provider.d.ts +59 -0
  43. package/dist/backlog/azure-devops-provider.js +283 -0
  44. package/dist/backlog/azure-devops-provider.js.map +1 -0
  45. package/dist/backlog/backlog-provider.d.ts +13 -0
  46. package/dist/backlog/backlog-provider.js +6 -0
  47. package/dist/backlog/backlog-provider.js.map +1 -0
  48. package/dist/backlog/backlog-provider.test.d.ts +1 -0
  49. package/dist/backlog/backlog-provider.test.js +426 -0
  50. package/dist/backlog/backlog-provider.test.js.map +1 -0
  51. package/dist/backlog/clickup-provider.d.ts +55 -0
  52. package/dist/backlog/clickup-provider.js +301 -0
  53. package/dist/backlog/clickup-provider.js.map +1 -0
  54. package/dist/backlog/clickup-provider.test.d.ts +1 -0
  55. package/dist/backlog/clickup-provider.test.js +426 -0
  56. package/dist/backlog/clickup-provider.test.js.map +1 -0
  57. package/dist/backlog/clickup-reference-scanner.d.ts +10 -0
  58. package/dist/backlog/clickup-reference-scanner.js +32 -0
  59. package/dist/backlog/clickup-reference-scanner.js.map +1 -0
  60. package/dist/backlog/clickup-reference-scanner.test.d.ts +1 -0
  61. package/dist/backlog/clickup-reference-scanner.test.js +92 -0
  62. package/dist/backlog/clickup-reference-scanner.test.js.map +1 -0
  63. package/dist/backlog/code-linker.d.ts +63 -0
  64. package/dist/backlog/code-linker.js +90 -0
  65. package/dist/backlog/code-linker.js.map +1 -0
  66. package/dist/backlog/code-linker.test.d.ts +1 -0
  67. package/dist/backlog/code-linker.test.js +325 -0
  68. package/dist/backlog/code-linker.test.js.map +1 -0
  69. package/dist/backlog/index.d.ts +14 -0
  70. package/dist/backlog/index.js +8 -0
  71. package/dist/backlog/index.js.map +1 -0
  72. package/dist/backlog/jira-provider.d.ts +60 -0
  73. package/dist/backlog/jira-provider.js +272 -0
  74. package/dist/backlog/jira-provider.js.map +1 -0
  75. package/dist/backlog/jira-provider.test.d.ts +1 -0
  76. package/dist/backlog/jira-provider.test.js +449 -0
  77. package/dist/backlog/jira-provider.test.js.map +1 -0
  78. package/dist/backlog/jira-reference-scanner.d.ts +11 -0
  79. package/dist/backlog/jira-reference-scanner.js +26 -0
  80. package/dist/backlog/jira-reference-scanner.js.map +1 -0
  81. package/dist/backlog/jira-reference-scanner.test.d.ts +1 -0
  82. package/dist/backlog/jira-reference-scanner.test.js +127 -0
  83. package/dist/backlog/jira-reference-scanner.test.js.map +1 -0
  84. package/dist/backlog/types.d.ts +22 -0
  85. package/dist/backlog/types.js +1 -0
  86. package/dist/backlog/types.js.map +1 -0
  87. package/dist/chunker/ast-chunker.d.ts +45 -0
  88. package/dist/chunker/ast-chunker.js +292 -0
  89. package/dist/chunker/ast-chunker.js.map +1 -0
  90. package/dist/chunker/ast-chunker.test.d.ts +1 -0
  91. package/dist/chunker/ast-chunker.test.js +391 -0
  92. package/dist/chunker/ast-chunker.test.js.map +1 -0
  93. package/dist/chunker/chunker.d.ts +8 -0
  94. package/dist/chunker/chunker.js +1 -0
  95. package/dist/chunker/chunker.js.map +1 -0
  96. package/dist/chunker/index.d.ts +3 -0
  97. package/dist/chunker/index.js +2 -0
  98. package/dist/chunker/index.js.map +1 -0
  99. package/dist/config/config-parser.d.ts +15 -0
  100. package/dist/config/config-parser.js +283 -0
  101. package/dist/config/config-parser.js.map +1 -0
  102. package/dist/config/config-parser.test.d.ts +1 -0
  103. package/dist/config/config-parser.test.js +699 -0
  104. package/dist/config/config-parser.test.js.map +1 -0
  105. package/dist/docs/confluence-provider.d.ts +121 -0
  106. package/dist/docs/confluence-provider.js +459 -0
  107. package/dist/docs/confluence-provider.js.map +1 -0
  108. package/dist/docs/confluence-provider.test.d.ts +1 -0
  109. package/dist/docs/confluence-provider.test.js +765 -0
  110. package/dist/docs/confluence-provider.test.js.map +1 -0
  111. package/dist/docs/index.d.ts +4 -0
  112. package/dist/docs/index.js +2 -0
  113. package/dist/docs/index.js.map +1 -0
  114. package/dist/docs/sharepoint-provider.d.ts +150 -0
  115. package/dist/docs/sharepoint-provider.js +637 -0
  116. package/dist/docs/sharepoint-provider.js.map +1 -0
  117. package/dist/docs/sharepoint-provider.test.d.ts +1 -0
  118. package/dist/docs/sharepoint-provider.test.js +873 -0
  119. package/dist/docs/sharepoint-provider.test.js.map +1 -0
  120. package/dist/embedding/bm25-index.d.ts +12 -0
  121. package/dist/embedding/bm25-index.js +89 -0
  122. package/dist/embedding/bm25-index.js.map +1 -0
  123. package/dist/embedding/bm25-index.test.d.ts +1 -0
  124. package/dist/embedding/bm25-index.test.js +289 -0
  125. package/dist/embedding/bm25-index.test.js.map +1 -0
  126. package/dist/embedding/hybrid-search.d.ts +13 -0
  127. package/dist/embedding/hybrid-search.js +124 -0
  128. package/dist/embedding/hybrid-search.js.map +1 -0
  129. package/dist/embedding/hybrid-search.test.d.ts +1 -0
  130. package/dist/embedding/hybrid-search.test.js +266 -0
  131. package/dist/embedding/hybrid-search.test.js.map +1 -0
  132. package/dist/embedding/index.d.ts +11 -0
  133. package/dist/embedding/index.js +7 -0
  134. package/dist/embedding/index.js.map +1 -0
  135. package/dist/embedding/lancedb-store.d.ts +21 -0
  136. package/dist/embedding/lancedb-store.js +172 -0
  137. package/dist/embedding/lancedb-store.js.map +1 -0
  138. package/dist/embedding/lancedb-store.test.d.ts +1 -0
  139. package/dist/embedding/lancedb-store.test.js +268 -0
  140. package/dist/embedding/lancedb-store.test.js.map +1 -0
  141. package/dist/embedding/model-lifecycle-manager.d.ts +83 -0
  142. package/dist/embedding/model-lifecycle-manager.js +419 -0
  143. package/dist/embedding/model-lifecycle-manager.js.map +1 -0
  144. package/dist/embedding/model-lifecycle-manager.test.d.ts +1 -0
  145. package/dist/embedding/model-lifecycle-manager.test.js +642 -0
  146. package/dist/embedding/model-lifecycle-manager.test.js.map +1 -0
  147. package/dist/embedding/ollama-embedding-provider.d.ts +16 -0
  148. package/dist/embedding/ollama-embedding-provider.js +74 -0
  149. package/dist/embedding/ollama-embedding-provider.js.map +1 -0
  150. package/dist/embedding/ollama-embedding-provider.test.d.ts +1 -0
  151. package/dist/embedding/ollama-embedding-provider.test.js +198 -0
  152. package/dist/embedding/ollama-embedding-provider.test.js.map +1 -0
  153. package/dist/embedding/openai-compatible-embedding-provider.d.ts +19 -0
  154. package/dist/embedding/openai-compatible-embedding-provider.js +108 -0
  155. package/dist/embedding/openai-compatible-embedding-provider.js.map +1 -0
  156. package/dist/embedding/openai-compatible-embedding-provider.test.d.ts +1 -0
  157. package/dist/embedding/openai-compatible-embedding-provider.test.js +456 -0
  158. package/dist/embedding/openai-compatible-embedding-provider.test.js.map +1 -0
  159. package/dist/embedding/qdrant-store.d.ts +28 -0
  160. package/dist/embedding/qdrant-store.js +174 -0
  161. package/dist/embedding/qdrant-store.js.map +1 -0
  162. package/dist/embedding/qdrant-store.test.d.ts +1 -0
  163. package/dist/embedding/qdrant-store.test.js +359 -0
  164. package/dist/embedding/qdrant-store.test.js.map +1 -0
  165. package/dist/enrichment/index.d.ts +4 -0
  166. package/dist/enrichment/index.js +2 -0
  167. package/dist/enrichment/index.js.map +1 -0
  168. package/dist/enrichment/nl-enricher.d.ts +16 -0
  169. package/dist/enrichment/nl-enricher.js +47 -0
  170. package/dist/enrichment/nl-enricher.js.map +1 -0
  171. package/dist/enrichment/nl-enricher.test.d.ts +1 -0
  172. package/dist/enrichment/nl-enricher.test.js +154 -0
  173. package/dist/enrichment/nl-enricher.test.js.map +1 -0
  174. package/dist/enrichment/ollama-client.d.ts +18 -0
  175. package/dist/enrichment/ollama-client.js +55 -0
  176. package/dist/enrichment/ollama-client.js.map +1 -0
  177. package/dist/enrichment/ollama-client.test.d.ts +1 -0
  178. package/dist/enrichment/ollama-client.test.js +129 -0
  179. package/dist/enrichment/ollama-client.test.js.map +1 -0
  180. package/dist/git/git-client.d.ts +22 -0
  181. package/dist/git/git-client.js +6 -0
  182. package/dist/git/git-client.js.map +1 -0
  183. package/dist/git/git-client.test.d.ts +1 -0
  184. package/dist/git/git-client.test.js +200 -0
  185. package/dist/git/git-client.test.js.map +1 -0
  186. package/dist/git/ignore-filter.d.ts +2 -0
  187. package/dist/git/ignore-filter.js +31 -0
  188. package/dist/git/ignore-filter.js.map +1 -0
  189. package/dist/git/ignore-filter.test.d.ts +1 -0
  190. package/dist/git/ignore-filter.test.js +87 -0
  191. package/dist/git/ignore-filter.test.js.map +1 -0
  192. package/dist/git/index.d.ts +4 -0
  193. package/dist/git/index.js +3 -0
  194. package/dist/git/index.js.map +1 -0
  195. package/dist/git/simple-git-client.d.ts +12 -0
  196. package/dist/git/simple-git-client.js +138 -0
  197. package/dist/git/simple-git-client.js.map +1 -0
  198. package/dist/graph/cross-repo-resolver.d.ts +50 -0
  199. package/dist/graph/cross-repo-resolver.js +315 -0
  200. package/dist/graph/cross-repo-resolver.js.map +1 -0
  201. package/dist/graph/cross-repo-resolver.test.d.ts +1 -0
  202. package/dist/graph/cross-repo-resolver.test.js +548 -0
  203. package/dist/graph/cross-repo-resolver.test.js.map +1 -0
  204. package/dist/graph/dependency-graph.d.ts +44 -0
  205. package/dist/graph/dependency-graph.js +108 -0
  206. package/dist/graph/dependency-graph.js.map +1 -0
  207. package/dist/graph/dependency-graph.test.d.ts +1 -0
  208. package/dist/graph/dependency-graph.test.js +276 -0
  209. package/dist/graph/dependency-graph.test.js.map +1 -0
  210. package/dist/graph/graph-builder.d.ts +11 -0
  211. package/dist/graph/graph-builder.js +113 -0
  212. package/dist/graph/graph-builder.js.map +1 -0
  213. package/dist/graph/graph-builder.test.d.ts +1 -0
  214. package/dist/graph/graph-builder.test.js +178 -0
  215. package/dist/graph/graph-builder.test.js.map +1 -0
  216. package/dist/graph/import-resolver.d.ts +11 -0
  217. package/dist/graph/import-resolver.js +199 -0
  218. package/dist/graph/import-resolver.js.map +1 -0
  219. package/dist/graph/import-resolver.test.d.ts +1 -0
  220. package/dist/graph/import-resolver.test.js +282 -0
  221. package/dist/graph/import-resolver.test.js.map +1 -0
  222. package/dist/graph/index.d.ts +7 -0
  223. package/dist/graph/index.js +4 -0
  224. package/dist/graph/index.js.map +1 -0
  225. package/dist/index.d.ts +31 -0
  226. package/dist/index.js +15 -0
  227. package/dist/index.js.map +1 -0
  228. package/dist/indexer/file-scanner.d.ts +34 -0
  229. package/dist/indexer/file-scanner.js +69 -0
  230. package/dist/indexer/file-scanner.js.map +1 -0
  231. package/dist/indexer/file-scanner.test.d.ts +1 -0
  232. package/dist/indexer/file-scanner.test.js +110 -0
  233. package/dist/indexer/file-scanner.test.js.map +1 -0
  234. package/dist/indexer/file-watcher.d.ts +79 -0
  235. package/dist/indexer/file-watcher.js +148 -0
  236. package/dist/indexer/incremental-indexer.d.ts +67 -0
  237. package/dist/indexer/incremental-indexer.js +142 -0
  238. package/dist/indexer/incremental-indexer.js.map +1 -0
  239. package/dist/indexer/incremental-indexer.test.d.ts +1 -0
  240. package/dist/indexer/incremental-indexer.test.js +266 -0
  241. package/dist/indexer/incremental-indexer.test.js.map +1 -0
  242. package/dist/indexer/index-check.d.ts +22 -0
  243. package/dist/indexer/index-check.js +74 -0
  244. package/dist/indexer/index-check.js.map +1 -0
  245. package/dist/indexer/index-check.test.d.ts +1 -0
  246. package/dist/indexer/index-check.test.js +100 -0
  247. package/dist/indexer/index-check.test.js.map +1 -0
  248. package/dist/indexer/index-state.d.ts +61 -0
  249. package/dist/indexer/index-state.js +82 -0
  250. package/dist/indexer/index-state.js.map +1 -0
  251. package/dist/indexer/index-state.test.d.ts +1 -0
  252. package/dist/indexer/index-state.test.js +140 -0
  253. package/dist/indexer/index-state.test.js.map +1 -0
  254. package/dist/indexer/index.d.ts +12 -0
  255. package/dist/indexer/index.js +6 -0
  256. package/dist/indexer/index.js.map +1 -0
  257. package/dist/indexer/multi-repo-indexer.d.ts +63 -0
  258. package/dist/indexer/multi-repo-indexer.js +144 -0
  259. package/dist/indexer/multi-repo-indexer.js.map +1 -0
  260. package/dist/indexer/multi-repo-indexer.test.d.ts +1 -0
  261. package/dist/indexer/multi-repo-indexer.test.js +238 -0
  262. package/dist/indexer/multi-repo-indexer.test.js.map +1 -0
  263. package/dist/parser/index.d.ts +4 -0
  264. package/dist/parser/index.js +3 -0
  265. package/dist/parser/index.js.map +1 -0
  266. package/dist/parser/language-registry.d.ts +46 -0
  267. package/dist/parser/language-registry.js +219 -0
  268. package/dist/parser/language-registry.js.map +1 -0
  269. package/dist/parser/language-registry.test.d.ts +1 -0
  270. package/dist/parser/language-registry.test.js +225 -0
  271. package/dist/parser/language-registry.test.js.map +1 -0
  272. package/dist/parser/markdown-parser.d.ts +124 -0
  273. package/dist/parser/markdown-parser.js +487 -0
  274. package/dist/parser/markdown-parser.js.map +1 -0
  275. package/dist/parser/markdown-parser.test.d.ts +1 -0
  276. package/dist/parser/markdown-parser.test.js +600 -0
  277. package/dist/parser/markdown-parser.test.js.map +1 -0
  278. package/dist/parser/tree-sitter-parser.d.ts +32 -0
  279. package/dist/parser/tree-sitter-parser.js +146 -0
  280. package/dist/parser/tree-sitter-parser.js.map +1 -0
  281. package/dist/retrieval/context-expander.d.ts +51 -0
  282. package/dist/retrieval/context-expander.js +218 -0
  283. package/dist/retrieval/context-expander.js.map +1 -0
  284. package/dist/retrieval/context-expander.test.d.ts +1 -0
  285. package/dist/retrieval/context-expander.test.js +339 -0
  286. package/dist/retrieval/context-expander.test.js.map +1 -0
  287. package/dist/retrieval/cross-encoder-reranker.d.ts +16 -0
  288. package/dist/retrieval/cross-encoder-reranker.js +90 -0
  289. package/dist/retrieval/cross-encoder-reranker.js.map +1 -0
  290. package/dist/retrieval/cross-encoder-reranker.test.d.ts +1 -0
  291. package/dist/retrieval/cross-encoder-reranker.test.js +305 -0
  292. package/dist/retrieval/cross-encoder-reranker.test.js.map +1 -0
  293. package/dist/retrieval/index.d.ts +8 -0
  294. package/dist/retrieval/index.js +4 -0
  295. package/dist/retrieval/index.js.map +1 -0
  296. package/dist/retrieval/query-analyzer.d.ts +29 -0
  297. package/dist/retrieval/query-analyzer.js +238 -0
  298. package/dist/retrieval/query-analyzer.js.map +1 -0
  299. package/dist/retrieval/query-analyzer.test.d.ts +1 -0
  300. package/dist/retrieval/query-analyzer.test.js +236 -0
  301. package/dist/retrieval/query-analyzer.test.js.map +1 -0
  302. package/dist/retrieval/token-budget.d.ts +51 -0
  303. package/dist/retrieval/token-budget.js +141 -0
  304. package/dist/retrieval/token-budget.js.map +1 -0
  305. package/dist/retrieval/token-budget.test.d.ts +1 -0
  306. package/dist/retrieval/token-budget.test.js +404 -0
  307. package/dist/retrieval/token-budget.test.js.map +1 -0
  308. package/dist/storage/azure-blob-provider.d.ts +19 -0
  309. package/dist/storage/azure-blob-provider.js +199 -0
  310. package/dist/storage/azure-blob-provider.js.map +1 -0
  311. package/dist/storage/azure-blob-provider.test.d.ts +1 -0
  312. package/dist/storage/azure-blob-provider.test.js +250 -0
  313. package/dist/storage/azure-blob-provider.test.js.map +1 -0
  314. package/dist/storage/gcs-provider.d.ts +22 -0
  315. package/dist/storage/gcs-provider.js +241 -0
  316. package/dist/storage/gcs-provider.js.map +1 -0
  317. package/dist/storage/gcs-provider.test.d.ts +1 -0
  318. package/dist/storage/gcs-provider.test.js +299 -0
  319. package/dist/storage/gcs-provider.test.js.map +1 -0
  320. package/dist/storage/index.d.ts +5 -0
  321. package/dist/storage/index.js +4 -0
  322. package/dist/storage/index.js.map +1 -0
  323. package/dist/storage/s3-provider.d.ts +21 -0
  324. package/dist/storage/s3-provider.js +220 -0
  325. package/dist/storage/s3-provider.js.map +1 -0
  326. package/dist/storage/s3-provider.test.d.ts +1 -0
  327. package/dist/storage/s3-provider.test.js +329 -0
  328. package/dist/storage/s3-provider.test.js.map +1 -0
  329. package/dist/storage/types.d.ts +65 -0
  330. package/dist/storage/types.js +12 -0
  331. package/dist/storage/types.js.map +1 -0
  332. package/dist/types/chunk.d.ts +32 -0
  333. package/dist/types/chunk.js +1 -0
  334. package/dist/types/chunk.js.map +1 -0
  335. package/dist/types/config.d.ts +71 -0
  336. package/dist/types/config.js +1 -0
  337. package/dist/types/config.js.map +1 -0
  338. package/dist/types/index.d.ts +5 -0
  339. package/dist/types/index.js +1 -0
  340. package/dist/types/index.js.map +1 -0
  341. package/dist/types/provider.d.ts +54 -0
  342. package/dist/types/provider.js +36 -0
  343. package/dist/types/provider.js.map +1 -0
  344. package/dist/types/search.d.ts +27 -0
  345. package/dist/types/search.js +1 -0
  346. package/dist/types/search.js.map +1 -0
  347. package/package.json +70 -0
@@ -0,0 +1,266 @@
1
+ import { describe, it, expect, beforeEach, afterEach } from 'vitest';
2
+ import { mkdtempSync, writeFileSync, rmSync } from 'node:fs';
3
+ import { join } from 'node:path';
4
+ import { tmpdir } from 'node:os';
5
+ import { ok } from 'neverthrow';
6
+ import { IndexState, computeFileHash } from './index-state.js';
7
+ import { IncrementalIndexer } from './incremental-indexer.js';
8
+ /**
9
+ * Minimal mock of GitClient that satisfies the interface.
10
+ * The IncrementalIndexer currently relies on FileScanner rather than
11
+ * GitClient for change detection, but the interface requires it.
12
+ */
13
+ function createMockGitClient() {
14
+ return {
15
+ async getChangedFiles(_since) {
16
+ return ok([]);
17
+ },
18
+ async getFileMetadata(filePath) {
19
+ return ok({
20
+ filePath,
21
+ lastModified: new Date(),
22
+ author: 'test',
23
+ commitHash: 'abc123',
24
+ });
25
+ },
26
+ async getCurrentCommit() {
27
+ return ok('abc123def456');
28
+ },
29
+ async isGitRepo(_dir) {
30
+ return ok(true);
31
+ },
32
+ };
33
+ }
34
+ describe('IncrementalIndexer', () => {
35
+ let tempDir;
36
+ let config;
37
+ let gitClient;
38
+ beforeEach(() => {
39
+ tempDir = mkdtempSync(join(tmpdir(), 'coderag-indexer-test-'));
40
+ config = {
41
+ rootDir: tempDir,
42
+ maxTokensPerChunk: 500,
43
+ concurrency: 2,
44
+ };
45
+ gitClient = createMockGitClient();
46
+ });
47
+ afterEach(() => {
48
+ rmSync(tempDir, { recursive: true, force: true });
49
+ });
50
+ describe('detectChanges', () => {
51
+ it('should detect new files when state is empty', async () => {
52
+ writeFileSync(join(tempDir, 'main.ts'), 'export const x = 1;');
53
+ writeFileSync(join(tempDir, 'util.ts'), 'export function add() {}');
54
+ const state = new IndexState();
55
+ const indexer = new IncrementalIndexer(config, gitClient, state);
56
+ const result = await indexer.detectChanges();
57
+ expect(result.isOk()).toBe(true);
58
+ if (result.isOk()) {
59
+ expect(result.value.added.sort()).toEqual(['main.ts', 'util.ts']);
60
+ expect(result.value.modified).toEqual([]);
61
+ expect(result.value.deleted).toEqual([]);
62
+ }
63
+ });
64
+ it('should detect modified files when content hash changes', async () => {
65
+ const originalContent = 'export const x = 1;';
66
+ const newContent = 'export const x = 2;';
67
+ writeFileSync(join(tempDir, 'main.ts'), newContent);
68
+ const state = new IndexState();
69
+ state.setFileState('main.ts', {
70
+ filePath: 'main.ts',
71
+ contentHash: computeFileHash(originalContent),
72
+ lastIndexedAt: new Date(),
73
+ chunkIds: ['old-chunk'],
74
+ });
75
+ const indexer = new IncrementalIndexer(config, gitClient, state);
76
+ const result = await indexer.detectChanges();
77
+ expect(result.isOk()).toBe(true);
78
+ if (result.isOk()) {
79
+ expect(result.value.added).toEqual([]);
80
+ expect(result.value.modified).toEqual(['main.ts']);
81
+ expect(result.value.deleted).toEqual([]);
82
+ }
83
+ });
84
+ it('should detect deleted files', async () => {
85
+ // State has a file that no longer exists on disk
86
+ const state = new IndexState();
87
+ state.setFileState('deleted.ts', {
88
+ filePath: 'deleted.ts',
89
+ contentHash: 'some-hash',
90
+ lastIndexedAt: new Date(),
91
+ chunkIds: ['chunk-1'],
92
+ });
93
+ const indexer = new IncrementalIndexer(config, gitClient, state);
94
+ const result = await indexer.detectChanges();
95
+ expect(result.isOk()).toBe(true);
96
+ if (result.isOk()) {
97
+ expect(result.value.added).toEqual([]);
98
+ expect(result.value.modified).toEqual([]);
99
+ expect(result.value.deleted).toEqual(['deleted.ts']);
100
+ }
101
+ });
102
+ it('should report no changes when state matches filesystem', async () => {
103
+ const content = 'export const x = 1;';
104
+ writeFileSync(join(tempDir, 'main.ts'), content);
105
+ const state = new IndexState();
106
+ state.setFileState('main.ts', {
107
+ filePath: 'main.ts',
108
+ contentHash: computeFileHash(content),
109
+ lastIndexedAt: new Date(),
110
+ chunkIds: ['chunk-1'],
111
+ });
112
+ const indexer = new IncrementalIndexer(config, gitClient, state);
113
+ const result = await indexer.detectChanges();
114
+ expect(result.isOk()).toBe(true);
115
+ if (result.isOk()) {
116
+ expect(result.value.added).toEqual([]);
117
+ expect(result.value.modified).toEqual([]);
118
+ expect(result.value.deleted).toEqual([]);
119
+ }
120
+ });
121
+ it('should detect a mix of added, modified, and deleted files', async () => {
122
+ const existingContent = 'export const y = 2;';
123
+ const modifiedContent = 'export const y = 999;';
124
+ writeFileSync(join(tempDir, 'existing.ts'), modifiedContent);
125
+ writeFileSync(join(tempDir, 'brand-new.ts'), 'new file');
126
+ const state = new IndexState();
127
+ state.setFileState('existing.ts', {
128
+ filePath: 'existing.ts',
129
+ contentHash: computeFileHash(existingContent),
130
+ lastIndexedAt: new Date(),
131
+ chunkIds: ['c1'],
132
+ });
133
+ state.setFileState('gone.ts', {
134
+ filePath: 'gone.ts',
135
+ contentHash: 'old',
136
+ lastIndexedAt: new Date(),
137
+ chunkIds: ['c2'],
138
+ });
139
+ const indexer = new IncrementalIndexer(config, gitClient, state);
140
+ const result = await indexer.detectChanges();
141
+ expect(result.isOk()).toBe(true);
142
+ if (result.isOk()) {
143
+ expect(result.value.added).toEqual(['brand-new.ts']);
144
+ expect(result.value.modified).toEqual(['existing.ts']);
145
+ expect(result.value.deleted).toEqual(['gone.ts']);
146
+ }
147
+ });
148
+ });
149
+ describe('reindex', () => {
150
+ it('should process added files and update state', async () => {
151
+ writeFileSync(join(tempDir, 'new-file.ts'), 'export const z = 42;');
152
+ const state = new IndexState();
153
+ const indexer = new IncrementalIndexer(config, gitClient, state);
154
+ const changes = {
155
+ added: ['new-file.ts'],
156
+ modified: [],
157
+ deleted: [],
158
+ };
159
+ const result = await indexer.reindex(changes);
160
+ expect(result.isOk()).toBe(true);
161
+ if (result.isOk()) {
162
+ expect(result.value.added).toEqual(['new-file.ts']);
163
+ expect(result.value.modified).toEqual([]);
164
+ expect(result.value.deleted).toEqual([]);
165
+ expect(result.value.totalChunks).toBeGreaterThan(0);
166
+ expect(result.value.duration).toBeGreaterThanOrEqual(0);
167
+ }
168
+ // Verify state was updated
169
+ const fileState = state.getFileState('new-file.ts');
170
+ expect(fileState).toBeDefined();
171
+ expect(fileState?.chunkIds.length).toBeGreaterThan(0);
172
+ });
173
+ it('should process modified files and update state', async () => {
174
+ const newContent = 'export const z = 99;';
175
+ writeFileSync(join(tempDir, 'modified.ts'), newContent);
176
+ const state = new IndexState();
177
+ state.setFileState('modified.ts', {
178
+ filePath: 'modified.ts',
179
+ contentHash: 'old-hash',
180
+ lastIndexedAt: new Date('2025-01-01'),
181
+ chunkIds: ['old-chunk'],
182
+ });
183
+ const indexer = new IncrementalIndexer(config, gitClient, state);
184
+ const changes = {
185
+ added: [],
186
+ modified: ['modified.ts'],
187
+ deleted: [],
188
+ };
189
+ const result = await indexer.reindex(changes);
190
+ expect(result.isOk()).toBe(true);
191
+ if (result.isOk()) {
192
+ expect(result.value.modified).toEqual(['modified.ts']);
193
+ }
194
+ // Verify state was updated with new hash
195
+ const fileState = state.getFileState('modified.ts');
196
+ expect(fileState).toBeDefined();
197
+ expect(fileState?.contentHash).toBe(computeFileHash(newContent));
198
+ });
199
+ it('should remove deleted files from state', async () => {
200
+ const state = new IndexState();
201
+ state.setFileState('deleted.ts', {
202
+ filePath: 'deleted.ts',
203
+ contentHash: 'hash',
204
+ lastIndexedAt: new Date(),
205
+ chunkIds: ['c1'],
206
+ });
207
+ const indexer = new IncrementalIndexer(config, gitClient, state);
208
+ const changes = {
209
+ added: [],
210
+ modified: [],
211
+ deleted: ['deleted.ts'],
212
+ };
213
+ const result = await indexer.reindex(changes);
214
+ expect(result.isOk()).toBe(true);
215
+ if (result.isOk()) {
216
+ expect(result.value.deleted).toEqual(['deleted.ts']);
217
+ }
218
+ // Verify file was removed from state
219
+ expect(state.getFileState('deleted.ts')).toBeUndefined();
220
+ });
221
+ it('should track unchanged files', async () => {
222
+ const content = 'export const stable = true;';
223
+ writeFileSync(join(tempDir, 'stable.ts'), content);
224
+ writeFileSync(join(tempDir, 'new.ts'), 'new');
225
+ const state = new IndexState();
226
+ state.setFileState('stable.ts', {
227
+ filePath: 'stable.ts',
228
+ contentHash: computeFileHash(content),
229
+ lastIndexedAt: new Date(),
230
+ chunkIds: ['existing-chunk'],
231
+ });
232
+ const indexer = new IncrementalIndexer(config, gitClient, state);
233
+ const changes = {
234
+ added: ['new.ts'],
235
+ modified: [],
236
+ deleted: [],
237
+ };
238
+ const result = await indexer.reindex(changes);
239
+ expect(result.isOk()).toBe(true);
240
+ if (result.isOk()) {
241
+ expect(result.value.unchanged).toContain('stable.ts');
242
+ // 1 existing chunk from stable.ts + 1 new chunk from new.ts
243
+ expect(result.value.totalChunks).toBe(2);
244
+ }
245
+ });
246
+ it('should handle empty change set', async () => {
247
+ const state = new IndexState();
248
+ const indexer = new IncrementalIndexer(config, gitClient, state);
249
+ const changes = {
250
+ added: [],
251
+ modified: [],
252
+ deleted: [],
253
+ };
254
+ const result = await indexer.reindex(changes);
255
+ expect(result.isOk()).toBe(true);
256
+ if (result.isOk()) {
257
+ expect(result.value.added).toEqual([]);
258
+ expect(result.value.modified).toEqual([]);
259
+ expect(result.value.deleted).toEqual([]);
260
+ expect(result.value.unchanged).toEqual([]);
261
+ expect(result.value.totalChunks).toBe(0);
262
+ }
263
+ });
264
+ });
265
+ });
266
+ //# sourceMappingURL=incremental-indexer.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"incremental-indexer.test.js","sourceRoot":"","sources":["../../src/indexer/incremental-indexer.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Result of checking whether a CodeRAG index exists at a given storage path.
3
+ *
4
+ * - `exists: false` — no index has been built (missing LanceDB data or BM25 file)
5
+ * - `exists: true, empty: true` — index structure exists but contains 0 chunks
6
+ * - `exists: true, empty: false` — index exists and has chunks
7
+ */
8
+ export interface IndexCheckResult {
9
+ readonly exists: boolean;
10
+ readonly empty: boolean;
11
+ }
12
+ /**
13
+ * Check whether a CodeRAG index exists at the given storage path.
14
+ *
15
+ * Checks both:
16
+ * 1. LanceDB directory exists and contains data (has subdirectories/files)
17
+ * 2. BM25 index file exists (`bm25-index.json`)
18
+ *
19
+ * If both exist, reads the BM25 index to determine whether the index is empty
20
+ * (0 documents) or populated.
21
+ */
22
+ export declare function checkIndexExists(storagePath: string): Promise<IndexCheckResult>;
@@ -0,0 +1,74 @@
1
+ import { access, readFile, readdir } from 'node:fs/promises';
2
+ import { join } from 'node:path';
3
+ const BM25_INDEX_FILE = 'bm25-index.json';
4
+ /**
5
+ * Check whether a CodeRAG index exists at the given storage path.
6
+ *
7
+ * Checks both:
8
+ * 1. LanceDB directory exists and contains data (has subdirectories/files)
9
+ * 2. BM25 index file exists (`bm25-index.json`)
10
+ *
11
+ * If both exist, reads the BM25 index to determine whether the index is empty
12
+ * (0 documents) or populated.
13
+ */
14
+ export async function checkIndexExists(storagePath) {
15
+ const NO_INDEX = { exists: false, empty: false };
16
+ // Check if the storage directory itself exists
17
+ const dirExists = await fileExists(storagePath);
18
+ if (!dirExists) {
19
+ return NO_INDEX;
20
+ }
21
+ // Check if the directory has any LanceDB data (subdirectories or .lance files)
22
+ const hasLanceData = await directoryHasContent(storagePath);
23
+ if (!hasLanceData) {
24
+ return NO_INDEX;
25
+ }
26
+ // Check if BM25 index file exists
27
+ const bm25Path = join(storagePath, BM25_INDEX_FILE);
28
+ const bm25Exists = await fileExists(bm25Path);
29
+ if (!bm25Exists) {
30
+ return NO_INDEX;
31
+ }
32
+ // Both exist; check if BM25 index has any documents
33
+ const isEmpty = await isBm25Empty(bm25Path);
34
+ return { exists: true, empty: isEmpty };
35
+ }
36
+ async function fileExists(path) {
37
+ try {
38
+ await access(path);
39
+ return true;
40
+ }
41
+ catch {
42
+ return false;
43
+ }
44
+ }
45
+ async function directoryHasContent(dirPath) {
46
+ try {
47
+ const entries = await readdir(dirPath);
48
+ // Filter out just the BM25 file — we want actual LanceDB data
49
+ const dataEntries = entries.filter((e) => e !== BM25_INDEX_FILE && e !== 'graph.json');
50
+ return dataEntries.length > 0;
51
+ }
52
+ catch {
53
+ return false;
54
+ }
55
+ }
56
+ async function isBm25Empty(bm25Path) {
57
+ try {
58
+ const content = await readFile(bm25Path, 'utf-8');
59
+ const parsed = JSON.parse(content);
60
+ if (parsed !== null && typeof parsed === 'object' && !Array.isArray(parsed)) {
61
+ const record = parsed;
62
+ // MiniSearch JSON has a `documentCount` field
63
+ if (typeof record['documentCount'] === 'number') {
64
+ return record['documentCount'] === 0;
65
+ }
66
+ }
67
+ // If we cannot determine count, assume not empty (conservative)
68
+ return false;
69
+ }
70
+ catch {
71
+ // If BM25 file is corrupted or unreadable, treat as empty
72
+ return true;
73
+ }
74
+ }
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-check.js","sourceRoot":"","sources":["../../src/indexer/index-check.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAC7D,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAcjC,MAAM,eAAe,GAAG,iBAAiB,CAAC;AAE1C;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,WAAmB;IACxD,MAAM,QAAQ,GAAqB,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;IAEnE,+CAA+C;IAC/C,MAAM,SAAS,GAAG,MAAM,UAAU,CAAC,WAAW,CAAC,CAAC;IAChD,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,+EAA+E;IAC/E,MAAM,YAAY,GAAG,MAAM,mBAAmB,CAAC,WAAW,CAAC,CAAC;IAC5D,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,kCAAkC;IAClC,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,EAAE,eAAe,CAAC,CAAC;IACpD,MAAM,UAAU,GAAG,MAAM,UAAU,CAAC,QAAQ,CAAC,CAAC;IAC9C,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,oDAAoD;IACpD,MAAM,OAAO,GAAG,MAAM,WAAW,CAAC,QAAQ,CAAC,CAAC;IAE5C,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;AAC1C,CAAC;AAED,KAAK,UAAU,UAAU,CAAC,IAAY;IACpC,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,IAAI,CAAC,CAAC;QACnB,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,KAAK,UAAU,mBAAmB,CAAC,OAAe;IAChD,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;QACvC,8DAA8D;QAC9D,MAAM,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,eAAe,IAAI,CAAC,KAAK,YAAY,CAAC,CAAC;QACvF,OAAO,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC;IAChC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,KAAK,UAAU,WAAW,CAAC,QAAgB;IACzC,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QAClD,MAAM,MAAM,GAAY,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAC5C,IAAI,MAAM,KAAK,IAAI,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YAC5E,MAAM,MAAM,GAAG,MAAiC,CAAC;YACjD,8CAA8C;YAC9C,IAAI,OAAO,MAAM,CAAC,eAAe,CAAC,KAAK,QAAQ,EAAE,CAAC;gBAChD,OAAO,MAAM,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC;YACvC,CAAC;QACH,CAAC;QACD,gEAAgE;QAChE,OAAO,KAAK,CAAC;IACf,CAAC;IAAC,MAAM,CAAC;QACP,0DAA0D;QAC1D,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,100 @@
1
+ import { describe, it, expect, beforeEach, afterEach } from 'vitest';
2
+ import { mkdtemp, writeFile, mkdir, rm } from 'node:fs/promises';
3
+ import { join } from 'node:path';
4
+ import { tmpdir } from 'node:os';
5
+ import { checkIndexExists } from './index-check.js';
6
+ describe('checkIndexExists', () => {
7
+ let tempDir;
8
+ beforeEach(async () => {
9
+ tempDir = await mkdtemp(join(tmpdir(), 'coderag-index-check-'));
10
+ });
11
+ afterEach(async () => {
12
+ await rm(tempDir, { recursive: true, force: true });
13
+ });
14
+ it('should return exists:false when storage path does not exist', async () => {
15
+ const result = await checkIndexExists(join(tempDir, 'nonexistent'));
16
+ expect(result.exists).toBe(false);
17
+ expect(result.empty).toBe(false);
18
+ });
19
+ it('should return exists:false when storage directory is empty', async () => {
20
+ const storagePath = join(tempDir, '.coderag');
21
+ await mkdir(storagePath, { recursive: true });
22
+ const result = await checkIndexExists(storagePath);
23
+ expect(result.exists).toBe(false);
24
+ });
25
+ it('should return exists:false when only BM25 index exists (no LanceDB data)', async () => {
26
+ const storagePath = join(tempDir, '.coderag');
27
+ await mkdir(storagePath, { recursive: true });
28
+ await writeFile(join(storagePath, 'bm25-index.json'), '{"documentCount": 5}');
29
+ const result = await checkIndexExists(storagePath);
30
+ expect(result.exists).toBe(false);
31
+ });
32
+ it('should return exists:false when only LanceDB data exists (no BM25 file)', async () => {
33
+ const storagePath = join(tempDir, '.coderag');
34
+ await mkdir(join(storagePath, 'chunks.lance'), { recursive: true });
35
+ const result = await checkIndexExists(storagePath);
36
+ expect(result.exists).toBe(false);
37
+ });
38
+ it('should return exists:true, empty:false when both LanceDB and BM25 exist with data', async () => {
39
+ const storagePath = join(tempDir, '.coderag');
40
+ await mkdir(join(storagePath, 'chunks.lance'), { recursive: true });
41
+ await writeFile(join(storagePath, 'bm25-index.json'), '{"documentCount": 42}');
42
+ const result = await checkIndexExists(storagePath);
43
+ expect(result.exists).toBe(true);
44
+ expect(result.empty).toBe(false);
45
+ });
46
+ it('should return exists:true, empty:true when index exists but has 0 documents', async () => {
47
+ const storagePath = join(tempDir, '.coderag');
48
+ await mkdir(join(storagePath, 'chunks.lance'), { recursive: true });
49
+ await writeFile(join(storagePath, 'bm25-index.json'), '{"documentCount": 0}');
50
+ const result = await checkIndexExists(storagePath);
51
+ expect(result.exists).toBe(true);
52
+ expect(result.empty).toBe(true);
53
+ });
54
+ it('should ignore graph.json when checking for LanceDB content', async () => {
55
+ const storagePath = join(tempDir, '.coderag');
56
+ await mkdir(storagePath, { recursive: true });
57
+ await writeFile(join(storagePath, 'graph.json'), '{}');
58
+ await writeFile(join(storagePath, 'bm25-index.json'), '{"documentCount": 5}');
59
+ // Only graph.json and bm25-index.json exist — no actual LanceDB data
60
+ const result = await checkIndexExists(storagePath);
61
+ expect(result.exists).toBe(false);
62
+ });
63
+ it('should handle corrupted BM25 JSON gracefully', async () => {
64
+ const storagePath = join(tempDir, '.coderag');
65
+ await mkdir(join(storagePath, 'chunks.lance'), { recursive: true });
66
+ await writeFile(join(storagePath, 'bm25-index.json'), 'NOT VALID JSON');
67
+ const result = await checkIndexExists(storagePath);
68
+ expect(result.exists).toBe(true);
69
+ // Corrupted file treated as empty
70
+ expect(result.empty).toBe(true);
71
+ });
72
+ it('should handle BM25 JSON without documentCount field', async () => {
73
+ const storagePath = join(tempDir, '.coderag');
74
+ await mkdir(join(storagePath, 'chunks.lance'), { recursive: true });
75
+ await writeFile(join(storagePath, 'bm25-index.json'), '{"someOtherField": true}');
76
+ const result = await checkIndexExists(storagePath);
77
+ expect(result.exists).toBe(true);
78
+ // Cannot determine count; conservatively assume not empty
79
+ expect(result.empty).toBe(false);
80
+ });
81
+ it('should handle BM25 JSON that is an array', async () => {
82
+ const storagePath = join(tempDir, '.coderag');
83
+ await mkdir(join(storagePath, 'chunks.lance'), { recursive: true });
84
+ await writeFile(join(storagePath, 'bm25-index.json'), '[1,2,3]');
85
+ const result = await checkIndexExists(storagePath);
86
+ expect(result.exists).toBe(true);
87
+ // Array is not a recognized format; conservatively assume not empty
88
+ expect(result.empty).toBe(false);
89
+ });
90
+ it('should work with multiple LanceDB data entries', async () => {
91
+ const storagePath = join(tempDir, '.coderag');
92
+ await mkdir(join(storagePath, 'chunks.lance'), { recursive: true });
93
+ await mkdir(join(storagePath, '_versions'), { recursive: true });
94
+ await writeFile(join(storagePath, 'bm25-index.json'), '{"documentCount": 100}');
95
+ const result = await checkIndexExists(storagePath);
96
+ expect(result.exists).toBe(true);
97
+ expect(result.empty).toBe(false);
98
+ });
99
+ });
100
+ //# sourceMappingURL=index-check.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-check.test.js","sourceRoot":"","sources":["../../src/indexer/index-check.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AACrE,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAC;AACjE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAEpD,QAAQ,CAAC,kBAAkB,EAAE,GAAG,EAAE;IAChC,IAAI,OAAe,CAAC;IAEpB,UAAU,CAAC,KAAK,IAAI,EAAE;QACpB,OAAO,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,sBAAsB,CAAC,CAAC,CAAC;IAClE,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,KAAK,IAAI,EAAE;QACnB,MAAM,EAAE,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACtD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6DAA6D,EAAE,KAAK,IAAI,EAAE;QAC3E,MAAM,MAAM,GAAG,MAAM,gBAAgB,CAAC,IAAI,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC,CAAC;QACpE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAClC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACnC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4DAA4D,EAAE,KAAK,IAAI,EAAE;QAC1E,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;QAC9C,MAAM,KAAK,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAE9C,MAAM,MAAM,GAAG,MAAM,gBAAgB,CAAC,WAAW,CAAC,CAAC;QACnD,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACpC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0EAA0E,EAAE,KAAK,IAAI,EAAE;QACxF,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;QAC9C,MAAM,KAAK,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC9C,MAAM,SAAS,CAAC,IAAI,CAAC,WAAW,EAAE,iBAAiB,CAAC,EAAE,sBAAsB,CAAC,CAAC;QAE9E,MAAM,MAAM,GAAG,MAAM,gBAAgB,CAAC,WAAW,CAAC,CAAC;QACnD,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACpC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yEAAyE,EAAE,KAAK,IAAI,EAAE;QACvF,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;QAC9C,MAAM,KAAK,CAAC,IAAI,CAAC,WAAW,EAAE,cAAc,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAEpE,MAAM,MAAM,GAAG,MAAM,gBAAgB,CAAC,WAAW,CAAC,CAAC;QACnD,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACpC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mFAAmF,EAAE,KAAK,IAAI,EAAE;QACjG,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;QAC9C,MAAM,KAAK,CAAC,IAAI,CAAC,WAAW,EAAE,cAAc,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACpE,MAAM,SAAS,CAAC,IAAI,CAAC,WAAW,EAAE,iBAAiB,CAAC,EAAE,uBAAuB,CAAC,CAAC;QAE/E,MAAM,MAAM,GAAG,MAAM,gBAAgB,CAAC,WAAW,CAAC,CAAC;QACnD,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACjC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACnC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6EAA6E,EAAE,KAAK,IAAI,EAAE;QAC3F,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;QAC9C,MAAM,KAAK,CAAC,IAAI,CAAC,WAAW,EAAE,cAAc,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACpE,MAAM,SAAS,CAAC,IAAI,CAAC,WAAW,EAAE,iBAAiB,CAAC,EAAE,sBAAsB,CAAC,CAAC;QAE9E,MAAM,MAAM,GAAG,MAAM,gBAAgB,CAAC,WAAW,CAAC,CAAC;QACnD,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACjC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAClC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4DAA4D,EAAE,KAAK,IAAI,EAAE;QAC1E,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;QAC9C,MAAM,KAAK,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC9C,MAAM,SAAS,CAAC,IAAI,CAAC,WAAW,EAAE,YAAY,CAAC,EAAE,IAAI,CAAC,CAAC;QACvD,MAAM,SAAS,CAAC,IAAI,CAAC,WAAW,EAAE,iBAAiB,CAAC,EAAE,sBAAsB,CAAC,CAAC;QAE9E,qEAAqE;QACrE,MAAM,MAAM,GAAG,MAAM,gBAAgB,CAAC,WAAW,CAAC,CAAC;QACnD,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACpC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8CAA8C,EAAE,KAAK,IAAI,EAAE;QAC5D,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;QAC9C,MAAM,KAAK,CAAC,IAAI,CAAC,WAAW,EAAE,cAAc,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACpE,MAAM,SAAS,CAAC,IAAI,CAAC,WAAW,EAAE,iBAAiB,CAAC,EAAE,gBAAgB,CAAC,CAAC;QAExE,MAAM,MAAM,GAAG,MAAM,gBAAgB,CAAC,WAAW,CAAC,CAAC;QACnD,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACjC,kCAAkC;QAClC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAClC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qDAAqD,EAAE,KAAK,IAAI,EAAE;QACnE,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;QAC9C,MAAM,KAAK,CAAC,IAAI,CAAC,WAAW,EAAE,cAAc,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACpE,MAAM,SAAS,CAAC,IAAI,CAAC,WAAW,EAAE,iBAAiB,CAAC,EAAE,0BAA0B,CAAC,CAAC;QAElF,MAAM,MAAM,GAAG,MAAM,gBAAgB,CAAC,WAAW,CAAC,CAAC;QACnD,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACjC,0DAA0D;QAC1D,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACnC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0CAA0C,EAAE,KAAK,IAAI,EAAE;QACxD,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;QAC9C,MAAM,KAAK,CAAC,IAAI,CAAC,WAAW,EAAE,cAAc,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACpE,MAAM,SAAS,CAAC,IAAI,CAAC,WAAW,EAAE,iBAAiB,CAAC,EAAE,SAAS,CAAC,CAAC;QAEjE,MAAM,MAAM,GAAG,MAAM,gBAAgB,CAAC,WAAW,CAAC,CAAC;QACnD,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACjC,oEAAoE;QACpE,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACnC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gDAAgD,EAAE,KAAK,IAAI,EAAE;QAC9D,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;QAC9C,MAAM,KAAK,CAAC,IAAI,CAAC,WAAW,EAAE,cAAc,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACpE,MAAM,KAAK,CAAC,IAAI,CAAC,WAAW,EAAE,WAAW,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACjE,MAAM,SAAS,CAAC,IAAI,CAAC,WAAW,EAAE,iBAAiB,CAAC,EAAE,wBAAwB,CAAC,CAAC;QAEhF,MAAM,MAAM,GAAG,MAAM,gBAAgB,CAAC,WAAW,CAAC,CAAC;QACnD,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACjC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACnC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Represents the indexed state of a single file, including its content hash
3
+ * and the chunk IDs that were produced from it.
4
+ */
5
+ export interface IndexedFileState {
6
+ filePath: string;
7
+ contentHash: string;
8
+ lastIndexedAt: Date;
9
+ chunkIds: string[];
10
+ }
11
+ /**
12
+ * Serialized form of IndexedFileState where dates are ISO strings.
13
+ */
14
+ interface SerializedFileState {
15
+ filePath: string;
16
+ contentHash: string;
17
+ lastIndexedAt: string;
18
+ chunkIds: string[];
19
+ }
20
+ /**
21
+ * Compute a deterministic SHA-256 hash of file content.
22
+ */
23
+ export declare function computeFileHash(content: string): string;
24
+ /**
25
+ * Tracks which files have been indexed and their content hashes,
26
+ * enabling incremental re-indexing by detecting what has changed.
27
+ */
28
+ export declare class IndexState {
29
+ private readonly store;
30
+ constructor();
31
+ /**
32
+ * Retrieve the indexed state for a file, or undefined if not tracked.
33
+ */
34
+ getFileState(filePath: string): IndexedFileState | undefined;
35
+ /**
36
+ * Set or update the indexed state for a file.
37
+ */
38
+ setFileState(filePath: string, state: IndexedFileState): void;
39
+ /**
40
+ * Remove a file from the index state (e.g., when it has been deleted).
41
+ */
42
+ removeFile(filePath: string): void;
43
+ /**
44
+ * Return all file paths currently tracked in the index state.
45
+ */
46
+ getAllFiles(): string[];
47
+ /**
48
+ * Determine whether a file needs re-indexing.
49
+ * Returns true if the file is not in the index or its content hash differs.
50
+ */
51
+ isDirty(filePath: string, currentHash: string): boolean;
52
+ /**
53
+ * Serialize the index state to a plain JSON-compatible object.
54
+ */
55
+ toJSON(): Record<string, SerializedFileState>;
56
+ /**
57
+ * Deserialize an index state from a plain JSON object.
58
+ */
59
+ static fromJSON(data: Record<string, SerializedFileState>): IndexState;
60
+ }
61
+ export {};
@@ -0,0 +1,82 @@
1
+ import { createHash } from 'node:crypto';
2
+ /**
3
+ * Compute a deterministic SHA-256 hash of file content.
4
+ */
5
+ export function computeFileHash(content) {
6
+ return createHash('sha256').update(content).digest('hex');
7
+ }
8
+ /**
9
+ * Tracks which files have been indexed and their content hashes,
10
+ * enabling incremental re-indexing by detecting what has changed.
11
+ */
12
+ export class IndexState {
13
+ store;
14
+ constructor() {
15
+ this.store = new Map();
16
+ }
17
+ /**
18
+ * Retrieve the indexed state for a file, or undefined if not tracked.
19
+ */
20
+ getFileState(filePath) {
21
+ return this.store.get(filePath);
22
+ }
23
+ /**
24
+ * Set or update the indexed state for a file.
25
+ */
26
+ setFileState(filePath, state) {
27
+ this.store.set(filePath, state);
28
+ }
29
+ /**
30
+ * Remove a file from the index state (e.g., when it has been deleted).
31
+ */
32
+ removeFile(filePath) {
33
+ this.store.delete(filePath);
34
+ }
35
+ /**
36
+ * Return all file paths currently tracked in the index state.
37
+ */
38
+ getAllFiles() {
39
+ return [...this.store.keys()];
40
+ }
41
+ /**
42
+ * Determine whether a file needs re-indexing.
43
+ * Returns true if the file is not in the index or its content hash differs.
44
+ */
45
+ isDirty(filePath, currentHash) {
46
+ const existing = this.store.get(filePath);
47
+ if (existing === undefined) {
48
+ return true;
49
+ }
50
+ return existing.contentHash !== currentHash;
51
+ }
52
+ /**
53
+ * Serialize the index state to a plain JSON-compatible object.
54
+ */
55
+ toJSON() {
56
+ const result = {};
57
+ for (const [key, value] of this.store) {
58
+ result[key] = {
59
+ filePath: value.filePath,
60
+ contentHash: value.contentHash,
61
+ lastIndexedAt: value.lastIndexedAt.toISOString(),
62
+ chunkIds: [...value.chunkIds],
63
+ };
64
+ }
65
+ return result;
66
+ }
67
+ /**
68
+ * Deserialize an index state from a plain JSON object.
69
+ */
70
+ static fromJSON(data) {
71
+ const state = new IndexState();
72
+ for (const [key, value] of Object.entries(data)) {
73
+ state.setFileState(key, {
74
+ filePath: value.filePath,
75
+ contentHash: value.contentHash,
76
+ lastIndexedAt: new Date(value.lastIndexedAt),
77
+ chunkIds: [...value.chunkIds],
78
+ });
79
+ }
80
+ return state;
81
+ }
82
+ }
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-state.js","sourceRoot":"","sources":["../../src/indexer/index-state.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAuBzC;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,OAAe;IAC7C,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC5D,CAAC;AAED;;;GAGG;AACH,MAAM,OAAO,UAAU;IACJ,KAAK,CAAgC;IAEtD;QACE,IAAI,CAAC,KAAK,GAAG,IAAI,GAAG,EAAE,CAAC;IACzB,CAAC;IAED;;OAEG;IACH,YAAY,CAAC,QAAgB;QAC3B,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAClC,CAAC;IAED;;OAEG;IACH,YAAY,CAAC,QAAgB,EAAE,KAAuB;QACpD,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IAClC,CAAC;IAED;;OAEG;IACH,UAAU,CAAC,QAAgB;QACzB,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC9B,CAAC;IAED;;OAEG;IACH,WAAW;QACT,OAAO,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;IAChC,CAAC;IAED;;;OAGG;IACH,OAAO,CAAC,QAAgB,EAAE,WAAmB;QAC3C,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC1C,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;YAC3B,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,QAAQ,CAAC,WAAW,KAAK,WAAW,CAAC;IAC9C,CAAC;IAED;;OAEG;IACH,MAAM;QACJ,MAAM,MAAM,GAAwC,EAAE,CAAC;QACvD,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACtC,MAAM,CAAC,GAAG,CAAC,GAAG;gBACZ,QAAQ,EAAE,KAAK,CAAC,QAAQ;gBACxB,WAAW,EAAE,KAAK,CAAC,WAAW;gBAC9B,aAAa,EAAE,KAAK,CAAC,aAAa,CAAC,WAAW,EAAE;gBAChD,QAAQ,EAAE,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC;aAC9B,CAAC;QACJ,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,QAAQ,CAAC,IAAyC;QACvD,MAAM,KAAK,GAAG,IAAI,UAAU,EAAE,CAAC;QAC/B,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;YAChD,KAAK,CAAC,YAAY,CAAC,GAAG,EAAE;gBACtB,QAAQ,EAAE,KAAK,CAAC,QAAQ;gBACxB,WAAW,EAAE,KAAK,CAAC,WAAW;gBAC9B,aAAa,EAAE,IAAI,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC;gBAC5C,QAAQ,EAAE,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC;aAC9B,CAAC,CAAC;QACL,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;CACF"}
@@ -0,0 +1 @@
1
+ export {};