codevault 1.8.3 → 1.8.5

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 (479) hide show
  1. package/README.md +33 -5
  2. package/dist/chunking/file-grouper.d.ts +1 -1
  3. package/dist/chunking/file-grouper.d.ts.map +1 -1
  4. package/dist/chunking/file-grouper.js +3 -3
  5. package/dist/chunking/file-grouper.js.map +1 -1
  6. package/dist/chunking/semantic-chunker.d.ts +1 -1
  7. package/dist/chunking/semantic-chunker.d.ts.map +1 -1
  8. package/dist/chunking/token-counter.d.ts +1 -1
  9. package/dist/chunking/token-counter.d.ts.map +1 -1
  10. package/dist/chunking/token-counter.js +16 -10
  11. package/dist/chunking/token-counter.js.map +1 -1
  12. package/dist/cli/commands/ask-cmd.js +15 -15
  13. package/dist/cli/commands/ask-cmd.js.map +1 -1
  14. package/dist/cli/commands/chat-cmd.d.ts.map +1 -1
  15. package/dist/cli/commands/chat-cmd.js +40 -40
  16. package/dist/cli/commands/chat-cmd.js.map +1 -1
  17. package/dist/cli/commands/config-cmd.d.ts.map +1 -1
  18. package/dist/cli/commands/config-cmd.js +61 -52
  19. package/dist/cli/commands/config-cmd.js.map +1 -1
  20. package/dist/cli/commands/context.d.ts.map +1 -1
  21. package/dist/cli/commands/context.js +20 -11
  22. package/dist/cli/commands/context.js.map +1 -1
  23. package/dist/cli/commands/index-cmd.d.ts.map +1 -1
  24. package/dist/cli/commands/index-cmd.js +109 -85
  25. package/dist/cli/commands/index-cmd.js.map +1 -1
  26. package/dist/cli/commands/info-cmd.d.ts.map +1 -1
  27. package/dist/cli/commands/info-cmd.js +12 -11
  28. package/dist/cli/commands/info-cmd.js.map +1 -1
  29. package/dist/cli/commands/interactive-config.d.ts.map +1 -1
  30. package/dist/cli/commands/interactive-config.js +60 -20
  31. package/dist/cli/commands/interactive-config.js.map +1 -1
  32. package/dist/cli/commands/search-cmd.d.ts.map +1 -1
  33. package/dist/cli/commands/search-cmd.js +22 -11
  34. package/dist/cli/commands/search-cmd.js.map +1 -1
  35. package/dist/cli/commands/search-with-code-cmd.d.ts.map +1 -1
  36. package/dist/cli/commands/search-with-code-cmd.js +25 -16
  37. package/dist/cli/commands/search-with-code-cmd.js.map +1 -1
  38. package/dist/cli/commands/update-cmd.d.ts.map +1 -1
  39. package/dist/cli/commands/update-cmd.js +16 -7
  40. package/dist/cli/commands/update-cmd.js.map +1 -1
  41. package/dist/cli/commands/watch-cmd.d.ts.map +1 -1
  42. package/dist/cli/commands/watch-cmd.js +21 -11
  43. package/dist/cli/commands/watch-cmd.js.map +1 -1
  44. package/dist/cli/index.js.map +1 -1
  45. package/dist/cli/utils.d.ts +56 -0
  46. package/dist/cli/utils.d.ts.map +1 -0
  47. package/dist/cli/utils.js +98 -0
  48. package/dist/cli/utils.js.map +1 -0
  49. package/dist/cli.js +0 -0
  50. package/dist/codemap/io.js.map +1 -1
  51. package/dist/config/constants.d.ts +4 -0
  52. package/dist/config/constants.d.ts.map +1 -1
  53. package/dist/config/constants.js +2 -0
  54. package/dist/config/constants.js.map +1 -1
  55. package/dist/config/loader.js.map +1 -1
  56. package/dist/context/packs.d.ts +2 -2
  57. package/dist/context/packs.d.ts.map +1 -1
  58. package/dist/context/packs.js +7 -4
  59. package/dist/context/packs.js.map +1 -1
  60. package/dist/core/IndexerEngine.d.ts +2 -0
  61. package/dist/core/IndexerEngine.d.ts.map +1 -1
  62. package/dist/core/IndexerEngine.js +34 -26
  63. package/dist/core/IndexerEngine.js.map +1 -1
  64. package/dist/core/SearchService.d.ts +2 -1
  65. package/dist/core/SearchService.d.ts.map +1 -1
  66. package/dist/core/SearchService.js +25 -18
  67. package/dist/core/SearchService.js.map +1 -1
  68. package/dist/core/batch-indexer.d.ts +4 -3
  69. package/dist/core/batch-indexer.d.ts.map +1 -1
  70. package/dist/core/batch-indexer.js +32 -35
  71. package/dist/core/batch-indexer.js.map +1 -1
  72. package/dist/core/indexing/FileProcessor.d.ts +1 -0
  73. package/dist/core/indexing/FileProcessor.d.ts.map +1 -1
  74. package/dist/core/indexing/FileProcessor.js +32 -9
  75. package/dist/core/indexing/FileProcessor.js.map +1 -1
  76. package/dist/core/indexing/IndexContext.d.ts +6 -4
  77. package/dist/core/indexing/IndexContext.d.ts.map +1 -1
  78. package/dist/core/indexing/IndexContext.js +3 -3
  79. package/dist/core/indexing/IndexContext.js.map +1 -1
  80. package/dist/core/indexing/IndexFinalizationStage.d.ts +6 -1
  81. package/dist/core/indexing/IndexFinalizationStage.d.ts.map +1 -1
  82. package/dist/core/indexing/IndexFinalizationStage.js +22 -3
  83. package/dist/core/indexing/IndexFinalizationStage.js.map +1 -1
  84. package/dist/core/indexing/IndexState.d.ts +3 -8
  85. package/dist/core/indexing/IndexState.d.ts.map +1 -1
  86. package/dist/core/indexing/IndexState.js.map +1 -1
  87. package/dist/core/indexing/PersistManager.d.ts +1 -1
  88. package/dist/core/indexing/PersistManager.d.ts.map +1 -1
  89. package/dist/core/indexing/PersistManager.js +17 -17
  90. package/dist/core/indexing/PersistManager.js.map +1 -1
  91. package/dist/core/indexing/chunk-pipeline.d.ts +33 -7
  92. package/dist/core/indexing/chunk-pipeline.d.ts.map +1 -1
  93. package/dist/core/indexing/chunk-pipeline.js +20 -8
  94. package/dist/core/indexing/chunk-pipeline.js.map +1 -1
  95. package/dist/core/metadata.d.ts +1 -1
  96. package/dist/core/metadata.d.ts.map +1 -1
  97. package/dist/core/metadata.js +1 -1
  98. package/dist/core/metadata.js.map +1 -1
  99. package/dist/core/search/CandidateRetriever.d.ts +1 -1
  100. package/dist/core/search/CandidateRetriever.d.ts.map +1 -1
  101. package/dist/core/search/CandidateRetriever.js +7 -5
  102. package/dist/core/search/CandidateRetriever.js.map +1 -1
  103. package/dist/core/search/HybridFusion.d.ts +1 -2
  104. package/dist/core/search/HybridFusion.d.ts.map +1 -1
  105. package/dist/core/search/HybridFusion.js +5 -17
  106. package/dist/core/search/HybridFusion.js.map +1 -1
  107. package/dist/core/search/ResultMapper.d.ts +0 -1
  108. package/dist/core/search/ResultMapper.d.ts.map +1 -1
  109. package/dist/core/search/ResultMapper.js +3 -14
  110. package/dist/core/search/ResultMapper.js.map +1 -1
  111. package/dist/core/search/SearchContextManager.d.ts +4 -1
  112. package/dist/core/search/SearchContextManager.d.ts.map +1 -1
  113. package/dist/core/search/SearchContextManager.js +19 -6
  114. package/dist/core/search/SearchContextManager.js.map +1 -1
  115. package/dist/core/search.d.ts.map +1 -1
  116. package/dist/core/search.js +9 -4
  117. package/dist/core/search.js.map +1 -1
  118. package/dist/core/types.d.ts +2 -2
  119. package/dist/core/types.d.ts.map +1 -1
  120. package/dist/database/db.d.ts +14 -14
  121. package/dist/database/db.d.ts.map +1 -1
  122. package/dist/database/db.js +14 -14
  123. package/dist/database/db.js.map +1 -1
  124. package/dist/indexer/merkle.js +1 -1
  125. package/dist/indexer/merkle.js.map +1 -1
  126. package/dist/languages/rules.d.ts +2 -1
  127. package/dist/languages/rules.d.ts.map +1 -1
  128. package/dist/languages/rules.js +14 -5
  129. package/dist/languages/rules.js.map +1 -1
  130. package/dist/languages/tree-sitter-loader.d.ts +24 -24
  131. package/dist/languages/tree-sitter-loader.d.ts.map +1 -1
  132. package/dist/languages/tree-sitter-loader.js +14 -10
  133. package/dist/languages/tree-sitter-loader.js.map +1 -1
  134. package/dist/mcp/handlers/context.d.ts +5 -11
  135. package/dist/mcp/handlers/context.d.ts.map +1 -1
  136. package/dist/mcp/handlers/context.js.map +1 -1
  137. package/dist/mcp/handlers/project.d.ts +9 -27
  138. package/dist/mcp/handlers/project.d.ts.map +1 -1
  139. package/dist/mcp/handlers/search.d.ts +24 -18
  140. package/dist/mcp/handlers/search.d.ts.map +1 -1
  141. package/dist/mcp/handlers/search.js +8 -2
  142. package/dist/mcp/handlers/search.js.map +1 -1
  143. package/dist/mcp/handlers/synthesis.d.ts +15 -11
  144. package/dist/mcp/handlers/synthesis.d.ts.map +1 -1
  145. package/dist/mcp/handlers/synthesis.js +4 -1
  146. package/dist/mcp/handlers/synthesis.js.map +1 -1
  147. package/dist/mcp/schemas.d.ts +2 -2
  148. package/dist/mcp/tools/ask-codebase.d.ts +10 -28
  149. package/dist/mcp/tools/ask-codebase.d.ts.map +1 -1
  150. package/dist/mcp/tools/ask-codebase.js +1 -1
  151. package/dist/mcp/tools/ask-codebase.js.map +1 -1
  152. package/dist/mcp/tools/use-context-pack.d.ts +14 -23
  153. package/dist/mcp/tools/use-context-pack.d.ts.map +1 -1
  154. package/dist/mcp/tools/use-context-pack.js +4 -3
  155. package/dist/mcp/tools/use-context-pack.js.map +1 -1
  156. package/dist/mcp-server.d.ts +1 -0
  157. package/dist/mcp-server.d.ts.map +1 -1
  158. package/dist/mcp-server.js +39 -24
  159. package/dist/mcp-server.js.map +1 -1
  160. package/dist/providers/base.d.ts +3 -2
  161. package/dist/providers/base.d.ts.map +1 -1
  162. package/dist/providers/base.js +3 -10
  163. package/dist/providers/base.js.map +1 -1
  164. package/dist/providers/chat-llm.d.ts +3 -2
  165. package/dist/providers/chat-llm.d.ts.map +1 -1
  166. package/dist/providers/chat-llm.js +13 -9
  167. package/dist/providers/chat-llm.js.map +1 -1
  168. package/dist/providers/mock.d.ts.map +1 -1
  169. package/dist/providers/mock.js +6 -5
  170. package/dist/providers/mock.js.map +1 -1
  171. package/dist/providers/openai.d.ts +2 -1
  172. package/dist/providers/openai.d.ts.map +1 -1
  173. package/dist/providers/openai.js +15 -19
  174. package/dist/providers/openai.js.map +1 -1
  175. package/dist/providers/token-counter.d.ts.map +1 -1
  176. package/dist/providers/token-counter.js +11 -3
  177. package/dist/providers/token-counter.js.map +1 -1
  178. package/dist/ranking/api-reranker.d.ts +1 -1
  179. package/dist/ranking/api-reranker.d.ts.map +1 -1
  180. package/dist/ranking/api-reranker.js +50 -13
  181. package/dist/ranking/api-reranker.js.map +1 -1
  182. package/dist/ranking/symbol-boost.d.ts.map +1 -1
  183. package/dist/ranking/symbol-boost.js +4 -11
  184. package/dist/ranking/symbol-boost.js.map +1 -1
  185. package/dist/search/bm25.d.ts +10 -0
  186. package/dist/search/bm25.d.ts.map +1 -1
  187. package/dist/search/bm25.js +16 -0
  188. package/dist/search/bm25.js.map +1 -1
  189. package/dist/search/hybrid.js.map +1 -1
  190. package/dist/search/scope.d.ts.map +1 -1
  191. package/dist/search/scope.js +3 -2
  192. package/dist/search/scope.js.map +1 -1
  193. package/dist/storage/encrypted-chunks.d.ts +3 -0
  194. package/dist/storage/encrypted-chunks.d.ts.map +1 -1
  195. package/dist/storage/encrypted-chunks.js +126 -47
  196. package/dist/storage/encrypted-chunks.js.map +1 -1
  197. package/dist/symbols/extract.d.ts.map +1 -1
  198. package/dist/symbols/extract.js +3 -2
  199. package/dist/symbols/extract.js.map +1 -1
  200. package/dist/symbols/graph.d.ts.map +1 -1
  201. package/dist/symbols/graph.js +14 -8
  202. package/dist/symbols/graph.js.map +1 -1
  203. package/dist/synthesis/conversational-synthesizer.d.ts +2 -1
  204. package/dist/synthesis/conversational-synthesizer.d.ts.map +1 -1
  205. package/dist/synthesis/conversational-synthesizer.js +6 -1
  206. package/dist/synthesis/conversational-synthesizer.js.map +1 -1
  207. package/dist/synthesis/markdown-formatter.d.ts.map +1 -1
  208. package/dist/synthesis/markdown-formatter.js +1 -1
  209. package/dist/synthesis/markdown-formatter.js.map +1 -1
  210. package/dist/synthesis/prompt-builder.d.ts.map +1 -1
  211. package/dist/synthesis/prompt-builder.js +42 -15
  212. package/dist/synthesis/prompt-builder.js.map +1 -1
  213. package/dist/synthesis/synthesizer.d.ts.map +1 -1
  214. package/dist/synthesis/synthesizer.js +23 -10
  215. package/dist/synthesis/synthesizer.js.map +1 -1
  216. package/dist/tests/api-reranker.test.d.ts +2 -0
  217. package/dist/tests/api-reranker.test.d.ts.map +1 -0
  218. package/dist/tests/api-reranker.test.js +575 -0
  219. package/dist/tests/api-reranker.test.js.map +1 -0
  220. package/dist/tests/bm25.test.d.ts +2 -0
  221. package/dist/tests/bm25.test.d.ts.map +1 -0
  222. package/dist/tests/bm25.test.js +340 -0
  223. package/dist/tests/bm25.test.js.map +1 -0
  224. package/dist/tests/chunking/file-grouper.test.d.ts +2 -0
  225. package/dist/tests/chunking/file-grouper.test.d.ts.map +1 -0
  226. package/dist/tests/chunking/file-grouper.test.js +495 -0
  227. package/dist/tests/chunking/file-grouper.test.js.map +1 -0
  228. package/dist/tests/chunking/semantic-chunker.test.d.ts +2 -0
  229. package/dist/tests/chunking/semantic-chunker.test.d.ts.map +1 -0
  230. package/dist/tests/chunking/semantic-chunker.test.js +509 -0
  231. package/dist/tests/chunking/semantic-chunker.test.js.map +1 -0
  232. package/dist/tests/chunking/token-counter.test.d.ts +2 -0
  233. package/dist/tests/chunking/token-counter.test.d.ts.map +1 -0
  234. package/dist/tests/chunking/token-counter.test.js +441 -0
  235. package/dist/tests/chunking/token-counter.test.js.map +1 -0
  236. package/dist/tests/cli/ask-cmd.test.d.ts +2 -0
  237. package/dist/tests/cli/ask-cmd.test.d.ts.map +1 -0
  238. package/dist/tests/cli/ask-cmd.test.js +152 -0
  239. package/dist/tests/cli/ask-cmd.test.js.map +1 -0
  240. package/dist/tests/cli/chat-cmd.test.d.ts +2 -0
  241. package/dist/tests/cli/chat-cmd.test.d.ts.map +1 -0
  242. package/dist/tests/cli/chat-cmd.test.js +118 -0
  243. package/dist/tests/cli/chat-cmd.test.js.map +1 -0
  244. package/dist/tests/cli/config-cmd.test.d.ts +2 -0
  245. package/dist/tests/cli/config-cmd.test.d.ts.map +1 -0
  246. package/dist/tests/cli/config-cmd.test.js +226 -0
  247. package/dist/tests/cli/config-cmd.test.js.map +1 -0
  248. package/dist/tests/cli/context.test.d.ts +2 -0
  249. package/dist/tests/cli/context.test.d.ts.map +1 -0
  250. package/dist/tests/cli/context.test.js +158 -0
  251. package/dist/tests/cli/context.test.js.map +1 -0
  252. package/dist/tests/cli/index-cmd.test.d.ts +2 -0
  253. package/dist/tests/cli/index-cmd.test.d.ts.map +1 -0
  254. package/dist/tests/cli/index-cmd.test.js +89 -0
  255. package/dist/tests/cli/index-cmd.test.js.map +1 -0
  256. package/dist/tests/cli/index.test.d.ts +2 -0
  257. package/dist/tests/cli/index.test.d.ts.map +1 -0
  258. package/dist/tests/cli/index.test.js +167 -0
  259. package/dist/tests/cli/index.test.js.map +1 -0
  260. package/dist/tests/cli/info-cmd.test.d.ts +2 -0
  261. package/dist/tests/cli/info-cmd.test.d.ts.map +1 -0
  262. package/dist/tests/cli/info-cmd.test.js +47 -0
  263. package/dist/tests/cli/info-cmd.test.js.map +1 -0
  264. package/dist/tests/cli/interactive-config.test.d.ts +2 -0
  265. package/dist/tests/cli/interactive-config.test.d.ts.map +1 -0
  266. package/dist/tests/cli/interactive-config.test.js +30 -0
  267. package/dist/tests/cli/interactive-config.test.js.map +1 -0
  268. package/dist/tests/cli/mcp-cmd.test.d.ts +2 -0
  269. package/dist/tests/cli/mcp-cmd.test.d.ts.map +1 -0
  270. package/dist/tests/cli/mcp-cmd.test.js +47 -0
  271. package/dist/tests/cli/mcp-cmd.test.js.map +1 -0
  272. package/dist/tests/cli/search-cmd.test.d.ts +2 -0
  273. package/dist/tests/cli/search-cmd.test.d.ts.map +1 -0
  274. package/dist/tests/cli/search-cmd.test.js +120 -0
  275. package/dist/tests/cli/search-cmd.test.js.map +1 -0
  276. package/dist/tests/cli/search-with-code-cmd.test.d.ts +2 -0
  277. package/dist/tests/cli/search-with-code-cmd.test.d.ts.map +1 -0
  278. package/dist/tests/cli/search-with-code-cmd.test.js +140 -0
  279. package/dist/tests/cli/search-with-code-cmd.test.js.map +1 -0
  280. package/dist/tests/cli/update-cmd.test.d.ts +2 -0
  281. package/dist/tests/cli/update-cmd.test.d.ts.map +1 -0
  282. package/dist/tests/cli/update-cmd.test.js +75 -0
  283. package/dist/tests/cli/update-cmd.test.js.map +1 -0
  284. package/dist/tests/cli/utils.test.d.ts +2 -0
  285. package/dist/tests/cli/utils.test.d.ts.map +1 -0
  286. package/dist/tests/cli/utils.test.js +119 -0
  287. package/dist/tests/cli/utils.test.js.map +1 -0
  288. package/dist/tests/cli/watch-cmd.test.d.ts +2 -0
  289. package/dist/tests/cli/watch-cmd.test.d.ts.map +1 -0
  290. package/dist/tests/cli/watch-cmd.test.js +84 -0
  291. package/dist/tests/cli/watch-cmd.test.js.map +1 -0
  292. package/dist/tests/cli-ui.test.d.ts +2 -0
  293. package/dist/tests/cli-ui.test.d.ts.map +1 -0
  294. package/dist/tests/cli-ui.test.js +608 -0
  295. package/dist/tests/cli-ui.test.js.map +1 -0
  296. package/dist/tests/codemap-io.test.d.ts +2 -0
  297. package/dist/tests/codemap-io.test.d.ts.map +1 -0
  298. package/dist/tests/codemap-io.test.js +992 -0
  299. package/dist/tests/codemap-io.test.js.map +1 -0
  300. package/dist/tests/config/apply-env.test.d.ts +2 -0
  301. package/dist/tests/config/apply-env.test.d.ts.map +1 -0
  302. package/dist/tests/config/apply-env.test.js +717 -0
  303. package/dist/tests/config/apply-env.test.js.map +1 -0
  304. package/dist/tests/config/constants.test.d.ts +2 -0
  305. package/dist/tests/config/constants.test.d.ts.map +1 -0
  306. package/dist/tests/config/constants.test.js +406 -0
  307. package/dist/tests/config/constants.test.js.map +1 -0
  308. package/dist/tests/config/loader.test.d.ts +2 -0
  309. package/dist/tests/config/loader.test.d.ts.map +1 -0
  310. package/dist/tests/config/loader.test.js +716 -0
  311. package/dist/tests/config/loader.test.js.map +1 -0
  312. package/dist/tests/config/resolver.test.d.ts +2 -0
  313. package/dist/tests/config/resolver.test.d.ts.map +1 -0
  314. package/dist/tests/config/resolver.test.js +402 -0
  315. package/dist/tests/config/resolver.test.js.map +1 -0
  316. package/dist/tests/config/types.test.d.ts +2 -0
  317. package/dist/tests/config/types.test.d.ts.map +1 -0
  318. package/dist/tests/config/types.test.js +460 -0
  319. package/dist/tests/config/types.test.js.map +1 -0
  320. package/dist/tests/context-packs.test.d.ts +2 -0
  321. package/dist/tests/context-packs.test.d.ts.map +1 -0
  322. package/dist/tests/context-packs.test.js +826 -0
  323. package/dist/tests/context-packs.test.js.map +1 -0
  324. package/dist/tests/conversational-synthesizer.test.d.ts +2 -0
  325. package/dist/tests/conversational-synthesizer.test.d.ts.map +1 -0
  326. package/dist/tests/conversational-synthesizer.test.js +595 -0
  327. package/dist/tests/conversational-synthesizer.test.js.map +1 -0
  328. package/dist/tests/database.test.d.ts +2 -0
  329. package/dist/tests/database.test.d.ts.map +1 -0
  330. package/dist/tests/database.test.js +965 -0
  331. package/dist/tests/database.test.js.map +1 -0
  332. package/dist/tests/encrypted-chunks.test.d.ts +2 -0
  333. package/dist/tests/encrypted-chunks.test.d.ts.map +1 -0
  334. package/dist/tests/encrypted-chunks.test.js +1470 -0
  335. package/dist/tests/encrypted-chunks.test.js.map +1 -0
  336. package/dist/tests/hybrid.test.d.ts +2 -0
  337. package/dist/tests/hybrid.test.d.ts.map +1 -0
  338. package/dist/tests/hybrid.test.js +456 -0
  339. package/dist/tests/hybrid.test.js.map +1 -0
  340. package/dist/tests/indexer/ChangeQueue.test.d.ts +12 -0
  341. package/dist/tests/indexer/ChangeQueue.test.d.ts.map +1 -0
  342. package/dist/tests/indexer/ChangeQueue.test.js +441 -0
  343. package/dist/tests/indexer/ChangeQueue.test.js.map +1 -0
  344. package/dist/tests/indexer/ProviderManager.test.d.ts +12 -0
  345. package/dist/tests/indexer/ProviderManager.test.d.ts.map +1 -0
  346. package/dist/tests/indexer/ProviderManager.test.js +290 -0
  347. package/dist/tests/indexer/ProviderManager.test.js.map +1 -0
  348. package/dist/tests/indexer/WatchService.test.d.ts +14 -0
  349. package/dist/tests/indexer/WatchService.test.d.ts.map +1 -0
  350. package/dist/tests/indexer/WatchService.test.js +667 -0
  351. package/dist/tests/indexer/WatchService.test.js.map +1 -0
  352. package/dist/tests/indexer/merkle.test.d.ts +11 -0
  353. package/dist/tests/indexer/merkle.test.d.ts.map +1 -0
  354. package/dist/tests/indexer/merkle.test.js +497 -0
  355. package/dist/tests/indexer/merkle.test.js.map +1 -0
  356. package/dist/tests/indexer/update.test.d.ts +10 -0
  357. package/dist/tests/indexer/update.test.d.ts.map +1 -0
  358. package/dist/tests/indexer/update.test.js +317 -0
  359. package/dist/tests/indexer/update.test.js.map +1 -0
  360. package/dist/tests/indexer/watch.test.d.ts +8 -0
  361. package/dist/tests/indexer/watch.test.d.ts.map +1 -0
  362. package/dist/tests/indexer/watch.test.js +95 -0
  363. package/dist/tests/indexer/watch.test.js.map +1 -0
  364. package/dist/tests/integration/index-search.integration.test.js +6 -4
  365. package/dist/tests/integration/index-search.integration.test.js.map +1 -1
  366. package/dist/tests/languages.test.d.ts +2 -0
  367. package/dist/tests/languages.test.d.ts.map +1 -0
  368. package/dist/tests/languages.test.js +575 -0
  369. package/dist/tests/languages.test.js.map +1 -0
  370. package/dist/tests/logger-redaction.test.d.ts +2 -0
  371. package/dist/tests/logger-redaction.test.d.ts.map +1 -0
  372. package/dist/tests/logger-redaction.test.js +48 -0
  373. package/dist/tests/logger-redaction.test.js.map +1 -0
  374. package/dist/tests/logger.test.d.ts +2 -0
  375. package/dist/tests/logger.test.d.ts.map +1 -0
  376. package/dist/tests/logger.test.js +468 -0
  377. package/dist/tests/logger.test.js.map +1 -0
  378. package/dist/tests/markdown-formatter.test.d.ts +2 -0
  379. package/dist/tests/markdown-formatter.test.d.ts.map +1 -0
  380. package/dist/tests/markdown-formatter.test.js +453 -0
  381. package/dist/tests/markdown-formatter.test.js.map +1 -0
  382. package/dist/tests/mcp/tools/use-context-pack.test.d.ts +7 -0
  383. package/dist/tests/mcp/tools/use-context-pack.test.d.ts.map +1 -0
  384. package/dist/tests/mcp/tools/use-context-pack.test.js +505 -0
  385. package/dist/tests/mcp/tools/use-context-pack.test.js.map +1 -0
  386. package/dist/tests/mutex.test.d.ts +2 -0
  387. package/dist/tests/mutex.test.d.ts.map +1 -0
  388. package/dist/tests/mutex.test.js +489 -0
  389. package/dist/tests/mutex.test.js.map +1 -0
  390. package/dist/tests/path-helpers.test.d.ts +2 -0
  391. package/dist/tests/path-helpers.test.d.ts.map +1 -0
  392. package/dist/tests/path-helpers.test.js +332 -0
  393. package/dist/tests/path-helpers.test.js.map +1 -0
  394. package/dist/tests/prompt-builder.test.d.ts +2 -0
  395. package/dist/tests/prompt-builder.test.d.ts.map +1 -0
  396. package/dist/tests/prompt-builder.test.js +417 -0
  397. package/dist/tests/prompt-builder.test.js.map +1 -0
  398. package/dist/tests/providers/base.test.d.ts +2 -0
  399. package/dist/tests/providers/base.test.d.ts.map +1 -0
  400. package/dist/tests/providers/base.test.js +299 -0
  401. package/dist/tests/providers/base.test.js.map +1 -0
  402. package/dist/tests/providers/chat-llm.test.d.ts +2 -0
  403. package/dist/tests/providers/chat-llm.test.d.ts.map +1 -0
  404. package/dist/tests/providers/chat-llm.test.js +435 -0
  405. package/dist/tests/providers/chat-llm.test.js.map +1 -0
  406. package/dist/tests/providers/index.test.d.ts +2 -0
  407. package/dist/tests/providers/index.test.d.ts.map +1 -0
  408. package/dist/tests/providers/index.test.js +204 -0
  409. package/dist/tests/providers/index.test.js.map +1 -0
  410. package/dist/tests/providers/mock.test.d.ts +2 -0
  411. package/dist/tests/providers/mock.test.d.ts.map +1 -0
  412. package/dist/tests/providers/mock.test.js +225 -0
  413. package/dist/tests/providers/mock.test.js.map +1 -0
  414. package/dist/tests/providers/openai.test.d.ts +2 -0
  415. package/dist/tests/providers/openai.test.d.ts.map +1 -0
  416. package/dist/tests/providers/openai.test.js +408 -0
  417. package/dist/tests/providers/openai.test.js.map +1 -0
  418. package/dist/tests/providers/token-counter.test.d.ts +2 -0
  419. package/dist/tests/providers/token-counter.test.d.ts.map +1 -0
  420. package/dist/tests/providers/token-counter.test.js +247 -0
  421. package/dist/tests/providers/token-counter.test.js.map +1 -0
  422. package/dist/tests/rate-limiter.test.js +392 -1
  423. package/dist/tests/rate-limiter.test.js.map +1 -1
  424. package/dist/tests/scope.test.d.ts +2 -0
  425. package/dist/tests/scope.test.d.ts.map +1 -0
  426. package/dist/tests/scope.test.js +529 -0
  427. package/dist/tests/scope.test.js.map +1 -0
  428. package/dist/tests/search-normalization.test.js.map +1 -1
  429. package/dist/tests/semantic-chunker.test.js.map +1 -1
  430. package/dist/tests/simple-lru.test.js +377 -0
  431. package/dist/tests/simple-lru.test.js.map +1 -1
  432. package/dist/tests/symbol-boost.test.js +730 -10
  433. package/dist/tests/symbol-boost.test.js.map +1 -1
  434. package/dist/tests/symbols-extract.test.d.ts +2 -0
  435. package/dist/tests/symbols-extract.test.d.ts.map +1 -0
  436. package/dist/tests/symbols-extract.test.js +536 -0
  437. package/dist/tests/symbols-extract.test.js.map +1 -0
  438. package/dist/tests/symbols-graph.test.d.ts +2 -0
  439. package/dist/tests/symbols-graph.test.d.ts.map +1 -0
  440. package/dist/tests/symbols-graph.test.js +656 -0
  441. package/dist/tests/symbols-graph.test.js.map +1 -0
  442. package/dist/tests/synthesizer.test.d.ts +2 -0
  443. package/dist/tests/synthesizer.test.d.ts.map +1 -0
  444. package/dist/tests/synthesizer.test.js +381 -0
  445. package/dist/tests/synthesizer.test.js.map +1 -0
  446. package/dist/types/codemap.d.ts +2 -2
  447. package/dist/types/codemap.d.ts.map +1 -1
  448. package/dist/types/codemap.js +17 -9
  449. package/dist/types/codemap.js.map +1 -1
  450. package/dist/types/context-pack.d.ts +5 -5
  451. package/dist/types/context-pack.d.ts.map +1 -1
  452. package/dist/types/context-pack.js +6 -3
  453. package/dist/types/context-pack.js.map +1 -1
  454. package/dist/utils/cli-ui.d.ts +1 -1
  455. package/dist/utils/cli-ui.d.ts.map +1 -1
  456. package/dist/utils/cli-ui.js +26 -26
  457. package/dist/utils/cli-ui.js.map +1 -1
  458. package/dist/utils/indexer-with-progress.d.ts.map +1 -1
  459. package/dist/utils/indexer-with-progress.js +0 -6
  460. package/dist/utils/indexer-with-progress.js.map +1 -1
  461. package/dist/utils/logger.d.ts +10 -1
  462. package/dist/utils/logger.d.ts.map +1 -1
  463. package/dist/utils/logger.js +158 -6
  464. package/dist/utils/logger.js.map +1 -1
  465. package/dist/utils/mutex.d.ts +7 -2
  466. package/dist/utils/mutex.d.ts.map +1 -1
  467. package/dist/utils/mutex.js +35 -7
  468. package/dist/utils/mutex.js.map +1 -1
  469. package/dist/utils/path-helpers.d.ts.map +1 -1
  470. package/dist/utils/path-helpers.js +5 -2
  471. package/dist/utils/path-helpers.js.map +1 -1
  472. package/dist/utils/rate-limiter.d.ts.map +1 -1
  473. package/dist/utils/rate-limiter.js +23 -4
  474. package/dist/utils/rate-limiter.js.map +1 -1
  475. package/dist/utils/simple-lru.d.ts +6 -0
  476. package/dist/utils/simple-lru.d.ts.map +1 -1
  477. package/dist/utils/simple-lru.js +26 -0
  478. package/dist/utils/simple-lru.js.map +1 -1
  479. package/package.json +1 -1
@@ -0,0 +1,667 @@
1
+ /**
2
+ * Unit tests for src/indexer/WatchService.ts
3
+ *
4
+ * Tests file system watching and debounced change detection including:
5
+ * - WatchService construction and configuration
6
+ * - File event handling (add, change, unlink)
7
+ * - Extension filtering
8
+ * - Debounce configuration
9
+ * - Controller interface
10
+ * - startWatch helper function
11
+ * - Cleanup and resource management
12
+ */
13
+ import test from 'node:test';
14
+ import assert from 'node:assert/strict';
15
+ import { setTimeout as delay } from 'timers/promises';
16
+ import path from 'path';
17
+ import fs from 'fs';
18
+ import os from 'os';
19
+ import { WatchService, startWatch } from '../../indexer/WatchService.js';
20
+ // Helper to create a temporary directory for testing
21
+ async function createTempDir() {
22
+ const root = await fs.promises.mkdtemp(path.join(os.tmpdir(), 'watchservice-test-'));
23
+ // Create src directory for test files
24
+ await fs.promises.mkdir(path.join(root, 'src'), { recursive: true });
25
+ return {
26
+ root,
27
+ cleanup: async () => {
28
+ await fs.promises.rm(root, { recursive: true, force: true });
29
+ }
30
+ };
31
+ }
32
+ // Helper to create a test file
33
+ async function writeTestFile(root, relativePath, content) {
34
+ const fullPath = path.join(root, relativePath);
35
+ await fs.promises.mkdir(path.dirname(fullPath), { recursive: true });
36
+ await fs.promises.writeFile(fullPath, content);
37
+ }
38
+ // Mock logger that captures calls
39
+ function createMockLogger() {
40
+ const errors = [];
41
+ const logs = [];
42
+ return {
43
+ log: (...args) => { logs.push(args); },
44
+ error: (...args) => { errors.push(args); },
45
+ warn: () => { },
46
+ info: () => { },
47
+ debug: () => { },
48
+ errors,
49
+ logs
50
+ };
51
+ }
52
+ // ============================================================================
53
+ // WatchService Construction Tests
54
+ // ============================================================================
55
+ test('WatchService can be constructed with minimal options', async () => {
56
+ const tmpDir = await createTempDir();
57
+ try {
58
+ const service = new WatchService({ repoPath: tmpDir.root });
59
+ assert.ok(service, 'Service should be created');
60
+ await service.close();
61
+ }
62
+ finally {
63
+ await tmpDir.cleanup();
64
+ }
65
+ });
66
+ test('WatchService can be constructed with empty options', async () => {
67
+ // Uses cwd as default
68
+ const service = new WatchService({});
69
+ assert.ok(service, 'Service should be created with empty options');
70
+ await service.close();
71
+ });
72
+ test('WatchService accepts custom debounce option', async () => {
73
+ const tmpDir = await createTempDir();
74
+ try {
75
+ const service = new WatchService({
76
+ repoPath: tmpDir.root,
77
+ debounceMs: 100
78
+ });
79
+ assert.ok(service, 'Service with custom debounce should be created');
80
+ await service.close();
81
+ }
82
+ finally {
83
+ await tmpDir.cleanup();
84
+ }
85
+ });
86
+ test('WatchService enforces minimum debounce', async () => {
87
+ const tmpDir = await createTempDir();
88
+ try {
89
+ // Very small debounce should be clamped to minimum
90
+ const service = new WatchService({
91
+ repoPath: tmpDir.root,
92
+ debounceMs: 1 // Very small
93
+ });
94
+ assert.ok(service, 'Service should handle very small debounce');
95
+ await service.close();
96
+ }
97
+ finally {
98
+ await tmpDir.cleanup();
99
+ }
100
+ });
101
+ test('WatchService accepts custom logger', async () => {
102
+ const tmpDir = await createTempDir();
103
+ const logger = createMockLogger();
104
+ try {
105
+ const service = new WatchService({
106
+ repoPath: tmpDir.root,
107
+ logger
108
+ });
109
+ assert.ok(service, 'Service with custom logger should be created');
110
+ await service.close();
111
+ }
112
+ finally {
113
+ await tmpDir.cleanup();
114
+ }
115
+ });
116
+ test('WatchService accepts custom provider option', async () => {
117
+ const tmpDir = await createTempDir();
118
+ try {
119
+ const service = new WatchService({
120
+ repoPath: tmpDir.root,
121
+ provider: 'mock'
122
+ });
123
+ assert.ok(service, 'Service with custom provider should be created');
124
+ await service.close();
125
+ }
126
+ finally {
127
+ await tmpDir.cleanup();
128
+ }
129
+ });
130
+ test('WatchService accepts encryption option', async () => {
131
+ const tmpDir = await createTempDir();
132
+ try {
133
+ const service = new WatchService({
134
+ repoPath: tmpDir.root,
135
+ encrypt: 'off'
136
+ });
137
+ assert.ok(service, 'Service with encryption option should be created');
138
+ await service.close();
139
+ }
140
+ finally {
141
+ await tmpDir.cleanup();
142
+ }
143
+ });
144
+ test('WatchService accepts concurrency option', async () => {
145
+ const tmpDir = await createTempDir();
146
+ try {
147
+ const service = new WatchService({
148
+ repoPath: tmpDir.root,
149
+ concurrency: 10
150
+ });
151
+ assert.ok(service, 'Service with concurrency option should be created');
152
+ await service.close();
153
+ }
154
+ finally {
155
+ await tmpDir.cleanup();
156
+ }
157
+ });
158
+ test('WatchService accepts onBatch callback', async () => {
159
+ const tmpDir = await createTempDir();
160
+ let batchCalled = false;
161
+ try {
162
+ const service = new WatchService({
163
+ repoPath: tmpDir.root,
164
+ onBatch: () => { batchCalled = true; }
165
+ });
166
+ assert.ok(service, 'Service with onBatch should be created');
167
+ await service.close();
168
+ }
169
+ finally {
170
+ await tmpDir.cleanup();
171
+ }
172
+ });
173
+ // ============================================================================
174
+ // waitForReady Tests
175
+ // ============================================================================
176
+ test('WatchService waitForReady resolves when watcher is ready', async () => {
177
+ const tmpDir = await createTempDir();
178
+ try {
179
+ const service = new WatchService({ repoPath: tmpDir.root });
180
+ await service.waitForReady();
181
+ assert.ok(true, 'waitForReady should resolve');
182
+ await service.close();
183
+ }
184
+ finally {
185
+ await tmpDir.cleanup();
186
+ }
187
+ });
188
+ test('WatchService waitForReady can be called multiple times', async () => {
189
+ const tmpDir = await createTempDir();
190
+ try {
191
+ const service = new WatchService({ repoPath: tmpDir.root });
192
+ await service.waitForReady();
193
+ await service.waitForReady();
194
+ await service.waitForReady();
195
+ assert.ok(true, 'Multiple waitForReady calls should work');
196
+ await service.close();
197
+ }
198
+ finally {
199
+ await tmpDir.cleanup();
200
+ }
201
+ });
202
+ // ============================================================================
203
+ // getController Tests
204
+ // ============================================================================
205
+ test('WatchService getController returns valid controller', async () => {
206
+ const tmpDir = await createTempDir();
207
+ try {
208
+ const service = new WatchService({ repoPath: tmpDir.root });
209
+ const controller = service.getController();
210
+ assert.ok(controller.watcher, 'Controller should have watcher');
211
+ assert.ok(controller.ready instanceof Promise, 'Controller should have ready promise');
212
+ assert.equal(typeof controller.close, 'function', 'Controller should have close method');
213
+ assert.equal(typeof controller.flush, 'function', 'Controller should have flush method');
214
+ await service.close();
215
+ }
216
+ finally {
217
+ await tmpDir.cleanup();
218
+ }
219
+ });
220
+ test('WatchService controller close triggers service close', async () => {
221
+ const tmpDir = await createTempDir();
222
+ try {
223
+ const service = new WatchService({ repoPath: tmpDir.root });
224
+ const controller = service.getController();
225
+ await controller.ready;
226
+ await controller.close();
227
+ assert.ok(true, 'Controller close should work');
228
+ }
229
+ finally {
230
+ await tmpDir.cleanup();
231
+ }
232
+ });
233
+ test('WatchService controller flush triggers service flush', async () => {
234
+ const tmpDir = await createTempDir();
235
+ try {
236
+ const service = new WatchService({ repoPath: tmpDir.root });
237
+ const controller = service.getController();
238
+ await controller.ready;
239
+ await controller.flush();
240
+ assert.ok(true, 'Controller flush should work');
241
+ await controller.close();
242
+ }
243
+ finally {
244
+ await tmpDir.cleanup();
245
+ }
246
+ });
247
+ // ============================================================================
248
+ // startWatch Helper Tests
249
+ // ============================================================================
250
+ test('startWatch returns valid controller', async () => {
251
+ const tmpDir = await createTempDir();
252
+ try {
253
+ const controller = startWatch({ repoPath: tmpDir.root });
254
+ assert.ok(controller.watcher, 'Should have watcher');
255
+ assert.ok(controller.ready instanceof Promise, 'Should have ready promise');
256
+ assert.equal(typeof controller.close, 'function', 'Should have close method');
257
+ assert.equal(typeof controller.flush, 'function', 'Should have flush method');
258
+ await controller.close();
259
+ }
260
+ finally {
261
+ await tmpDir.cleanup();
262
+ }
263
+ });
264
+ test('startWatch with empty options uses defaults', async () => {
265
+ const controller = startWatch({});
266
+ await controller.ready;
267
+ await controller.close();
268
+ assert.ok(true, 'startWatch with empty options should work');
269
+ });
270
+ test('startWatch passes all options through', async () => {
271
+ const tmpDir = await createTempDir();
272
+ let batchCalled = false;
273
+ try {
274
+ const controller = startWatch({
275
+ repoPath: tmpDir.root,
276
+ provider: 'mock',
277
+ debounceMs: 100,
278
+ encrypt: 'off',
279
+ concurrency: 5,
280
+ onBatch: () => { batchCalled = true; }
281
+ });
282
+ await controller.ready;
283
+ await controller.close();
284
+ assert.ok(true, 'All options should be passed through');
285
+ }
286
+ finally {
287
+ await tmpDir.cleanup();
288
+ }
289
+ });
290
+ // ============================================================================
291
+ // File Event Handling Tests (with real file system)
292
+ // ============================================================================
293
+ test('WatchService detects new file creation', async () => {
294
+ const tmpDir = await createTempDir();
295
+ const changes = [];
296
+ try {
297
+ const service = new WatchService({
298
+ repoPath: tmpDir.root,
299
+ debounceMs: 50,
300
+ onBatch: (event) => { changes.push(event); }
301
+ });
302
+ await service.waitForReady();
303
+ // Create a new TypeScript file
304
+ await writeTestFile(tmpDir.root, 'src/newfile.ts', 'export const x = 1;');
305
+ // Wait for debounce and processing
306
+ await delay(300);
307
+ await service.flush();
308
+ // Note: The file may not be detected if chokidar hasn't settled yet
309
+ // This is a timing-sensitive test
310
+ await service.close();
311
+ }
312
+ finally {
313
+ await tmpDir.cleanup();
314
+ }
315
+ });
316
+ test('WatchService detects file modification', async () => {
317
+ const tmpDir = await createTempDir();
318
+ const changes = [];
319
+ try {
320
+ // Create file before starting watch
321
+ await writeTestFile(tmpDir.root, 'src/existing.ts', 'export const x = 1;');
322
+ const service = new WatchService({
323
+ repoPath: tmpDir.root,
324
+ debounceMs: 50,
325
+ onBatch: (event) => { changes.push(event); }
326
+ });
327
+ await service.waitForReady();
328
+ // Wait for watcher to stabilize
329
+ await delay(100);
330
+ // Modify the file
331
+ await writeTestFile(tmpDir.root, 'src/existing.ts', 'export const x = 2;');
332
+ // Wait for debounce and processing
333
+ await delay(300);
334
+ await service.flush();
335
+ await service.close();
336
+ }
337
+ finally {
338
+ await tmpDir.cleanup();
339
+ }
340
+ });
341
+ test('WatchService detects file deletion', async () => {
342
+ const tmpDir = await createTempDir();
343
+ const changes = [];
344
+ try {
345
+ // Create file before starting watch
346
+ const testFile = path.join(tmpDir.root, 'src/todelete.ts');
347
+ await writeTestFile(tmpDir.root, 'src/todelete.ts', 'export const x = 1;');
348
+ const service = new WatchService({
349
+ repoPath: tmpDir.root,
350
+ debounceMs: 50,
351
+ onBatch: (event) => { changes.push(event); }
352
+ });
353
+ await service.waitForReady();
354
+ // Wait for watcher to stabilize
355
+ await delay(100);
356
+ // Delete the file
357
+ await fs.promises.unlink(testFile);
358
+ // Wait for debounce and processing
359
+ await delay(300);
360
+ await service.flush();
361
+ await service.close();
362
+ }
363
+ finally {
364
+ await tmpDir.cleanup();
365
+ }
366
+ });
367
+ // ============================================================================
368
+ // Extension Filtering Tests
369
+ // ============================================================================
370
+ test('WatchService filters out unsupported extensions', async () => {
371
+ const tmpDir = await createTempDir();
372
+ const changes = [];
373
+ try {
374
+ const service = new WatchService({
375
+ repoPath: tmpDir.root,
376
+ debounceMs: 50,
377
+ onBatch: (event) => { changes.push(event); }
378
+ });
379
+ await service.waitForReady();
380
+ // Wait for watcher to stabilize
381
+ await delay(100);
382
+ // Create a file with unsupported extension
383
+ await writeTestFile(tmpDir.root, 'src/data.xyz', 'some data');
384
+ // Wait for processing
385
+ await delay(200);
386
+ await service.flush();
387
+ // The .xyz file should be filtered out and not trigger a batch
388
+ // (Note: This depends on language extensions configuration)
389
+ await service.close();
390
+ }
391
+ finally {
392
+ await tmpDir.cleanup();
393
+ }
394
+ });
395
+ test('WatchService allows supported TypeScript extension', async () => {
396
+ const tmpDir = await createTempDir();
397
+ const changes = [];
398
+ try {
399
+ const service = new WatchService({
400
+ repoPath: tmpDir.root,
401
+ debounceMs: 50,
402
+ onBatch: (event) => { changes.push(event); }
403
+ });
404
+ await service.waitForReady();
405
+ // Wait for watcher to stabilize
406
+ await delay(100);
407
+ // Create TypeScript file
408
+ await writeTestFile(tmpDir.root, 'src/allowed.ts', 'export const x = 1;');
409
+ // Wait for processing
410
+ await delay(300);
411
+ await service.flush();
412
+ await service.close();
413
+ }
414
+ finally {
415
+ await tmpDir.cleanup();
416
+ }
417
+ });
418
+ // ============================================================================
419
+ // Ignored Directories Tests
420
+ // ============================================================================
421
+ test('WatchService ignores node_modules', async () => {
422
+ const tmpDir = await createTempDir();
423
+ const changes = [];
424
+ try {
425
+ const service = new WatchService({
426
+ repoPath: tmpDir.root,
427
+ debounceMs: 50,
428
+ onBatch: (event) => { changes.push(event); }
429
+ });
430
+ await service.waitForReady();
431
+ await delay(100);
432
+ // Create file in node_modules (should be ignored)
433
+ await fs.promises.mkdir(path.join(tmpDir.root, 'node_modules'), { recursive: true });
434
+ await writeTestFile(tmpDir.root, 'node_modules/package/index.ts', 'export const x = 1;');
435
+ await delay(200);
436
+ await service.flush();
437
+ // Changes from node_modules should be ignored
438
+ const nodeModulesChanges = changes.filter(c => c.changed.some(f => f.includes('node_modules')) ||
439
+ c.deleted.some(f => f.includes('node_modules')));
440
+ assert.equal(nodeModulesChanges.length, 0, 'node_modules changes should be ignored');
441
+ await service.close();
442
+ }
443
+ finally {
444
+ await tmpDir.cleanup();
445
+ }
446
+ });
447
+ test('WatchService ignores .git directory', async () => {
448
+ const tmpDir = await createTempDir();
449
+ const changes = [];
450
+ try {
451
+ const service = new WatchService({
452
+ repoPath: tmpDir.root,
453
+ debounceMs: 50,
454
+ onBatch: (event) => { changes.push(event); }
455
+ });
456
+ await service.waitForReady();
457
+ await delay(100);
458
+ // Create file in .git (should be ignored)
459
+ await fs.promises.mkdir(path.join(tmpDir.root, '.git', 'objects'), { recursive: true });
460
+ await writeTestFile(tmpDir.root, '.git/config', '[core]');
461
+ await delay(200);
462
+ await service.flush();
463
+ // Changes from .git should be ignored
464
+ const gitChanges = changes.filter(c => c.changed.some(f => f.includes('.git')) ||
465
+ c.deleted.some(f => f.includes('.git')));
466
+ assert.equal(gitChanges.length, 0, '.git changes should be ignored');
467
+ await service.close();
468
+ }
469
+ finally {
470
+ await tmpDir.cleanup();
471
+ }
472
+ });
473
+ test('WatchService ignores .codevault directory', async () => {
474
+ const tmpDir = await createTempDir();
475
+ const changes = [];
476
+ try {
477
+ const service = new WatchService({
478
+ repoPath: tmpDir.root,
479
+ debounceMs: 50,
480
+ onBatch: (event) => { changes.push(event); }
481
+ });
482
+ await service.waitForReady();
483
+ await delay(100);
484
+ // Create file in .codevault (should be ignored)
485
+ await fs.promises.mkdir(path.join(tmpDir.root, '.codevault'), { recursive: true });
486
+ await writeTestFile(tmpDir.root, '.codevault/index.db', 'data');
487
+ await delay(200);
488
+ await service.flush();
489
+ // Changes from .codevault should be ignored
490
+ const codevaultChanges = changes.filter(c => c.changed.some(f => f.includes('.codevault')) ||
491
+ c.deleted.some(f => f.includes('.codevault')));
492
+ assert.equal(codevaultChanges.length, 0, '.codevault changes should be ignored');
493
+ await service.close();
494
+ }
495
+ finally {
496
+ await tmpDir.cleanup();
497
+ }
498
+ });
499
+ // ============================================================================
500
+ // Close and Cleanup Tests
501
+ // ============================================================================
502
+ test('WatchService close stops watching', async () => {
503
+ const tmpDir = await createTempDir();
504
+ const changes = [];
505
+ try {
506
+ const service = new WatchService({
507
+ repoPath: tmpDir.root,
508
+ debounceMs: 50,
509
+ onBatch: (event) => { changes.push(event); }
510
+ });
511
+ await service.waitForReady();
512
+ await service.close();
513
+ // Create file after close (should not trigger)
514
+ await writeTestFile(tmpDir.root, 'src/afterclose.ts', 'export const x = 1;');
515
+ await delay(200);
516
+ // No changes should be detected after close
517
+ // (We can't easily assert this, but the test should complete without error)
518
+ assert.ok(true, 'Close should stop watching');
519
+ }
520
+ finally {
521
+ await tmpDir.cleanup();
522
+ }
523
+ });
524
+ test('WatchService close is idempotent', async () => {
525
+ const tmpDir = await createTempDir();
526
+ try {
527
+ const service = new WatchService({ repoPath: tmpDir.root });
528
+ await service.waitForReady();
529
+ // Multiple closes should not throw
530
+ await service.close();
531
+ await service.close();
532
+ await service.close();
533
+ assert.ok(true, 'Multiple closes should be safe');
534
+ }
535
+ finally {
536
+ await tmpDir.cleanup();
537
+ }
538
+ });
539
+ test('WatchService flush after close does not throw', async () => {
540
+ const tmpDir = await createTempDir();
541
+ try {
542
+ const service = new WatchService({ repoPath: tmpDir.root });
543
+ await service.waitForReady();
544
+ await service.close();
545
+ // Flush after close should not throw
546
+ await service.flush();
547
+ assert.ok(true, 'Flush after close should be safe');
548
+ }
549
+ finally {
550
+ await tmpDir.cleanup();
551
+ }
552
+ });
553
+ // ============================================================================
554
+ // Error Handling Tests
555
+ // ============================================================================
556
+ test('WatchService logs errors from watcher', async () => {
557
+ const tmpDir = await createTempDir();
558
+ const logger = createMockLogger();
559
+ try {
560
+ const service = new WatchService({
561
+ repoPath: tmpDir.root,
562
+ logger
563
+ });
564
+ await service.waitForReady();
565
+ await service.close();
566
+ // We can't easily trigger a watcher error, but the error handler exists
567
+ assert.ok(true, 'Error handler should be attached');
568
+ }
569
+ finally {
570
+ await tmpDir.cleanup();
571
+ }
572
+ });
573
+ // ============================================================================
574
+ // Path Normalization Tests
575
+ // ============================================================================
576
+ test('WatchService normalizes paths to POSIX format', async () => {
577
+ const tmpDir = await createTempDir();
578
+ const changes = [];
579
+ try {
580
+ const service = new WatchService({
581
+ repoPath: tmpDir.root,
582
+ debounceMs: 50,
583
+ onBatch: (event) => { changes.push(event); }
584
+ });
585
+ await service.waitForReady();
586
+ await delay(100);
587
+ // Create file with nested path
588
+ await writeTestFile(tmpDir.root, 'src/nested/deep/file.ts', 'export const x = 1;');
589
+ await delay(300);
590
+ await service.flush();
591
+ // Any detected changes should have POSIX-style paths (forward slashes)
592
+ for (const change of changes) {
593
+ for (const filePath of [...change.changed, ...change.deleted]) {
594
+ assert.ok(!filePath.includes('\\'), 'Path should use forward slashes');
595
+ }
596
+ }
597
+ await service.close();
598
+ }
599
+ finally {
600
+ await tmpDir.cleanup();
601
+ }
602
+ });
603
+ // ============================================================================
604
+ // Edge Cases
605
+ // ============================================================================
606
+ test('WatchService handles non-existent repoPath gracefully', async () => {
607
+ const nonExistentPath = path.join(os.tmpdir(), 'nonexistent-' + Date.now());
608
+ try {
609
+ const service = new WatchService({
610
+ repoPath: nonExistentPath
611
+ });
612
+ // Watcher may still start but watch nothing
613
+ await service.waitForReady();
614
+ await service.close();
615
+ assert.ok(true, 'Should handle non-existent path');
616
+ }
617
+ catch (error) {
618
+ // Some systems may throw for non-existent path
619
+ assert.ok(true, 'Error for non-existent path is acceptable');
620
+ }
621
+ });
622
+ test('WatchService handles invalid debounceMs values', async () => {
623
+ const tmpDir = await createTempDir();
624
+ try {
625
+ const service = new WatchService({
626
+ repoPath: tmpDir.root,
627
+ debounceMs: NaN
628
+ });
629
+ await service.waitForReady();
630
+ await service.close();
631
+ assert.ok(true, 'Should handle NaN debounce');
632
+ }
633
+ finally {
634
+ await tmpDir.cleanup();
635
+ }
636
+ });
637
+ test('WatchService handles negative debounceMs', async () => {
638
+ const tmpDir = await createTempDir();
639
+ try {
640
+ const service = new WatchService({
641
+ repoPath: tmpDir.root,
642
+ debounceMs: -100
643
+ });
644
+ await service.waitForReady();
645
+ await service.close();
646
+ assert.ok(true, 'Should handle negative debounce');
647
+ }
648
+ finally {
649
+ await tmpDir.cleanup();
650
+ }
651
+ });
652
+ test('WatchService handles null onBatch callback', async () => {
653
+ const tmpDir = await createTempDir();
654
+ try {
655
+ const service = new WatchService({
656
+ repoPath: tmpDir.root,
657
+ onBatch: null
658
+ });
659
+ await service.waitForReady();
660
+ await service.close();
661
+ assert.ok(true, 'Should handle null callback');
662
+ }
663
+ finally {
664
+ await tmpDir.cleanup();
665
+ }
666
+ });
667
+ //# sourceMappingURL=WatchService.test.js.map