lmgrep 0.1.18 → 0.2.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 (408) hide show
  1. package/README.md +226 -63
  2. package/completions/_lmgrep +49 -40
  3. package/dist/application/Lmgrep.d.ts +107 -0
  4. package/dist/application/Lmgrep.js +99 -0
  5. package/dist/application/Lmgrep.js.map +1 -0
  6. package/dist/application/LmgrepFactory.d.ts +40 -0
  7. package/dist/application/LmgrepFactory.js +155 -0
  8. package/dist/application/LmgrepFactory.js.map +1 -0
  9. package/dist/application/indexing/BranchBootstrapper.d.ts +21 -0
  10. package/dist/application/indexing/BranchBootstrapper.js +52 -0
  11. package/dist/application/indexing/BranchBootstrapper.js.map +1 -0
  12. package/dist/application/indexing/BranchManifestSweeper.d.ts +17 -0
  13. package/dist/application/indexing/BranchManifestSweeper.js +35 -0
  14. package/dist/application/indexing/BranchManifestSweeper.js.map +1 -0
  15. package/dist/application/indexing/Duration.d.ts +9 -0
  16. package/dist/application/indexing/Duration.js +25 -0
  17. package/dist/application/indexing/Duration.js.map +1 -0
  18. package/dist/application/indexing/EmbeddingAbortError.d.ts +11 -0
  19. package/dist/application/indexing/EmbeddingAbortError.js +20 -0
  20. package/dist/application/indexing/EmbeddingAbortError.js.map +1 -0
  21. package/dist/application/indexing/EmbeddingPipeline.d.ts +59 -0
  22. package/dist/application/indexing/EmbeddingPipeline.js +140 -0
  23. package/dist/application/indexing/EmbeddingPipeline.js.map +1 -0
  24. package/dist/application/indexing/IndexBuilder.d.ts +112 -0
  25. package/dist/application/indexing/IndexBuilder.js +370 -0
  26. package/dist/application/indexing/IndexBuilder.js.map +1 -0
  27. package/dist/application/indexing/IndexingProgress.d.ts +34 -0
  28. package/dist/application/indexing/IndexingProgress.js +2 -0
  29. package/dist/application/indexing/IndexingProgress.js.map +1 -0
  30. package/dist/application/operations/Deadline.d.ts +13 -0
  31. package/dist/application/operations/Deadline.js +29 -0
  32. package/dist/application/operations/Deadline.js.map +1 -0
  33. package/dist/application/operations/HealthMonitor.d.ts +58 -0
  34. package/dist/application/operations/HealthMonitor.js +128 -0
  35. package/dist/application/operations/HealthMonitor.js.map +1 -0
  36. package/dist/application/operations/IndexAlternatives.d.ts +35 -0
  37. package/dist/application/operations/IndexAlternatives.js +61 -0
  38. package/dist/application/operations/IndexAlternatives.js.map +1 -0
  39. package/dist/application/operations/IndexInventory.d.ts +69 -0
  40. package/dist/application/operations/IndexInventory.js +99 -0
  41. package/dist/application/operations/IndexInventory.js.map +1 -0
  42. package/dist/application/operations/StatusService.d.ts +90 -0
  43. package/dist/application/operations/StatusService.js +171 -0
  44. package/dist/application/operations/StatusService.js.map +1 -0
  45. package/dist/application/operations/WatchService.d.ts +67 -0
  46. package/dist/application/operations/WatchService.js +145 -0
  47. package/dist/application/operations/WatchService.js.map +1 -0
  48. package/dist/application/operations/WorkingTreeDiff.d.ts +19 -0
  49. package/dist/application/operations/WorkingTreeDiff.js +36 -0
  50. package/dist/application/operations/WorkingTreeDiff.js.map +1 -0
  51. package/dist/application/research/ResearchAgent.d.ts +68 -0
  52. package/dist/application/research/ResearchAgent.js +201 -0
  53. package/dist/application/research/ResearchAgent.js.map +1 -0
  54. package/dist/application/research/ResearchPrompts.d.ts +16 -0
  55. package/dist/application/research/ResearchPrompts.js +34 -0
  56. package/dist/application/research/ResearchPrompts.js.map +1 -0
  57. package/dist/application/search/SearchCriteria.d.ts +37 -0
  58. package/dist/application/search/SearchCriteria.js +48 -0
  59. package/dist/application/search/SearchCriteria.js.map +1 -0
  60. package/dist/application/search/SearchService.d.ts +36 -0
  61. package/dist/application/search/SearchService.js +108 -0
  62. package/dist/application/search/SearchService.js.map +1 -0
  63. package/dist/application/search/SearchTargetResolver.d.ts +56 -0
  64. package/dist/application/search/SearchTargetResolver.js +104 -0
  65. package/dist/application/search/SearchTargetResolver.js.map +1 -0
  66. package/dist/cli.d.ts +1 -1
  67. package/dist/cli.js +4 -953
  68. package/dist/cli.js.map +1 -1
  69. package/dist/domain/config/ConfigSource.d.ts +16 -0
  70. package/dist/domain/config/ConfigSource.js +2 -0
  71. package/dist/domain/config/ConfigSource.js.map +1 -0
  72. package/dist/domain/config/LmgrepConfig.d.ts +53 -0
  73. package/dist/domain/config/LmgrepConfig.js +2 -0
  74. package/dist/domain/config/LmgrepConfig.js.map +1 -0
  75. package/dist/domain/corpus/Chunk.d.ts +49 -0
  76. package/dist/domain/corpus/Chunk.js +60 -0
  77. package/dist/domain/corpus/Chunk.js.map +1 -0
  78. package/dist/domain/corpus/CodeLocation.d.ts +18 -0
  79. package/dist/domain/corpus/CodeLocation.js +34 -0
  80. package/dist/domain/corpus/CodeLocation.js.map +1 -0
  81. package/dist/domain/corpus/ContentHash.d.ts +15 -0
  82. package/dist/domain/corpus/ContentHash.js +30 -0
  83. package/dist/domain/corpus/ContentHash.js.map +1 -0
  84. package/dist/domain/corpus/FileVersion.d.ts +31 -0
  85. package/dist/domain/corpus/FileVersion.js +47 -0
  86. package/dist/domain/corpus/FileVersion.js.map +1 -0
  87. package/dist/domain/corpus/SourceFile.d.ts +26 -0
  88. package/dist/domain/corpus/SourceFile.js +47 -0
  89. package/dist/domain/corpus/SourceFile.js.map +1 -0
  90. package/dist/domain/corpus/Vector.d.ts +37 -0
  91. package/dist/domain/corpus/Vector.js +96 -0
  92. package/dist/domain/corpus/Vector.js.map +1 -0
  93. package/dist/domain/ports/ChatModelPort.d.ts +57 -0
  94. package/dist/domain/ports/ChatModelPort.js +2 -0
  95. package/dist/domain/ports/ChatModelPort.js.map +1 -0
  96. package/dist/domain/ports/ChunkRepositoryPort.d.ts +42 -0
  97. package/dist/domain/ports/ChunkRepositoryPort.js +2 -0
  98. package/dist/domain/ports/ChunkRepositoryPort.js.map +1 -0
  99. package/dist/domain/ports/ChunkerPort.d.ts +5 -0
  100. package/dist/domain/ports/ChunkerPort.js +2 -0
  101. package/dist/domain/ports/ChunkerPort.js.map +1 -0
  102. package/dist/domain/ports/DatabaseSessionPort.d.ts +10 -0
  103. package/dist/domain/ports/DatabaseSessionPort.js +2 -0
  104. package/dist/domain/ports/DatabaseSessionPort.js.map +1 -0
  105. package/dist/domain/ports/EmbedderPort.d.ts +14 -0
  106. package/dist/domain/ports/EmbedderPort.js +2 -0
  107. package/dist/domain/ports/EmbedderPort.js.map +1 -0
  108. package/dist/domain/ports/FileManifestRepositoryPort.d.ts +32 -0
  109. package/dist/domain/ports/FileManifestRepositoryPort.js +2 -0
  110. package/dist/domain/ports/FileManifestRepositoryPort.js.map +1 -0
  111. package/dist/domain/ports/GitPort.d.ts +24 -0
  112. package/dist/domain/ports/GitPort.js +2 -0
  113. package/dist/domain/ports/GitPort.js.map +1 -0
  114. package/dist/domain/ports/IndexMaintenancePort.d.ts +58 -0
  115. package/dist/domain/ports/IndexMaintenancePort.js +2 -0
  116. package/dist/domain/ports/IndexMaintenancePort.js.map +1 -0
  117. package/dist/domain/ports/IndexMetadataPort.d.ts +23 -0
  118. package/dist/domain/ports/IndexMetadataPort.js +2 -0
  119. package/dist/domain/ports/IndexMetadataPort.js.map +1 -0
  120. package/dist/domain/ports/LockPort.d.ts +17 -0
  121. package/dist/domain/ports/LockPort.js +2 -0
  122. package/dist/domain/ports/LockPort.js.map +1 -0
  123. package/dist/domain/ports/LoggerPort.d.ts +5 -0
  124. package/dist/domain/ports/LoggerPort.js +2 -0
  125. package/dist/domain/ports/LoggerPort.js.map +1 -0
  126. package/dist/domain/ports/ProjectIndexesPort.d.ts +20 -0
  127. package/dist/domain/ports/ProjectIndexesPort.js +2 -0
  128. package/dist/domain/ports/ProjectIndexesPort.js.map +1 -0
  129. package/dist/domain/ports/ProjectRegistryPort.d.ts +42 -0
  130. package/dist/domain/ports/ProjectRegistryPort.js +2 -0
  131. package/dist/domain/ports/ProjectRegistryPort.js.map +1 -0
  132. package/dist/domain/ports/StateDirectoryPort.d.ts +29 -0
  133. package/dist/domain/ports/StateDirectoryPort.js +2 -0
  134. package/dist/domain/ports/StateDirectoryPort.js.map +1 -0
  135. package/dist/domain/ports/WorkspacePort.d.ts +38 -0
  136. package/dist/domain/ports/WorkspacePort.js +2 -0
  137. package/dist/domain/ports/WorkspacePort.js.map +1 -0
  138. package/dist/domain/project/Branch.d.ts +20 -0
  139. package/dist/domain/project/Branch.js +33 -0
  140. package/dist/domain/project/Branch.js.map +1 -0
  141. package/dist/domain/project/DatabaseLocation.d.ts +32 -0
  142. package/dist/domain/project/DatabaseLocation.js +35 -0
  143. package/dist/domain/project/DatabaseLocation.js.map +1 -0
  144. package/dist/domain/project/IndexMetadata.d.ts +17 -0
  145. package/dist/domain/project/IndexMetadata.js +2 -0
  146. package/dist/domain/project/IndexMetadata.js.map +1 -0
  147. package/dist/domain/project/ModelIdentity.d.ts +58 -0
  148. package/dist/domain/project/ModelIdentity.js +97 -0
  149. package/dist/domain/project/ModelIdentity.js.map +1 -0
  150. package/dist/domain/project/Project.d.ts +17 -0
  151. package/dist/domain/project/Project.js +21 -0
  152. package/dist/domain/project/Project.js.map +1 -0
  153. package/dist/domain/project/ProjectId.d.ts +28 -0
  154. package/dist/domain/project/ProjectId.js +58 -0
  155. package/dist/domain/project/ProjectId.js.map +1 -0
  156. package/dist/domain/project/ProjectLocator.d.ts +112 -0
  157. package/dist/domain/project/ProjectLocator.js +178 -0
  158. package/dist/domain/project/ProjectLocator.js.map +1 -0
  159. package/dist/domain/research/Citation.d.ts +27 -0
  160. package/dist/domain/research/Citation.js +43 -0
  161. package/dist/domain/research/Citation.js.map +1 -0
  162. package/dist/domain/research/EvidenceLedger.d.ts +47 -0
  163. package/dist/domain/research/EvidenceLedger.js +111 -0
  164. package/dist/domain/research/EvidenceLedger.js.map +1 -0
  165. package/dist/domain/research/ResearchTrace.d.ts +19 -0
  166. package/dist/domain/research/ResearchTrace.js +22 -0
  167. package/dist/domain/research/ResearchTrace.js.map +1 -0
  168. package/dist/domain/retrieval/Hit.d.ts +19 -0
  169. package/dist/domain/retrieval/Hit.js +28 -0
  170. package/dist/domain/retrieval/Hit.js.map +1 -0
  171. package/dist/domain/retrieval/HitList.d.ts +35 -0
  172. package/dist/domain/retrieval/HitList.js +81 -0
  173. package/dist/domain/retrieval/HitList.js.map +1 -0
  174. package/dist/domain/retrieval/MissingIndexError.d.ts +11 -0
  175. package/dist/domain/retrieval/MissingIndexError.js +15 -0
  176. package/dist/domain/retrieval/MissingIndexError.js.map +1 -0
  177. package/dist/index.d.ts +43 -45
  178. package/dist/index.js +30 -567
  179. package/dist/index.js.map +1 -1
  180. package/dist/infrastructure/ai/AiSdkChatModel.d.ts +31 -0
  181. package/dist/infrastructure/ai/AiSdkChatModel.js +137 -0
  182. package/dist/infrastructure/ai/AiSdkChatModel.js.map +1 -0
  183. package/dist/infrastructure/ai/AiSdkEmbedder.d.ts +28 -0
  184. package/dist/infrastructure/ai/AiSdkEmbedder.js +79 -0
  185. package/dist/infrastructure/ai/AiSdkEmbedder.js.map +1 -0
  186. package/dist/infrastructure/ai/EmbeddingPrefixes.d.ts +21 -0
  187. package/dist/infrastructure/ai/EmbeddingPrefixes.js +40 -0
  188. package/dist/infrastructure/ai/EmbeddingPrefixes.js.map +1 -0
  189. package/dist/infrastructure/ai/LmStudioProbe.d.ts +18 -0
  190. package/dist/infrastructure/ai/LmStudioProbe.js +49 -0
  191. package/dist/infrastructure/ai/LmStudioProbe.js.map +1 -0
  192. package/dist/infrastructure/ai/LocalModelReloader.d.ts +21 -0
  193. package/dist/infrastructure/ai/LocalModelReloader.js +61 -0
  194. package/dist/infrastructure/ai/LocalModelReloader.js.map +1 -0
  195. package/dist/infrastructure/ai/LocalRuntimeDetector.d.ts +36 -0
  196. package/dist/infrastructure/ai/LocalRuntimeDetector.js +61 -0
  197. package/dist/infrastructure/ai/LocalRuntimeDetector.js.map +1 -0
  198. package/dist/infrastructure/ai/ModelRuntime.d.ts +32 -0
  199. package/dist/infrastructure/ai/ModelRuntime.js +2 -0
  200. package/dist/infrastructure/ai/ModelRuntime.js.map +1 -0
  201. package/dist/infrastructure/ai/OllamaProbe.d.ts +21 -0
  202. package/dist/infrastructure/ai/OllamaProbe.js +69 -0
  203. package/dist/infrastructure/ai/OllamaProbe.js.map +1 -0
  204. package/dist/infrastructure/ai/ProviderFailure.d.ts +16 -0
  205. package/dist/infrastructure/ai/ProviderFailure.js +35 -0
  206. package/dist/infrastructure/ai/ProviderFailure.js.map +1 -0
  207. package/dist/infrastructure/ai/ProviderModuleLoader.d.ts +13 -0
  208. package/dist/infrastructure/ai/ProviderModuleLoader.js +49 -0
  209. package/dist/infrastructure/ai/ProviderModuleLoader.js.map +1 -0
  210. package/dist/infrastructure/ai/ProviderRegistry.d.ts +37 -0
  211. package/dist/infrastructure/ai/ProviderRegistry.js +55 -0
  212. package/dist/infrastructure/ai/ProviderRegistry.js.map +1 -0
  213. package/dist/infrastructure/fs/ConfigLoader.d.ts +59 -0
  214. package/dist/infrastructure/fs/ConfigLoader.js +194 -0
  215. package/dist/infrastructure/fs/ConfigLoader.js.map +1 -0
  216. package/dist/infrastructure/fs/DatabaseLocks.d.ts +52 -0
  217. package/dist/infrastructure/fs/DatabaseLocks.js +92 -0
  218. package/dist/infrastructure/fs/DatabaseLocks.js.map +1 -0
  219. package/dist/infrastructure/fs/DiskUsage.d.ts +6 -0
  220. package/dist/infrastructure/fs/DiskUsage.js +41 -0
  221. package/dist/infrastructure/fs/DiskUsage.js.map +1 -0
  222. package/dist/infrastructure/fs/IndexableFileRules.d.ts +33 -0
  223. package/dist/infrastructure/fs/IndexableFileRules.js +177 -0
  224. package/dist/infrastructure/fs/IndexableFileRules.js.map +1 -0
  225. package/dist/infrastructure/fs/Loggers.d.ts +14 -0
  226. package/dist/infrastructure/fs/Loggers.js +18 -0
  227. package/dist/infrastructure/fs/Loggers.js.map +1 -0
  228. package/dist/infrastructure/fs/PidFileLock.d.ts +40 -0
  229. package/dist/infrastructure/fs/PidFileLock.js +97 -0
  230. package/dist/infrastructure/fs/PidFileLock.js.map +1 -0
  231. package/dist/infrastructure/fs/ProjectIndexes.d.ts +8 -0
  232. package/dist/infrastructure/fs/ProjectIndexes.js +35 -0
  233. package/dist/infrastructure/fs/ProjectIndexes.js.map +1 -0
  234. package/dist/infrastructure/fs/ProjectMetadataStore.d.ts +42 -0
  235. package/dist/infrastructure/fs/ProjectMetadataStore.js +86 -0
  236. package/dist/infrastructure/fs/ProjectMetadataStore.js.map +1 -0
  237. package/dist/infrastructure/fs/ProjectRegistry.d.ts +25 -0
  238. package/dist/infrastructure/fs/ProjectRegistry.js +83 -0
  239. package/dist/infrastructure/fs/ProjectRegistry.js.map +1 -0
  240. package/dist/infrastructure/fs/StateDirectory.d.ts +28 -0
  241. package/dist/infrastructure/fs/StateDirectory.js +71 -0
  242. package/dist/infrastructure/fs/StateDirectory.js.map +1 -0
  243. package/dist/infrastructure/fs/Workspace.d.ts +25 -0
  244. package/dist/infrastructure/fs/Workspace.js +90 -0
  245. package/dist/infrastructure/fs/Workspace.js.map +1 -0
  246. package/dist/infrastructure/git/GitClient.d.ts +34 -0
  247. package/dist/infrastructure/git/GitClient.js +74 -0
  248. package/dist/infrastructure/git/GitClient.js.map +1 -0
  249. package/dist/infrastructure/lancedb/ChunkRepository.d.ts +38 -0
  250. package/dist/infrastructure/lancedb/ChunkRepository.js +166 -0
  251. package/dist/infrastructure/lancedb/ChunkRepository.js.map +1 -0
  252. package/dist/infrastructure/lancedb/DatabaseImporter.d.ts +22 -0
  253. package/dist/infrastructure/lancedb/DatabaseImporter.js +74 -0
  254. package/dist/infrastructure/lancedb/DatabaseImporter.js.map +1 -0
  255. package/dist/infrastructure/lancedb/FileManifestRepository.d.ts +34 -0
  256. package/dist/infrastructure/lancedb/FileManifestRepository.js +137 -0
  257. package/dist/infrastructure/lancedb/FileManifestRepository.js.map +1 -0
  258. package/dist/infrastructure/lancedb/IndexMaintenance.d.ts +53 -0
  259. package/dist/infrastructure/lancedb/IndexMaintenance.js +227 -0
  260. package/dist/infrastructure/lancedb/IndexMaintenance.js.map +1 -0
  261. package/dist/infrastructure/lancedb/LanceTables.d.ts +67 -0
  262. package/dist/infrastructure/lancedb/LanceTables.js +159 -0
  263. package/dist/infrastructure/lancedb/LanceTables.js.map +1 -0
  264. package/dist/{lib/native-tuning.js → infrastructure/lancedb/NativeTuning.js} +1 -1
  265. package/dist/infrastructure/lancedb/NativeTuning.js.map +1 -0
  266. package/dist/infrastructure/lancedb/RowReplication.d.ts +27 -0
  267. package/dist/infrastructure/lancedb/RowReplication.js +82 -0
  268. package/dist/infrastructure/lancedb/RowReplication.js.map +1 -0
  269. package/dist/infrastructure/lancedb/VectorIndexPolicy.d.ts +60 -0
  270. package/dist/infrastructure/lancedb/VectorIndexPolicy.js +72 -0
  271. package/dist/infrastructure/lancedb/VectorIndexPolicy.js.map +1 -0
  272. package/dist/infrastructure/p2p/IndexShare.d.ts +45 -0
  273. package/dist/infrastructure/p2p/IndexShare.js +160 -0
  274. package/dist/infrastructure/p2p/IndexShare.js.map +1 -0
  275. package/dist/infrastructure/p2p/PeerSwarm.d.ts +16 -0
  276. package/dist/infrastructure/p2p/PeerSwarm.js +41 -0
  277. package/dist/infrastructure/p2p/PeerSwarm.js.map +1 -0
  278. package/dist/infrastructure/p2p/SecureChannel.d.ts +60 -0
  279. package/dist/infrastructure/p2p/SecureChannel.js +71 -0
  280. package/dist/infrastructure/p2p/SecureChannel.js.map +1 -0
  281. package/dist/infrastructure/p2p/ShareCode.d.ts +25 -0
  282. package/dist/infrastructure/p2p/ShareCode.js +304 -0
  283. package/dist/infrastructure/p2p/ShareCode.js.map +1 -0
  284. package/dist/infrastructure/process/ProcessRegistry.d.ts +50 -0
  285. package/dist/infrastructure/process/ProcessRegistry.js +109 -0
  286. package/dist/infrastructure/process/ProcessRegistry.js.map +1 -0
  287. package/dist/infrastructure/treesitter/ChunkContextBuilder.d.ts +45 -0
  288. package/dist/infrastructure/treesitter/ChunkContextBuilder.js +159 -0
  289. package/dist/infrastructure/treesitter/ChunkContextBuilder.js.map +1 -0
  290. package/dist/infrastructure/treesitter/LanguageCatalog.d.ts +30 -0
  291. package/dist/{lib/chunker/languages.js → infrastructure/treesitter/LanguageCatalog.js} +34 -29
  292. package/dist/infrastructure/treesitter/LanguageCatalog.js.map +1 -0
  293. package/dist/infrastructure/treesitter/SlidingWindowChunker.d.ts +15 -0
  294. package/dist/infrastructure/treesitter/SlidingWindowChunker.js +42 -0
  295. package/dist/infrastructure/treesitter/SlidingWindowChunker.js.map +1 -0
  296. package/dist/infrastructure/treesitter/TreeSitterChunker.d.ts +42 -0
  297. package/dist/infrastructure/treesitter/TreeSitterChunker.js +163 -0
  298. package/dist/infrastructure/treesitter/TreeSitterChunker.js.map +1 -0
  299. package/dist/mcp.d.ts +1 -1
  300. package/dist/mcp.js +14 -72
  301. package/dist/mcp.js.map +1 -1
  302. package/dist/presentation/cli/Cli.d.ts +31 -0
  303. package/dist/presentation/cli/Cli.js +120 -0
  304. package/dist/presentation/cli/Cli.js.map +1 -0
  305. package/dist/presentation/cli/CliOptions.d.ts +18 -0
  306. package/dist/presentation/cli/CliOptions.js +25 -0
  307. package/dist/presentation/cli/CliOptions.js.map +1 -0
  308. package/dist/presentation/cli/CommandContext.d.ts +50 -0
  309. package/dist/presentation/cli/CommandContext.js +88 -0
  310. package/dist/presentation/cli/CommandContext.js.map +1 -0
  311. package/dist/presentation/cli/ConfigTemplate.d.ts +31 -0
  312. package/dist/presentation/cli/ConfigTemplate.js +83 -0
  313. package/dist/presentation/cli/ConfigTemplate.js.map +1 -0
  314. package/dist/presentation/cli/Renderer.d.ts +90 -0
  315. package/dist/presentation/cli/Renderer.js +290 -0
  316. package/dist/presentation/cli/Renderer.js.map +1 -0
  317. package/dist/presentation/cli/commands/AskCommand.d.ts +14 -0
  318. package/dist/presentation/cli/commands/AskCommand.js +48 -0
  319. package/dist/presentation/cli/commands/AskCommand.js.map +1 -0
  320. package/dist/presentation/cli/commands/CompletionsCommand.d.ts +18 -0
  321. package/dist/presentation/cli/commands/CompletionsCommand.js +96 -0
  322. package/dist/presentation/cli/commands/CompletionsCommand.js.map +1 -0
  323. package/dist/presentation/cli/commands/ConfigCommands.d.ts +55 -0
  324. package/dist/presentation/cli/commands/ConfigCommands.js +204 -0
  325. package/dist/presentation/cli/commands/ConfigCommands.js.map +1 -0
  326. package/dist/presentation/cli/commands/IndexCommand.d.ts +18 -0
  327. package/dist/presentation/cli/commands/IndexCommand.js +54 -0
  328. package/dist/presentation/cli/commands/IndexCommand.js.map +1 -0
  329. package/dist/presentation/cli/commands/ProjectsCommand.d.ts +48 -0
  330. package/dist/presentation/cli/commands/ProjectsCommand.js +240 -0
  331. package/dist/presentation/cli/commands/ProjectsCommand.js.map +1 -0
  332. package/dist/presentation/cli/commands/SearchCommand.d.ts +19 -0
  333. package/dist/presentation/cli/commands/SearchCommand.js +55 -0
  334. package/dist/presentation/cli/commands/SearchCommand.js.map +1 -0
  335. package/dist/presentation/cli/commands/ServerCommands.d.ts +13 -0
  336. package/dist/presentation/cli/commands/ServerCommands.js +40 -0
  337. package/dist/presentation/cli/commands/ServerCommands.js.map +1 -0
  338. package/dist/presentation/cli/commands/ShareCommands.d.ts +22 -0
  339. package/dist/presentation/cli/commands/ShareCommands.js +134 -0
  340. package/dist/presentation/cli/commands/ShareCommands.js.map +1 -0
  341. package/dist/presentation/cli/commands/StatusCommand.d.ts +15 -0
  342. package/dist/presentation/cli/commands/StatusCommand.js +53 -0
  343. package/dist/presentation/cli/commands/StatusCommand.js.map +1 -0
  344. package/dist/presentation/mcp/HitFormatter.d.ts +17 -0
  345. package/dist/presentation/mcp/HitFormatter.js +42 -0
  346. package/dist/presentation/mcp/HitFormatter.js.map +1 -0
  347. package/dist/presentation/mcp/IndexWatchController.d.ts +17 -0
  348. package/dist/presentation/mcp/IndexWatchController.js +31 -0
  349. package/dist/presentation/mcp/IndexWatchController.js.map +1 -0
  350. package/dist/presentation/mcp/LmgrepCore.d.ts +66 -0
  351. package/dist/presentation/mcp/LmgrepCore.js +178 -0
  352. package/dist/presentation/mcp/LmgrepCore.js.map +1 -0
  353. package/dist/presentation/mcp/McpServer.d.ts +18 -0
  354. package/dist/presentation/mcp/McpServer.js +63 -0
  355. package/dist/presentation/mcp/McpServer.js.map +1 -0
  356. package/dist/presentation/mcp/ToolDescriptions.d.ts +40 -0
  357. package/dist/presentation/mcp/ToolDescriptions.js +85 -0
  358. package/dist/presentation/mcp/ToolDescriptions.js.map +1 -0
  359. package/package.json +84 -89
  360. package/dist/lib/build.d.ts +0 -21
  361. package/dist/lib/build.js +0 -374
  362. package/dist/lib/build.js.map +0 -1
  363. package/dist/lib/chunker/context.d.ts +0 -21
  364. package/dist/lib/chunker/context.js +0 -131
  365. package/dist/lib/chunker/context.js.map +0 -1
  366. package/dist/lib/chunker/index.d.ts +0 -7
  367. package/dist/lib/chunker/index.js +0 -209
  368. package/dist/lib/chunker/index.js.map +0 -1
  369. package/dist/lib/chunker/languages.d.ts +0 -15
  370. package/dist/lib/chunker/languages.js.map +0 -1
  371. package/dist/lib/config.d.ts +0 -12
  372. package/dist/lib/config.js +0 -83
  373. package/dist/lib/config.js.map +0 -1
  374. package/dist/lib/embedder.d.ts +0 -65
  375. package/dist/lib/embedder.js +0 -236
  376. package/dist/lib/embedder.js.map +0 -1
  377. package/dist/lib/facet-session.d.ts +0 -44
  378. package/dist/lib/facet-session.js +0 -125
  379. package/dist/lib/facet-session.js.map +0 -1
  380. package/dist/lib/native-tuning.js.map +0 -1
  381. package/dist/lib/p2p.d.ts +0 -32
  382. package/dist/lib/p2p.js +0 -281
  383. package/dist/lib/p2p.js.map +0 -1
  384. package/dist/lib/providers.d.ts +0 -1
  385. package/dist/lib/providers.js +0 -41
  386. package/dist/lib/providers.js.map +0 -1
  387. package/dist/lib/repair.d.ts +0 -10
  388. package/dist/lib/repair.js +0 -57
  389. package/dist/lib/repair.js.map +0 -1
  390. package/dist/lib/scanner.d.ts +0 -34
  391. package/dist/lib/scanner.js +0 -242
  392. package/dist/lib/scanner.js.map +0 -1
  393. package/dist/lib/search-tool.d.ts +0 -55
  394. package/dist/lib/search-tool.js +0 -319
  395. package/dist/lib/search-tool.js.map +0 -1
  396. package/dist/lib/serve.d.ts +0 -11
  397. package/dist/lib/serve.js +0 -144
  398. package/dist/lib/serve.js.map +0 -1
  399. package/dist/lib/store.d.ts +0 -252
  400. package/dist/lib/store.js +0 -1216
  401. package/dist/lib/store.js.map +0 -1
  402. package/dist/lib/types.d.ts +0 -194
  403. package/dist/lib/types.js +0 -13
  404. package/dist/lib/types.js.map +0 -1
  405. package/dist/lib/vocab.d.ts +0 -20
  406. package/dist/lib/vocab.js +0 -275
  407. package/dist/lib/vocab.js.map +0 -1
  408. /package/dist/{lib/native-tuning.d.ts → infrastructure/lancedb/NativeTuning.d.ts} +0 -0
package/dist/cli.js CHANGED
@@ -1,957 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  process.title = "lmgrep";
3
- // Must come first — sets TOKIO/RAYON/UV thread caps before LanceDB native
3
+ // Must come first — sets TOKIO/RAYON/UV thread caps before the LanceDB native
4
4
  // binding initializes its runtime.
5
- import "./lib/native-tuning.js";
6
- import { Command } from "commander";
7
- import { createHash } from "node:crypto";
8
- import { readFileSync, writeFileSync, existsSync, rmSync, mkdirSync, } from "node:fs";
9
- import { homedir } from "node:os";
10
- import { join, resolve } from "node:path";
11
- import { execSync, spawnSync } from "node:child_process";
12
- import { createIndex } from "./index.js";
13
- import { getGlobalConfigPath } from "./lib/config.js";
14
- import { walkFiles } from "./lib/scanner.js";
15
- import { renameSync } from "node:fs";
16
- import { Store, buildSlug, getDbPath, getLegacyDbPath, readProjectMetadata, extractModelFamily, discoverIndexedProjects, discoverRunningProcesses, withWriteLock, } from "./lib/store.js";
17
- const program = new Command();
18
- program
19
- .name("lmgrep")
20
- .description("Semantic code search with any AI embedding provider")
21
- .version("0.1.0");
22
- program
23
- .command("index")
24
- .description("Index the current directory for semantic search")
25
- .option("-r, --reset", "Reset and rebuild the entire index")
26
- .option("-v, --verbose", "Show file-by-file progress")
27
- .option("-s, --since <duration>", "Only consider files modified within duration (e.g. 10m, 2h, 1d)")
28
- .option("-f, --force", "Force re-embed even if file hash unchanged (use with --since)")
29
- .option("-d, --dry", "Show what would be indexed without actually doing it")
30
- .action(async (opts) => {
31
- const cwd = process.cwd();
32
- const index = await createIndex({ cwd });
33
- await index.build({
34
- reset: opts.reset,
35
- verbose: opts.verbose,
36
- since: opts.since,
37
- force: opts.force,
38
- dry: opts.dry,
39
- });
40
- await index.close();
41
- });
42
- program
43
- .command("search <query>")
44
- .description("Search the codebase using natural language")
45
- .option("-m, --limit <n>", "Max results", "25")
46
- .option("--scores", "Show relevance scores")
47
- .option("--compact", "Show file paths only")
48
- .option("--json", "Output results as JSON")
49
- .option("--min-score <n>", "Minimum score threshold")
50
- .option("--file-prefix <prefix>", "Only search files matching this path prefix")
51
- .option("--not <query>", "Exclude results similar to this query")
52
- .option("--type <types>", "Only return chunks of these AST types (comma-separated)")
53
- .option("--language <langs>", "Only return chunks from files with these extensions (comma-separated, e.g. .ts,.py)")
54
- .option("--project <path>", "Search a different project's index")
55
- .option("--across <paths>", "Search multiple project indexes (comma-separated paths)")
56
- .action(async (query, opts) => {
57
- const cwd = process.cwd();
58
- const index = await createIndex({ cwd });
59
- const results = await index.search(query, {
60
- limit: Number.parseInt(opts.limit, 10),
61
- filePrefix: opts.filePrefix,
62
- not: opts.not,
63
- minScore: opts.minScore
64
- ? Number.parseFloat(opts.minScore)
65
- : undefined,
66
- type: opts.type
67
- ? opts.type.split(",").map((s) => s.trim())
68
- : undefined,
69
- language: opts.language
70
- ? opts.language.split(",").map((s) => s.trim())
71
- : undefined,
72
- project: opts.project,
73
- across: opts.across
74
- ? opts.across.split(",").map((s) => s.trim())
75
- : undefined,
76
- });
77
- if (opts.json) {
78
- console.log(JSON.stringify(results, null, 2));
79
- await index.close();
80
- return;
81
- }
82
- if (results.length === 0) {
83
- console.log("No results found.");
84
- }
85
- else if (opts.compact) {
86
- const seen = new Set();
87
- for (const r of results) {
88
- if (!seen.has(r.filePath)) {
89
- seen.add(r.filePath);
90
- console.log(r.filePath);
91
- }
92
- }
93
- }
94
- else {
95
- for (const r of results) {
96
- const header = `${r.filePath}:${r.startLine}-${r.endLine} [${r.type}] ${r.name}`;
97
- const score = opts.scores
98
- ? ` (score: ${r.score.toFixed(3)})`
99
- : "";
100
- console.log(`\n${"─".repeat(60)}`);
101
- console.log(`${header}${score}`);
102
- console.log(`${"─".repeat(60)}`);
103
- console.log(r.context);
104
- console.log();
105
- console.log(r.content);
106
- }
107
- }
108
- await index.close();
109
- });
110
- {
111
- const facet = program
112
- .command("facet")
113
- .description("Cluster search results into semantic facets");
114
- facet
115
- .command("index")
116
- .description("Build the vocab table used for cluster labeling")
117
- .option("--reset", "Drop and rebuild the vocab table")
118
- .option("--min-df <n>", "Min document frequency for a term to be embedded", "10")
119
- .action(async (opts) => {
120
- const cwd = process.cwd();
121
- const index = await createIndex({ cwd });
122
- try {
123
- const result = await index.facetIndex({
124
- reset: opts.reset,
125
- minDf: Number.parseInt(opts.minDf, 10),
126
- });
127
- console.log(`Vocab: +${result.added} new terms (${result.total} total).`);
128
- }
129
- finally {
130
- await index.close();
131
- }
132
- });
133
- facet
134
- .command("search <query>")
135
- .description("Run semantic search and print root facets + session id")
136
- .option("-m, --limit <n>", "Max results to cluster", "25")
137
- .option("-k, --k <n>", "Number of facets", "5")
138
- .option("--file-prefix <prefix>", "Only search files matching this path prefix")
139
- .option("--json", "Output as JSON")
140
- .option("-v, --verbose", "Show top vocab candidates per cluster")
141
- .action(async (query, opts) => {
142
- const cwd = process.cwd();
143
- const index = await createIndex({ cwd });
144
- const result = await index.facetSearch(query, {
145
- limit: Number.parseInt(opts.limit, 10),
146
- k: Number.parseInt(opts.k, 10),
147
- filePrefix: opts.filePrefix,
148
- });
149
- if (opts.json) {
150
- console.log(JSON.stringify(result, null, 2));
151
- }
152
- else if (result.labels.length === 0) {
153
- console.log("No results found.");
154
- }
155
- else if (opts.verbose) {
156
- console.log(result.sessionId);
157
- printCandidates(result.labels, result.candidates, result.disambiguators);
158
- }
159
- else {
160
- console.log(result.sessionId);
161
- printQualified(result.labels, result.qualifiers);
162
- }
163
- await index.close();
164
- });
165
- facet
166
- .command("list <path>")
167
- .description("Print the facet list at a node (e.g. kx3 or kx3/token)")
168
- .option("--json", "Output as JSON")
169
- .option("-v, --verbose", "Show top vocab candidates per cluster")
170
- .action(async (path, opts) => {
171
- const cwd = process.cwd();
172
- const index = await createIndex({ cwd });
173
- try {
174
- const result = await index.facetList(path);
175
- if (opts.json) {
176
- console.log(JSON.stringify(result, null, 2));
177
- }
178
- else if (opts.verbose) {
179
- printCandidates(result.labels, result.candidates, result.disambiguators);
180
- }
181
- else {
182
- printQualified(result.labels, result.qualifiers);
183
- }
184
- }
185
- catch (err) {
186
- console.error(err.message);
187
- process.exitCode = 1;
188
- }
189
- finally {
190
- await index.close();
191
- }
192
- });
193
- facet
194
- .command("show <path>")
195
- .description("Print the result chunks at a node")
196
- .option("--json", "Output as JSON")
197
- .option("--compact", "Show file paths only")
198
- .action(async (path, opts) => {
199
- const cwd = process.cwd();
200
- const index = await createIndex({ cwd });
201
- try {
202
- const result = await index.facetShow(path);
203
- if (opts.json) {
204
- console.log(JSON.stringify(result, null, 2));
205
- }
206
- else if (result.results.length === 0) {
207
- console.log("(empty)");
208
- }
209
- else if (opts.compact) {
210
- const seen = new Set();
211
- for (const r of result.results) {
212
- if (!seen.has(r.filePath)) {
213
- seen.add(r.filePath);
214
- console.log(r.filePath);
215
- }
216
- }
217
- }
218
- else {
219
- for (const r of result.results) {
220
- console.log(`\n${"─".repeat(60)}`);
221
- console.log(`${r.filePath}:${r.startLine}-${r.endLine} [${r.type}] ${r.name}`);
222
- console.log(`${"─".repeat(60)}`);
223
- console.log(r.context);
224
- console.log();
225
- console.log(r.content);
226
- }
227
- }
228
- }
229
- catch (err) {
230
- console.error(err.message);
231
- process.exitCode = 1;
232
- }
233
- finally {
234
- await index.close();
235
- }
236
- });
237
- facet
238
- .command("refine <path>")
239
- .description("Compute child facets for the pool at a node")
240
- .option("-k, --k <n>", "Number of facets", "5")
241
- .option("--json", "Output as JSON")
242
- .option("-v, --verbose", "Show top vocab candidates per cluster")
243
- .action(async (path, opts) => {
244
- const cwd = process.cwd();
245
- const index = await createIndex({ cwd });
246
- try {
247
- const result = await index.facetRefine(path, {
248
- k: Number.parseInt(opts.k, 10),
249
- });
250
- if (opts.json) {
251
- console.log(JSON.stringify(result, null, 2));
252
- }
253
- else if (result.labels.length === 0) {
254
- console.log("(nothing to refine)");
255
- }
256
- else if (opts.verbose) {
257
- printCandidates(result.labels, result.candidates, result.disambiguators);
258
- }
259
- else {
260
- printQualified(result.labels, result.qualifiers);
261
- }
262
- }
263
- catch (err) {
264
- console.error(err.message);
265
- process.exitCode = 1;
266
- }
267
- finally {
268
- await index.close();
269
- }
270
- });
271
- }
272
- function printQualified(labels, qualifiers) {
273
- for (let i = 0; i < labels.length; i++) {
274
- const q = qualifiers?.[i] ?? [];
275
- if (q.length === 0) {
276
- console.log(` ${labels[i]}`);
277
- }
278
- else {
279
- console.log(` ${labels[i]}: ${q.join(", ")}`);
280
- }
281
- }
282
- }
283
- function printCandidates(labels, candidates, disambiguators) {
284
- for (let i = 0; i < labels.length; i++) {
285
- const cands = candidates?.[i] ?? [labels[i]];
286
- const [head, ...rest] = cands;
287
- const alts = rest.length > 0 ? ` (${rest.join(", ")})` : "";
288
- console.log(` ${head}${alts}`);
289
- const rows = disambiguators?.[i] ?? [];
290
- for (const row of rows) {
291
- const terms = row.terms.join(", ");
292
- console.log(` vs ${row.vs}: ${terms}`);
293
- }
294
- }
295
- }
296
- program
297
- .command("status")
298
- .description("Show index stats and check embedding connectivity")
299
- .option("-c, --changes", "Scan for changed files since last index")
300
- .option("--json", "Output status as JSON")
301
- .action(async (opts) => {
302
- const cwd = process.cwd();
303
- const index = await createIndex({ cwd });
304
- const info = await index.status();
305
- const processes = discoverRunningProcesses();
306
- if (opts.json) {
307
- const output = { ...info, processes };
308
- if (opts.changes) {
309
- const projectRoot = info.projectRoot;
310
- const projectStore = Store.forProject(projectRoot);
311
- const storedFileHashes = await projectStore.getFileHashes();
312
- const currentFiles = walkFiles(projectRoot);
313
- const changes = computeChanges(projectRoot, currentFiles, storedFileHashes);
314
- output.changes = changes;
315
- await projectStore.close();
316
- }
317
- console.log(JSON.stringify(output, null, 2));
318
- await index.close();
319
- return;
320
- }
321
- console.log(`Project root: ${info.projectRoot}`);
322
- if (info.prefix)
323
- console.log(`Subdirectory: ${info.prefix}`);
324
- console.log(`Model: ${info.config.model}`);
325
- if (info.config.provider)
326
- console.log(`Provider: ${info.config.provider}`);
327
- if (info.config.baseURL)
328
- console.log(`Base URL: ${info.config.baseURL}`);
329
- console.log(`Batch size: ${info.config.batchSize}`);
330
- if (info.config.maxTokens)
331
- console.log(`Max tokens: ${info.config.maxTokens}`);
332
- if (info.fileCount === 0) {
333
- console.log("\nNo index found. Run `lmgrep index` first.");
334
- await index.close();
335
- return;
336
- }
337
- console.log(`\nIndex stats:`);
338
- console.log(` Files: ${info.fileCount}`);
339
- console.log(` Chunks: ${info.chunkCount}`);
340
- console.log(` Unique hashes: ${info.uniqueHashes}`);
341
- if (info.indexModel)
342
- console.log(` Index model: ${info.indexModel}`);
343
- if (info.indexDimensions)
344
- console.log(` Dimensions: ${info.indexDimensions}`);
345
- if (info.chunkCount !== info.uniqueHashes) {
346
- console.log(` Duplicates: ${info.chunkCount - info.uniqueHashes}`);
347
- }
348
- console.log(`\nEmbedding check:`);
349
- if (info.embeddingOk) {
350
- console.log(` OK (${info.embeddingLatencyMs}ms)`);
351
- }
352
- else {
353
- console.log(` FAILED`);
354
- if (info.embeddingError) {
355
- for (const line of info.embeddingError.split("\n")) {
356
- console.log(` ${line}`);
357
- }
358
- }
359
- }
360
- console.log(`\nSearch check:`);
361
- if (info.searchOk) {
362
- console.log(` OK (${info.searchResultCount} result, ${info.searchLatencyMs}ms)`);
363
- }
364
- else if (info.embeddingOk && info.fileCount > 0) {
365
- console.log(` FAILED (query returned no results)`);
366
- }
367
- else {
368
- console.log(` SKIPPED`);
369
- }
370
- if (processes.length > 0) {
371
- console.log(`\nRunning processes:`);
372
- for (const proc of processes) {
373
- const kindLabel = proc.kind === "mcp" ? "MCP server" :
374
- proc.kind === "serve" ? "serve" :
375
- "CLI";
376
- const project = proc.projectRoot ?? "unknown";
377
- const watching = proc.watching ? ", watching" : "";
378
- console.log(` ${kindLabel} (pid ${proc.pid})${watching}`);
379
- console.log(` index: ${project}`);
380
- }
381
- }
382
- else {
383
- console.log(`\nNo running lmgrep processes.`);
384
- }
385
- if (opts.changes) {
386
- console.log(`\nScanning for changes...`);
387
- const projectRoot = info.projectRoot;
388
- const projectStore = Store.forProject(projectRoot);
389
- const storedFileHashes = await projectStore.getFileHashes();
390
- const currentFiles = walkFiles(projectRoot);
391
- const { added, modified, deleted } = computeChanges(projectRoot, currentFiles, storedFileHashes);
392
- const total = added.length + modified.length + deleted.length;
393
- if (total === 0) {
394
- console.log(" No changes detected.");
395
- }
396
- else {
397
- if (added.length > 0) {
398
- console.log(` Added: ${added.length}`);
399
- for (const f of added.slice(0, 10))
400
- console.log(` + ${f}`);
401
- if (added.length > 10)
402
- console.log(` ... and ${added.length - 10} more`);
403
- }
404
- if (modified.length > 0) {
405
- console.log(` Modified: ${modified.length}`);
406
- for (const f of modified.slice(0, 10))
407
- console.log(` ~ ${f}`);
408
- if (modified.length > 10)
409
- console.log(` ... and ${modified.length - 10} more`);
410
- }
411
- if (deleted.length > 0) {
412
- console.log(` Deleted: ${deleted.length}`);
413
- for (const f of deleted.slice(0, 10))
414
- console.log(` - ${f}`);
415
- if (deleted.length > 10)
416
- console.log(` ... and ${deleted.length - 10} more`);
417
- }
418
- console.log(`\n Run \`lmgrep index\` to update the index.`);
419
- }
420
- await projectStore.close();
421
- }
422
- await index.close();
423
- });
424
- program
425
- .command("repair")
426
- .description("Detect and fix index inconsistencies (orphaned/stale chunks)")
427
- .option("-d, --dry", "Show what would be repaired without making changes")
428
- .option("--json", "Output repair results as JSON")
429
- .action(async (opts) => {
430
- const cwd = process.cwd();
431
- const index = await createIndex({ cwd });
432
- const result = await index.repair(opts.dry);
433
- if (opts.json) {
434
- console.log(JSON.stringify(result, null, 2));
435
- }
436
- await index.close();
437
- });
438
- program
439
- .command("serve")
440
- .description("Watch the current directory and re-index on changes")
441
- .action(async () => {
442
- const cwd = process.cwd();
443
- const index = await createIndex({ cwd });
444
- await index.watch();
445
- });
446
- program
447
- .command("mcp")
448
- .description("Start the MCP server (stdio transport)")
449
- .action(async () => {
450
- await import("./mcp.js");
451
- });
452
- program
453
- .command("export")
454
- .description("Share this project's index with a peer via P2P")
455
- .action(async () => {
456
- const cwd = process.cwd();
457
- const { startExport } = await import("./lib/p2p.js");
458
- const { code, done } = await startExport({
459
- cwd,
460
- onProgress(sent, total) {
461
- process.stderr.write(`\rSending: ${sent}/${total} chunks`);
462
- },
463
- });
464
- console.log(`Share code: ${code}`);
465
- console.log("Waiting for peer... (Ctrl+C to cancel)\n");
466
- await done;
467
- process.stderr.write("\n");
468
- console.log("Transfer complete.");
469
- });
470
- program
471
- .command("init")
472
- .description("Detect your embedding setup and create config")
473
- .option("--force", "Overwrite existing config")
474
- .option("--local", "Write a project-local .lmgrep.yml instead of the global config")
475
- .action(async (opts) => {
476
- const cwd = process.cwd();
477
- const configPath = opts.local
478
- ? join(cwd, ".lmgrep.yml")
479
- : getGlobalConfigPath();
480
- if (existsSync(configPath) && !opts.force) {
481
- console.error(`Config already exists at ${configPath}. Use --force to overwrite.`);
482
- process.exit(1);
483
- }
484
- // Check if there's an existing index with model info
485
- const dbPath = getDbPath(cwd);
486
- const meta = existsSync(dbPath)
487
- ? readProjectMetadata(dbPath)
488
- : undefined;
489
- const indexFamily = meta?.model
490
- ? extractModelFamily(meta.model)
491
- : undefined;
492
- // Detect Ollama
493
- const ollama = await detectOllama();
494
- if (!ollama.running) {
495
- console.log("Ollama not detected.\n");
496
- console.log("Install Ollama:");
497
- console.log(" curl -fsSL https://ollama.com/install.sh | sh\n");
498
- if (indexFamily) {
499
- console.log(`This index was built with "${meta.model}" (${meta.dimensions} dims).`);
500
- console.log(`After installing Ollama, pull a compatible model and run \`lmgrep init\` again.`);
501
- }
502
- else {
503
- console.log("After installing, run `lmgrep init` again to auto-configure.");
504
- }
505
- // Still write a template config
506
- mkdirSync(join(configPath, ".."), { recursive: true });
507
- writeFileSync(configPath, buildConfigTemplate());
508
- console.log(`\nWrote ${configPath} (edit model before indexing)`);
509
- return;
510
- }
511
- console.log("Found Ollama.");
512
- // If we have index metadata, try to find a compatible model
513
- let selectedModel;
514
- if (indexFamily && meta?.dimensions) {
515
- console.log(`Index built with "${meta.model}" (${indexFamily}, ${meta.dimensions} dims)`);
516
- // Check if a compatible model is already pulled
517
- const compatible = ollama.models.find((m) => {
518
- const family = extractModelFamily(`ollama:${m}`);
519
- return family === indexFamily;
520
- });
521
- if (compatible) {
522
- selectedModel = compatible;
523
- console.log(`Found compatible model: ${compatible}`);
524
- }
525
- else {
526
- console.log(`\nNo compatible model found locally. You need a model from the "${indexFamily}" family.`);
527
- console.log("Pull one with:");
528
- console.log(` ollama pull ${indexFamily}\n`);
529
- console.log("Then run `lmgrep init` again to auto-configure.");
530
- }
531
- }
532
- // If no index constraint, pick the first embedding model or suggest one
533
- if (!selectedModel && !indexFamily) {
534
- if (ollama.models.length > 0) {
535
- // Prefer embedding-oriented models
536
- const embeddingModel = ollama.models.find((m) => m.includes("embed") ||
537
- m.includes("nomic") ||
538
- m.includes("bge") ||
539
- m.includes("minilm"));
540
- selectedModel = embeddingModel ?? ollama.models[0];
541
- console.log(`Using model: ${selectedModel}`);
542
- }
543
- else {
544
- console.log("\nNo models found. Pull an embedding model:");
545
- console.log(" ollama pull nomic-embed-text\n");
546
- console.log("Then run `lmgrep init` again.");
547
- }
548
- }
549
- const modelString = selectedModel
550
- ? `ollama:${selectedModel}`
551
- : undefined;
552
- mkdirSync(join(configPath, ".."), { recursive: true });
553
- writeFileSync(configPath, buildConfigTemplate({
554
- model: modelString,
555
- baseURL: modelString
556
- ? "http://localhost:11434/v1"
557
- : undefined,
558
- }));
559
- console.log(`Wrote ${configPath}`);
560
- });
561
- program
562
- .command("config")
563
- .description("Open the global config file in your editor")
564
- .action(() => {
565
- const configPath = getGlobalConfigPath();
566
- if (!existsSync(configPath)) {
567
- console.error(`No config found at ${configPath}. Run \`lmgrep init\` first.`);
568
- process.exit(1);
569
- }
570
- const editorCmd = process.env.VISUAL ?? process.env.EDITOR ?? "vi";
571
- console.log(`Opening ${configPath}`);
572
- // $EDITOR may include flags (e.g. "code -w"). Split on whitespace
573
- // for the command/flags, but pass the path as its own argv entry so
574
- // paths containing spaces (e.g. macOS "Application Support") aren't
575
- // re-split by the shell.
576
- const parts = editorCmd.trim().split(/\s+/);
577
- const editor = parts[0];
578
- const editorArgs = parts.slice(1);
579
- const result = spawnSync(editor, [...editorArgs, configPath], {
580
- stdio: "inherit",
581
- });
582
- if (result.error || (result.status != null && result.status !== 0)) {
583
- console.error(`Could not open editor "${editorCmd}". Set $EDITOR or $VISUAL.`);
584
- process.exit(1);
585
- }
586
- });
587
- program
588
- .command("migrate")
589
- .description("Rename existing index directories to match the current slug scheme")
590
- .option("-d, --dry", "Show what would be migrated without making changes")
591
- .action(async (opts) => {
592
- const baseDir = join(homedir(), ".local", "state", "lmgrep");
593
- const projects = discoverIndexedProjects();
594
- if (projects.length === 0) {
595
- console.log("No indexed projects found.");
596
- return;
597
- }
598
- const moves = [];
599
- // Track which target paths already exist on disk OR are claimed by an
600
- // already-correctly-named source — those count as conflicts for any
601
- // other source mapping to the same target.
602
- const claimedTargets = new Set();
603
- for (const { dbPath, metadata } of projects) {
604
- const id = metadata.remote ?? metadata.root;
605
- const targetSlug = buildSlug(id);
606
- const targetPath = resolve(join(baseDir, targetSlug));
607
- if (resolve(dbPath) === targetPath) {
608
- claimedTargets.add(targetPath);
609
- }
610
- }
611
- for (const { dbPath, metadata } of projects) {
612
- const id = metadata.remote ?? metadata.root;
613
- const targetSlug = buildSlug(id);
614
- const targetPath = join(baseDir, targetSlug);
615
- const targetAbs = resolve(targetPath);
616
- if (resolve(dbPath) === targetAbs)
617
- continue;
618
- const conflict = claimedTargets.has(targetAbs) || existsSync(targetPath);
619
- moves.push({ from: dbPath, to: targetPath, id, conflict });
620
- // First non-conflicting mover claims the target so subsequent
621
- // movers in this run see it as a conflict.
622
- if (!conflict)
623
- claimedTargets.add(targetAbs);
624
- }
625
- if (moves.length === 0) {
626
- console.log("All indexes already use the current slug scheme.");
627
- return;
628
- }
629
- console.log(`Found ${moves.length} index(es) to migrate:\n`);
630
- for (const m of moves) {
631
- const arrow = m.conflict ? "→ (conflict, skipped)" : "→";
632
- console.log(` ${m.from}\n ${arrow} ${m.to}\n`);
633
- }
634
- const conflicts = moves.filter((m) => m.conflict);
635
- if (conflicts.length > 0) {
636
- console.log(`${conflicts.length} conflict(s): target already exists. ` +
637
- "These are likely sibling worktrees that already share a unified " +
638
- "index — delete the stale source manually with `rm -rf` after " +
639
- "verifying it's redundant.");
640
- }
641
- if (opts.dry) {
642
- console.log("\nDry run — no changes made.");
643
- return;
644
- }
645
- let migrated = 0;
646
- for (const m of moves) {
647
- if (m.conflict)
648
- continue;
649
- try {
650
- renameSync(m.from, m.to);
651
- migrated++;
652
- }
653
- catch (err) {
654
- const msg = err instanceof Error ? err.message : String(err);
655
- console.error(`Failed to migrate ${m.from}: ${msg}`);
656
- }
657
- }
658
- console.log(`\nMigrated ${migrated} index(es).`);
659
- });
660
- program
661
- .command("compact")
662
- .description("Remove duplicate/stale chunks and compact the index to reclaim disk space")
663
- .action(async () => {
664
- const cwd = process.cwd();
665
- const store = Store.forProject(cwd);
666
- // Hold the write mutex so the cleanup's table rewrite can't race a
667
- // concurrent indexer (watcher or `lmgrep index`).
668
- await withWriteLock(cwd, async () => {
669
- const r = await store.dedupeChunks();
670
- if (r.duplicateIds + r.staleVersions > 0) {
671
- console.log(`Removed ${r.duplicateIds} duplicate and ${r.staleVersions} stale chunks (${r.before} → ${r.after}).`);
672
- }
673
- else {
674
- console.log("No duplicate or stale chunks found.");
675
- }
676
- await store.compact();
677
- });
678
- console.log("Compaction complete.");
679
- await store.close();
680
- });
681
- program
682
- .command("prune")
683
- .description("Delete the index database for the current directory")
684
- .option("--force", "Skip confirmation")
685
- .action(async (opts) => {
686
- const cwd = process.cwd();
687
- const dbPath = getDbPath(cwd);
688
- if (!existsSync(dbPath)) {
689
- console.log("No index found for this directory.");
690
- return;
691
- }
692
- if (!opts.force) {
693
- const readline = await import("node:readline");
694
- const rl = readline.createInterface({
695
- input: process.stdin,
696
- output: process.stdout,
697
- });
698
- const answer = await new Promise((resolve) => {
699
- rl.question(`Delete index at ${dbPath}? [y/N] `, resolve);
700
- });
701
- rl.close();
702
- if (answer.toLowerCase() !== "y") {
703
- console.log("Cancelled.");
704
- return;
705
- }
706
- }
707
- rmSync(dbPath, { recursive: true, force: true });
708
- console.log(`Deleted index at ${dbPath}`);
709
- });
710
- program
711
- .command("import [source]")
712
- .description("Import chunks from a peer (share code) or another lmgrep database (path). " +
713
- "If no argument is given, tries to find a legacy index for this directory.")
714
- .option("--reset", "Reset the current index before importing")
715
- .action(async (source, opts) => {
716
- const cwd = process.cwd();
717
- // P2P import if source looks like a share code
718
- if (source) {
719
- const { SHARE_CODE_RE, startImport } = await import("./lib/p2p.js");
720
- if (SHARE_CODE_RE.test(source)) {
721
- console.log("Connecting to peer...");
722
- const result = await startImport({
723
- cwd,
724
- code: source,
725
- reset: opts.reset,
726
- onProgress(received, total) {
727
- process.stderr.write(`\rReceiving: ${received}/${total} chunks`);
728
- },
729
- onMeta(meta) {
730
- console.log(`Peer index: ${meta.chunkCount} chunks` +
731
- (meta.model ? `, model: ${meta.model}` : "") +
732
- (meta.dimensions ? `, ${meta.dimensions} dims` : ""));
733
- },
734
- });
735
- process.stderr.write("\n");
736
- console.log(`Imported ${result.chunks} chunks and ${result.files} file hashes from peer.`);
737
- return;
738
- }
739
- }
740
- // Local import (existing logic)
741
- let sourcePath;
742
- const dbPath = source;
743
- if (dbPath) {
744
- sourcePath = resolve(cwd, dbPath);
745
- }
746
- else {
747
- const legacy = getLegacyDbPath(cwd);
748
- if (existsSync(legacy)) {
749
- sourcePath = legacy;
750
- console.log(`Found legacy index at ${legacy}`);
751
- }
752
- else {
753
- console.error("No legacy index found. Provide a path: lmgrep import <db-path>");
754
- process.exit(1);
755
- }
756
- }
757
- if (!existsSync(sourcePath)) {
758
- console.error(`Database not found: ${sourcePath}`);
759
- process.exit(1);
760
- }
761
- const newDbPath = getDbPath(cwd);
762
- if (resolve(sourcePath) === resolve(newDbPath)) {
763
- console.error("Source and destination are the same database.");
764
- process.exit(1);
765
- }
766
- const store = Store.forProject(cwd);
767
- if (opts.reset) {
768
- await store.reset();
769
- }
770
- const { chunks, files } = await store.importFrom(sourcePath);
771
- console.log(`Imported ${chunks} chunks and ${files} file hashes from ${sourcePath}`);
772
- // Show model info from source to guide the user
773
- const sourceMeta = readProjectMetadata(sourcePath);
774
- if (sourceMeta?.model) {
775
- const family = extractModelFamily(sourceMeta.model);
776
- console.log(`\nThis index was built with "${sourceMeta.model}" (${family}${sourceMeta.dimensions ? `, ${sourceMeta.dimensions} dims` : ""}).`);
777
- console.log(`Configure a compatible model in .lmgrep.yml, then run \`lmgrep init\` to auto-detect.`);
778
- }
779
- await store.close();
780
- });
781
- {
782
- const completionsCmd = program
783
- .command("completions")
784
- .description("Output shell completions");
785
- // Resolve the completions directory relative to this script
786
- const completionsDir = join(import.meta.dirname, "..", "completions");
787
- completionsCmd
788
- .command("zsh")
789
- .description("Output zsh completions")
790
- .option("--install", "Install to site-functions and reload completions")
791
- .action((opts) => {
792
- const script = readFileSync(join(completionsDir, "_lmgrep"), "utf-8");
793
- if (opts.install) {
794
- const siteFunctions = findZshSiteFunctions();
795
- if (!siteFunctions) {
796
- console.error("Could not find a writable zsh site-functions directory.\n" +
797
- "Output manually with: lmgrep completions zsh > /path/to/_lmgrep");
798
- process.exit(1);
799
- }
800
- const target = join(siteFunctions, "_lmgrep");
801
- mkdirSync(siteFunctions, { recursive: true });
802
- writeFileSync(target, script);
803
- console.log(`Installed completions to ${target}`);
804
- console.log("Restart your shell or run: exec zsh");
805
- return;
806
- }
807
- console.log(script);
808
- });
809
- }
810
- // Auto-detect MCP mode: no args + both stdin and stdout are piped (stdio transport)
811
- const userArgs = process.argv.slice(2);
812
- if (userArgs.length === 0 && !process.stdin.isTTY && !process.stdout.isTTY) {
813
- await import("./mcp.js");
814
- }
815
- else {
816
- program.parse();
817
- }
818
- // --- Zsh helpers ---
819
- function findZshSiteFunctions() {
820
- // Prefer user-local paths, fall back to system paths
821
- const candidates = [
822
- join(homedir(), ".local", "share", "zsh", "site-functions"),
823
- "/usr/local/share/zsh/site-functions",
824
- "/usr/share/zsh/site-functions",
825
- ];
826
- // Also check $fpath entries that contain "site-functions"
827
- try {
828
- const fpath = execSync("zsh -c 'echo $fpath'", {
829
- stdio: ["ignore", "pipe", "ignore"],
830
- timeout: 3000,
831
- })
832
- .toString()
833
- .trim();
834
- for (const p of fpath.split(" ")) {
835
- if (p.includes("site-functions") && !candidates.includes(p)) {
836
- candidates.push(p);
837
- }
838
- }
839
- }
840
- catch { }
841
- // Return the first candidate that exists or is in a writable parent
842
- for (const candidate of candidates) {
843
- try {
844
- if (existsSync(candidate)) {
845
- // Check if writable
846
- writeFileSync(join(candidate, ".lmgrep-test"), "");
847
- rmSync(join(candidate, ".lmgrep-test"));
848
- return candidate;
849
- }
850
- // Check if parent is writable (we can create the dir)
851
- const parent = join(candidate, "..");
852
- if (existsSync(parent)) {
853
- mkdirSync(candidate, { recursive: true });
854
- return candidate;
855
- }
856
- }
857
- catch {
858
- // not writable, try next
859
- }
860
- }
861
- return undefined;
862
- }
863
- // --- Helpers ---
864
- async function detectOllama() {
865
- try {
866
- const res = await fetch("http://localhost:11434/api/tags", {
867
- signal: AbortSignal.timeout(3000),
868
- });
869
- if (!res.ok)
870
- return { running: true, models: [] };
871
- const data = (await res.json());
872
- const models = (data.models ?? []).map((m) => m.name);
873
- return { running: true, models };
874
- }
875
- catch {
876
- return { running: false, models: [] };
877
- }
878
- }
879
- function buildConfigTemplate(overrides) {
880
- const model = overrides?.model;
881
- const hasModel = !!model;
882
- const modelLine = hasModel
883
- ? `model: ${model}`
884
- : `# model: ollama:nomic-embed-text # ← set your model here`;
885
- const baseURLLine = overrides?.baseURL
886
- ? `baseURL: ${overrides.baseURL}`
887
- : `# baseURL: http://localhost:11434/v1`;
888
- return `# lmgrep configuration
889
- #
890
- # Quick start with Ollama:
891
- # 1. Install: curl -fsSL https://ollama.com/install.sh | sh
892
- # 2. Pull a model: ollama pull nomic-embed-text
893
- # 3. Run: lmgrep init --force (to auto-detect)
894
-
895
- # Embedding model in "provider:model" format
896
- ${modelLine}
897
-
898
- # Base URL for the embedding API
899
- ${baseURLLine}
900
-
901
- # Batch size for embedding API calls
902
- batchSize: 100
903
-
904
- # Optional: override the provider package
905
- # provider: "@ai-sdk/openai"
906
-
907
- # Optional: embedding dimensions (if model supports it)
908
- # dimensions: 384
909
-
910
- # Optional: max tokens per chunk (estimated at 4 chars/token)
911
- # maxTokens: 8192
912
-
913
- # Optional: prefixes for asymmetric embedding models
914
- # queryPrefix: "search_query: "
915
- # documentPrefix: "search_document: "
916
-
917
- # Optional: additional ignore patterns (merged with .gitignore)
918
- # ignore:
919
- # - "*.generated.ts"
920
- # - "fixtures/"
921
-
922
- # Optional: extra file extensions to index
923
- # extensions:
924
- # include: [".sql", ".graphql", ".proto"]
925
- # exclude: [".json"]
926
- `;
927
- }
928
- function computeChanges(projectRoot, currentFiles, storedFileHashes) {
929
- const added = [];
930
- const modified = [];
931
- const deleted = [];
932
- const seen = new Set();
933
- for (const file of currentFiles) {
934
- seen.add(file);
935
- try {
936
- const content = readFileSync(join(projectRoot, file));
937
- const fileHash = createHash("sha256")
938
- .update(content)
939
- .digest("hex")
940
- .slice(0, 16);
941
- const stored = storedFileHashes.get(file);
942
- if (!stored) {
943
- added.push(file);
944
- }
945
- else if (stored !== fileHash) {
946
- modified.push(file);
947
- }
948
- }
949
- catch { }
950
- }
951
- for (const [fp] of storedFileHashes) {
952
- if (!seen.has(fp))
953
- deleted.push(fp);
954
- }
955
- return { added, modified, deleted };
956
- }
5
+ import "./infrastructure/lancedb/NativeTuning.js";
6
+ import { Cli } from "./presentation/cli/Cli.js";
7
+ await new Cli().run();
957
8
  //# sourceMappingURL=cli.js.map