codesearch-mcp 0.2.3-alpha → 0.4.0-alpha

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 (317) hide show
  1. package/CHANGELOG.md +88 -5
  2. package/LICENSE +661 -21
  3. package/README.md +76 -40
  4. package/dist/app.js +17 -38
  5. package/dist/src/ast/CallExtractor.d.ts +8 -0
  6. package/dist/src/ast/CallExtractor.js +68 -0
  7. package/dist/src/ast/GraphqlNameExtractor.d.ts +22 -0
  8. package/dist/src/ast/GraphqlNameExtractor.js +240 -0
  9. package/dist/src/ast/ImportEdgeExtractor.d.ts +11 -0
  10. package/dist/src/ast/ImportEdgeExtractor.js +129 -0
  11. package/dist/src/ast/IndexedNodeResolver.d.ts +14 -0
  12. package/dist/src/ast/IndexedNodeResolver.js +217 -0
  13. package/dist/src/ast/MemberExtractor.d.ts +8 -0
  14. package/dist/src/ast/MemberExtractor.js +129 -0
  15. package/dist/src/ast/TopLevelSymbolExtractor.d.ts +5 -0
  16. package/dist/src/ast/TopLevelSymbolExtractor.js +86 -0
  17. package/dist/src/ast/graphql-grammar.d.ts +24 -0
  18. package/dist/src/ast/graphql-grammar.js +93 -0
  19. package/dist/src/ast/node-helpers.d.ts +11 -0
  20. package/dist/src/ast/node-helpers.js +55 -0
  21. package/dist/src/chunking/AstChunker.d.ts +12 -0
  22. package/dist/src/chunking/AstChunker.js +30 -0
  23. package/dist/src/chunking/CharacterChunkStrategy.d.ts +8 -0
  24. package/dist/src/chunking/CharacterChunkStrategy.js +15 -0
  25. package/dist/src/chunking/DeclarationChunkStrategy.d.ts +15 -0
  26. package/dist/src/chunking/DeclarationChunkStrategy.js +87 -0
  27. package/dist/src/chunking/FragmentMerger.d.ts +11 -0
  28. package/dist/src/chunking/FragmentMerger.js +61 -0
  29. package/dist/src/chunking/ImportOnlyFilter.d.ts +5 -0
  30. package/dist/src/chunking/ImportOnlyFilter.js +14 -0
  31. package/dist/src/chunking/LangchainTextSplitter.d.ts +21 -0
  32. package/dist/src/chunking/LangchainTextSplitter.js +133 -0
  33. package/dist/src/chunking/MinSizeSplitPolicy.d.ts +9 -0
  34. package/dist/src/chunking/MinSizeSplitPolicy.js +18 -0
  35. package/dist/src/chunking/RunPacker.d.ts +12 -0
  36. package/dist/src/chunking/RunPacker.js +84 -0
  37. package/dist/src/chunking/create-chunker.d.ts +3 -0
  38. package/dist/src/chunking/create-chunker.js +15 -0
  39. package/dist/src/chunking/interfaces.d.ts +27 -0
  40. package/dist/src/commands/ConfigCommand.js +1 -9
  41. package/dist/src/commands/EvalCommand.d.ts +10 -5
  42. package/dist/src/commands/EvalCommand.js +60 -149
  43. package/dist/src/commands/IndexCommand.d.ts +10 -4
  44. package/dist/src/commands/IndexCommand.js +52 -146
  45. package/dist/src/commands/McpCommand.d.ts +6 -3
  46. package/dist/src/commands/McpCommand.js +19 -20
  47. package/dist/src/commands/WebCommand.d.ts +9 -3
  48. package/dist/src/commands/WebCommand.js +17 -11
  49. package/dist/src/commands/eval/baseline-comparison.d.ts +6 -0
  50. package/dist/src/commands/eval/baseline-comparison.js +54 -0
  51. package/dist/src/commands/eval/eval-args.d.ts +6 -0
  52. package/dist/src/commands/eval/eval-args.js +71 -0
  53. package/dist/src/commands/eval/eval-corpora.d.ts +6 -0
  54. package/dist/src/commands/eval/eval-corpora.js +76 -0
  55. package/dist/src/commands/eval/eval-metadata.d.ts +17 -0
  56. package/dist/src/commands/eval/eval-metadata.js +75 -0
  57. package/dist/src/commands/eval/index-inspector.d.ts +3 -0
  58. package/dist/src/commands/eval/index-inspector.js +21 -0
  59. package/dist/src/commands/eval/staged-search.d.ts +3 -0
  60. package/dist/src/commands/eval/staged-search.js +20 -0
  61. package/dist/src/commands/eval/suite-loader.d.ts +8 -0
  62. package/dist/src/commands/eval/suite-loader.js +52 -0
  63. package/dist/src/commands/index/backend-probe.d.ts +2 -0
  64. package/dist/src/commands/index/backend-probe.js +15 -0
  65. package/dist/src/commands/index/embedding-setup.d.ts +3 -0
  66. package/dist/src/commands/index/embedding-setup.js +16 -0
  67. package/dist/src/commands/index/index-summary.d.ts +2 -0
  68. package/dist/src/commands/index/index-summary.js +22 -0
  69. package/dist/src/commands/index/legacy-ollama-guard.d.ts +3 -0
  70. package/dist/src/commands/index/legacy-ollama-guard.js +23 -0
  71. package/dist/src/commands/index/prune-step.d.ts +3 -0
  72. package/dist/src/commands/index/prune-step.js +22 -0
  73. package/dist/src/commands/index/scan-targets.d.ts +8 -0
  74. package/dist/src/commands/index/scan-targets.js +107 -0
  75. package/dist/src/config-error.d.ts +0 -4
  76. package/dist/src/config-error.js +0 -4
  77. package/dist/src/config-store.d.ts +1 -55
  78. package/dist/src/config-store.js +11 -73
  79. package/dist/src/config.d.ts +9 -18
  80. package/dist/src/config.js +36 -35
  81. package/dist/src/constants.d.ts +17 -28
  82. package/dist/src/constants.js +35 -29
  83. package/dist/src/container.d.ts +10 -2
  84. package/dist/src/container.js +19 -8
  85. package/dist/src/db/drizzle-types.d.ts +7 -0
  86. package/dist/src/db/drizzle-types.js +2 -0
  87. package/dist/src/db/index.d.ts +1 -0
  88. package/dist/src/db/schema-steps.d.ts +8 -0
  89. package/dist/src/db/schema-steps.js +105 -0
  90. package/dist/src/db/schema.d.ts +17 -0
  91. package/dist/src/db/schema.js +1 -6
  92. package/dist/src/declarations/DeclarationTree.d.ts +19 -0
  93. package/dist/src/declarations/DeclarationTree.js +66 -0
  94. package/dist/src/declarations/DeclarationTreeBuilder.d.ts +22 -0
  95. package/dist/src/declarations/DeclarationTreeBuilder.js +179 -0
  96. package/dist/src/declarations/SourceLines.d.ts +37 -0
  97. package/dist/src/declarations/SourceLines.js +415 -0
  98. package/dist/src/dependency-traversal.d.ts +0 -6
  99. package/dist/src/dependency-traversal.js +0 -6
  100. package/dist/src/enriched-prompt.d.ts +0 -6
  101. package/dist/src/enriched-prompt.js +0 -6
  102. package/dist/src/error-record.d.ts +12 -0
  103. package/dist/src/error-record.js +248 -0
  104. package/dist/src/eval-corpus.d.ts +16 -0
  105. package/dist/src/eval-corpus.js +169 -0
  106. package/dist/src/eval-results.d.ts +6 -3
  107. package/dist/src/eval-results.js +323 -26
  108. package/dist/src/eval-vector-index.d.ts +5 -0
  109. package/dist/src/eval-vector-index.js +60 -0
  110. package/dist/src/file-utils.d.ts +0 -5
  111. package/dist/src/file-utils.js +0 -5
  112. package/dist/src/graph.d.ts +0 -25
  113. package/dist/src/graph.js +0 -28
  114. package/dist/src/help.js +9 -1
  115. package/dist/src/hnsw-settings.d.ts +3 -0
  116. package/dist/src/hnsw-settings.js +24 -0
  117. package/dist/src/index-args.d.ts +13 -0
  118. package/dist/src/index-args.js +48 -0
  119. package/dist/src/indexing/AnalysisBatcher.d.ts +12 -0
  120. package/dist/src/indexing/AnalysisBatcher.js +28 -0
  121. package/dist/src/indexing/ChunkEmbedder.d.ts +24 -0
  122. package/dist/src/indexing/ChunkEmbedder.js +37 -0
  123. package/dist/src/indexing/ConsoleScanReporter.d.ts +10 -0
  124. package/dist/src/indexing/ConsoleScanReporter.js +73 -0
  125. package/dist/src/indexing/EmbeddingSchemaPreparer.d.ts +14 -0
  126. package/dist/src/indexing/EmbeddingSchemaPreparer.js +66 -0
  127. package/dist/src/indexing/FileIngestor.d.ts +22 -0
  128. package/dist/src/indexing/FileIngestor.js +116 -0
  129. package/dist/src/indexing/IndexStore.d.ts +24 -0
  130. package/dist/src/indexing/IndexStore.js +69 -0
  131. package/dist/src/indexing/StaleFilePruner.d.ts +8 -0
  132. package/dist/src/indexing/StaleFilePruner.js +55 -0
  133. package/dist/src/indexing/analysis-rows.d.ts +4 -0
  134. package/dist/src/indexing/analysis-rows.js +65 -0
  135. package/dist/src/indexing/project-notices.d.ts +2 -0
  136. package/dist/src/indexing/project-notices.js +63 -0
  137. package/dist/src/interfaces/IAstParser.d.ts +4 -40
  138. package/dist/src/interfaces/ICallGraph.d.ts +28 -0
  139. package/dist/src/interfaces/ICallGraph.js +2 -0
  140. package/dist/src/interfaces/IChunkSearch.d.ts +42 -0
  141. package/dist/src/interfaces/IChunkSearch.js +2 -0
  142. package/dist/src/interfaces/IChunker.d.ts +3 -12
  143. package/dist/src/interfaces/ICorpusInspector.d.ts +7 -0
  144. package/dist/src/interfaces/ICorpusInspector.js +2 -0
  145. package/dist/src/interfaces/IDatabase.d.ts +8 -24
  146. package/dist/src/interfaces/IDependencyGraph.d.ts +24 -0
  147. package/dist/src/interfaces/IDependencyGraph.js +2 -0
  148. package/dist/src/interfaces/IEmbedder.d.ts +0 -9
  149. package/dist/src/interfaces/IIndexIdentityGuard.d.ts +3 -0
  150. package/dist/src/interfaces/IIndexIdentityGuard.js +2 -0
  151. package/dist/src/interfaces/IIndexedNodeResolver.d.ts +10 -0
  152. package/dist/src/interfaces/IIndexedNodeResolver.js +2 -0
  153. package/dist/src/interfaces/ILogger.d.ts +1 -11
  154. package/dist/src/interfaces/IMcpReadiness.d.ts +12 -0
  155. package/dist/src/interfaces/IMcpReadiness.js +2 -0
  156. package/dist/src/interfaces/IMcpToolHandler.d.ts +0 -5
  157. package/dist/src/interfaces/IMonorepoResolver.d.ts +0 -22
  158. package/dist/src/interfaces/IProjectCatalog.d.ts +13 -0
  159. package/dist/src/interfaces/IProjectCatalog.js +2 -0
  160. package/dist/src/interfaces/IProjectDiscovery.d.ts +0 -17
  161. package/dist/src/interfaces/IProjectRoots.d.ts +3 -0
  162. package/dist/src/interfaces/IProjectRoots.js +2 -0
  163. package/dist/src/interfaces/IRetrievalEvaluator.d.ts +153 -12
  164. package/dist/src/interfaces/IScanReporter.d.ts +13 -0
  165. package/dist/src/interfaces/IScanReporter.js +2 -0
  166. package/dist/src/interfaces/ISymbolLookup.d.ts +49 -0
  167. package/dist/src/interfaces/ISymbolLookup.js +2 -0
  168. package/dist/src/interfaces/IToolPaths.d.ts +62 -0
  169. package/dist/src/interfaces/IToolPaths.js +2 -0
  170. package/dist/src/interfaces/IWorkspaceFiles.d.ts +28 -0
  171. package/dist/src/interfaces/IWorkspaceFiles.js +2 -0
  172. package/dist/src/interfaces/SymbolKind.d.ts +1 -0
  173. package/dist/src/interfaces/SymbolKind.js +2 -0
  174. package/dist/src/interfaces/index.d.ts +12 -1
  175. package/dist/src/interrupt.js +0 -2
  176. package/dist/src/owner-path.d.ts +9 -10
  177. package/dist/src/owner-path.js +11 -23
  178. package/dist/src/project-scope.d.ts +1 -12
  179. package/dist/src/project-scope.js +5 -12
  180. package/dist/src/project-selector.d.ts +0 -5
  181. package/dist/src/project-selector.js +0 -11
  182. package/dist/src/retrieval-eval.d.ts +15 -6
  183. package/dist/src/retrieval-eval.js +388 -59
  184. package/dist/src/search/CallGraph.d.ts +9 -0
  185. package/dist/src/search/CallGraph.js +84 -0
  186. package/dist/src/search/ChunkSearch.d.ts +23 -0
  187. package/dist/src/search/ChunkSearch.js +115 -0
  188. package/dist/src/search/DependencyGraph.d.ts +19 -0
  189. package/dist/src/search/DependencyGraph.js +180 -0
  190. package/dist/src/search/IndexIdentityGuard.d.ts +11 -0
  191. package/dist/src/search/IndexIdentityGuard.js +37 -0
  192. package/dist/src/search/ProjectCatalog.d.ts +11 -0
  193. package/dist/src/search/ProjectCatalog.js +38 -0
  194. package/dist/src/search/SymbolLookup.d.ts +24 -0
  195. package/dist/src/search/SymbolLookup.js +97 -0
  196. package/dist/src/search/chunks/CandidateFetcher.d.ts +19 -0
  197. package/dist/src/search/chunks/CandidateFetcher.js +40 -0
  198. package/dist/src/search/chunks/IterativeScanGate.d.ts +10 -0
  199. package/dist/src/search/chunks/IterativeScanGate.js +42 -0
  200. package/dist/src/search/chunks/RerankStage.d.ts +15 -0
  201. package/dist/src/search/chunks/RerankStage.js +42 -0
  202. package/dist/src/search/chunks/search-metrics.d.ts +18 -0
  203. package/dist/src/search/chunks/search-metrics.js +32 -0
  204. package/dist/src/search/chunks/search-plan.d.ts +18 -0
  205. package/dist/src/search/chunks/search-plan.js +19 -0
  206. package/dist/src/search/create-search-services.d.ts +26 -0
  207. package/dist/src/search/create-search-services.js +29 -0
  208. package/dist/src/search/index-paths.d.ts +1 -0
  209. package/dist/src/search/index-paths.js +5 -0
  210. package/dist/src/search/result-shaping.d.ts +4 -0
  211. package/dist/src/search/result-shaping.js +19 -0
  212. package/dist/src/search/symbol-sql.d.ts +13 -0
  213. package/dist/src/search/symbol-sql.js +66 -0
  214. package/dist/src/search/symbols/SymbolGrepFallback.d.ts +19 -0
  215. package/dist/src/search/symbols/SymbolGrepFallback.js +106 -0
  216. package/dist/src/search/symbols/SymbolIndexQuery.d.ts +14 -0
  217. package/dist/src/search/symbols/SymbolIndexQuery.js +52 -0
  218. package/dist/src/search/symbols/SymbolTextSearch.d.ts +13 -0
  219. package/dist/src/search/symbols/SymbolTextSearch.js +84 -0
  220. package/dist/src/search/symbols/TargetColumnGate.d.ts +7 -0
  221. package/dist/src/search/symbols/TargetColumnGate.js +23 -0
  222. package/dist/src/search/symbols/find-symbol-constants.d.ts +4 -0
  223. package/dist/src/search/symbols/find-symbol-constants.js +8 -0
  224. package/dist/src/search/symbols/grep-args.d.ts +3 -0
  225. package/dist/src/search/symbols/grep-args.js +7 -0
  226. package/dist/src/search/symbols/grep-patterns.d.ts +4 -0
  227. package/dist/src/search/symbols/grep-patterns.js +60 -0
  228. package/dist/src/services/AstParserService.d.ts +10 -106
  229. package/dist/src/services/AstParserService.js +37 -1068
  230. package/dist/src/services/DatabaseService.d.ts +10 -17
  231. package/dist/src/services/DatabaseService.js +71 -115
  232. package/dist/src/services/EmbedderFactory.d.ts +0 -4
  233. package/dist/src/services/EmbedderFactory.js +0 -5
  234. package/dist/src/services/IndexerService.d.ts +7 -26
  235. package/dist/src/services/IndexerService.js +38 -286
  236. package/dist/src/services/InfinityEmbedder.d.ts +0 -21
  237. package/dist/src/services/InfinityEmbedder.js +0 -15
  238. package/dist/src/services/LoggerService.d.ts +7 -5
  239. package/dist/src/services/LoggerService.js +37 -41
  240. package/dist/src/services/McpReadiness.d.ts +18 -0
  241. package/dist/src/services/McpReadiness.js +73 -0
  242. package/dist/src/services/McpServer.d.ts +50 -19
  243. package/dist/src/services/McpServer.js +132 -62
  244. package/dist/src/services/MonorepoAwareDiscoveryService.d.ts +1 -45
  245. package/dist/src/services/MonorepoAwareDiscoveryService.js +1 -51
  246. package/dist/src/services/NxMonorepoResolver.d.ts +0 -29
  247. package/dist/src/services/NxMonorepoResolver.js +5 -56
  248. package/dist/src/services/OpenAICompatibleEmbedder.d.ts +0 -6
  249. package/dist/src/services/OpenAICompatibleEmbedder.js +0 -14
  250. package/dist/src/services/ProjectDiscoveryService.d.ts +0 -4
  251. package/dist/src/services/ProjectDiscoveryService.js +0 -4
  252. package/dist/src/services/VoyageEmbedder.d.ts +0 -6
  253. package/dist/src/services/VoyageEmbedder.js +0 -6
  254. package/dist/src/services/WebServerService.d.ts +5 -56
  255. package/dist/src/services/WebServerService.js +25 -63
  256. package/dist/src/services/http-retry.d.ts +0 -7
  257. package/dist/src/services/http-retry.js +1 -10
  258. package/dist/src/services/infinity-provisioning.d.ts +0 -74
  259. package/dist/src/services/infinity-provisioning.js +5 -88
  260. package/dist/src/services/legacy-ollama-index.d.ts +0 -16
  261. package/dist/src/services/legacy-ollama-index.js +0 -23
  262. package/dist/src/services/reranker.d.ts +0 -9
  263. package/dist/src/services/reranker.js +46 -12
  264. package/dist/src/setup.d.ts +24 -24
  265. package/dist/src/setup.js +205 -103
  266. package/dist/src/symbol-name.d.ts +1 -12
  267. package/dist/src/symbol-name.js +16 -25
  268. package/dist/src/symbol-rows.d.ts +0 -14
  269. package/dist/src/symbol-rows.js +0 -14
  270. package/dist/src/tool-call-log.d.ts +2 -0
  271. package/dist/src/tool-call-log.js +24 -0
  272. package/dist/src/tools/FindSymbolTool.d.ts +17 -7
  273. package/dist/src/tools/FindSymbolTool.js +54 -35
  274. package/dist/src/tools/GetCallersTool.d.ts +16 -8
  275. package/dist/src/tools/GetCallersTool.js +65 -35
  276. package/dist/src/tools/GetDependenciesTool.d.ts +16 -8
  277. package/dist/src/tools/GetDependenciesTool.js +36 -29
  278. package/dist/src/tools/GetDependentsTool.d.ts +20 -8
  279. package/dist/src/tools/GetDependentsTool.js +48 -34
  280. package/dist/src/tools/ListFilesTool.d.ts +16 -8
  281. package/dist/src/tools/ListFilesTool.js +20 -26
  282. package/dist/src/tools/ListProjectsTool.d.ts +11 -7
  283. package/dist/src/tools/ListProjectsTool.js +13 -11
  284. package/dist/src/tools/McpTool.d.ts +17 -0
  285. package/dist/src/tools/McpTool.js +28 -0
  286. package/dist/src/tools/ReadFileRangeTool.d.ts +16 -8
  287. package/dist/src/tools/ReadFileRangeTool.js +23 -25
  288. package/dist/src/tools/ReadFileTool.d.ts +15 -8
  289. package/dist/src/tools/ReadFileTool.js +19 -24
  290. package/dist/src/tools/SearchCodebaseTool.d.ts +22 -10
  291. package/dist/src/tools/SearchCodebaseTool.js +71 -50
  292. package/dist/src/tools/format-helpers.d.ts +9 -9
  293. package/dist/src/tools/format-helpers.js +146 -28
  294. package/dist/src/tools/tool-args.d.ts +38 -0
  295. package/dist/src/tools/tool-args.js +95 -0
  296. package/dist/src/web/dashboard.d.ts +0 -8
  297. package/dist/src/web/dashboard.js +7 -10
  298. package/dist/src/workspace/GrepRunner.d.ts +15 -0
  299. package/dist/src/workspace/GrepRunner.js +104 -0
  300. package/dist/src/workspace/ProjectRoots.d.ts +22 -0
  301. package/dist/src/workspace/ProjectRoots.js +102 -0
  302. package/dist/src/workspace/ToolPaths.d.ts +31 -0
  303. package/dist/src/workspace/ToolPaths.js +312 -0
  304. package/dist/src/workspace/WorkspaceFiles.d.ts +19 -0
  305. package/dist/src/workspace/WorkspaceFiles.js +285 -0
  306. package/dist/src/workspace/fs-access.d.ts +9 -0
  307. package/dist/src/workspace/fs-access.js +47 -0
  308. package/dist/src/workspace/path-helpers.d.ts +3 -0
  309. package/dist/src/workspace/path-helpers.js +43 -0
  310. package/package.json +5 -4
  311. package/dist/src/interfaces/ISearcher.d.ts +0 -35
  312. package/dist/src/services/AstChunker.d.ts +0 -42
  313. package/dist/src/services/AstChunker.js +0 -158
  314. package/dist/src/services/SearcherService.d.ts +0 -342
  315. package/dist/src/services/SearcherService.js +0 -1199
  316. package/docs/web-dashboard.md +0 -206
  317. /package/dist/src/{interfaces/ISearcher.js → chunking/interfaces.js} +0 -0
@@ -54,11 +54,7 @@ exports.CONFIG_DIR = path.join(os.homedir(), '.config', 'codesearch-mcp');
54
54
  exports.CONFIG_FILE = path.join(exports.CONFIG_DIR, 'config.json');
55
55
  exports.SCHEMA_FILE = path.join(exports.CONFIG_DIR, 'config.schema.json');
56
56
  exports.ENV_FILE = path.join(exports.CONFIG_DIR, '.env');
57
- // Relative $schema reference written into config.json so editors resolve the
58
- // sibling schema file for autocomplete / inline validation.
59
57
  const SCHEMA_REF = './config.schema.json';
60
- // All fields optional — defaults live in config.ts. The file stays minimal.
61
- // Descriptions surface as tooltips in schema-aware editors (VS Code, JetBrains).
62
58
  const jsonSchema = zod_1.z.object({
63
59
  db: zod_1.z.object({
64
60
  host: zod_1.z.string().describe('PostgreSQL host').optional(),
@@ -83,24 +79,23 @@ const jsonSchema = zod_1.z.object({
83
79
  chunkStrategy: zod_1.z.enum(['ast', 'character']).describe('How TS/JS files are chunked: ast = symbol-aligned boundaries, character = fixed-size recursive splitter (default ast)').optional(),
84
80
  }).optional(),
85
81
  search: zod_1.z.object({
86
- similarityThreshold: zod_1.z.number().min(0).max(1).describe('Max cosine distance 0–1; lower = stricter (default 0.6)').optional(),
82
+ similarityThreshold: zod_1.z.number().min(0).max(1).describe('Max cosine distance 0–1, lower = stricter. Unset: recommended value for the embedding model').optional(),
87
83
  defaultLimit: zod_1.z.number().int().describe('Default result count (default 5)').optional(),
88
84
  maxLimit: zod_1.z.number().int().describe('Hard cap on results (default 20)').optional(),
89
85
  }).optional(),
90
86
  reranker: zod_1.z.object({
91
- enabled: zod_1.z.boolean().describe('Enable cross-encoder reranking; requires reranker.model').optional(),
92
- provider: zod_1.z.enum(['openai-compatible']).describe('Rerank backend. Only openai-compatible /rerank servers (Infinity, TEI, vLLM).').optional(),
93
- baseURL: zod_1.z.string().describe('Rerank server base URL (defaults to embedding.baseURL — Infinity serves both).').optional(),
94
- apiKey: zod_1.z.string().describe('API key, or env:VAR_NAME. Empty for local servers.').optional(),
95
- model: zod_1.z.string().describe('Reranker model name (e.g. qllama/bge-reranker-v2-m3)').optional(),
87
+ enabled: zod_1.z.boolean().describe('Enable cross-encoder reranking (default true with infinity embedding or when reranker.provider/baseURL/url is set, else false)').optional(),
88
+ provider: zod_1.z.enum(['openai-compatible', 'voyage']).describe('Rerank backend: openai-compatible /rerank servers (Infinity, vLLM) or voyage (Voyage AI, requires reranker.apiKey) (default openai-compatible)').optional(),
89
+ baseURL: zod_1.z.string().describe('Rerank server base URL (default embedding.baseURL for openai-compatible — Infinity serves both; https://api.voyageai.com/v1 for voyage)').optional(),
90
+ apiKey: zod_1.z.string().describe('API key, or env:VAR_NAME. Empty for local servers; required for voyage.').optional(),
91
+ model: zod_1.z.string().describe('Reranker model name (default mixedbread-ai/mxbai-rerank-xsmall-v1 for openai-compatible, rerank-3 for voyage)').optional(),
96
92
  url: zod_1.z.string().describe('Full URL of the rerank endpoint (default derived from provider + baseURL)').optional(),
97
- overfetch: zod_1.z.number().int().min(1).max(20).describe('Candidate multiplier before reranking (limit × N, default 5)').optional(),
98
- candidateFloor: zod_1.z.number().int().min(1).describe('Minimum candidate pool fed to the reranker regardless of limit; fetchLimit = min(max(limit × overfetch, candidateFloor), 200) (default 80)').optional(),
93
+ overfetch: zod_1.z.number().int().min(1).max(20).describe('Candidate multiplier before reranking (limit × N, default 5); also sizes the pool of a search without reranking whose per-file limit is below limit').optional(),
94
+ candidateFloor: zod_1.z.number().int().min(1).describe('Minimum candidate pool fed to the reranker regardless of limit; fetchLimit = min(max(limit × overfetch, candidateFloor), 200) (default 80); the same pool serves a search without reranking whose per-file limit is below limit').optional(),
99
95
  }).optional(),
100
96
  logging: zod_1.z.object({
101
97
  level: zod_1.z.enum(['debug', 'info', 'warn', 'error']).describe('File log level (default error)').optional(),
102
98
  dir: zod_1.z.string().describe('Base log directory; "false" to disable file logging').optional(),
103
- searchMetrics: zod_1.z.boolean().describe('Emit one structured search-tuning line (info level) per search, independent of level (default false)').optional(),
104
99
  }).optional(),
105
100
  workspaceRoot: zod_1.z.string().describe('Full path to the directory containing all your projects').optional(),
106
101
  });
@@ -134,22 +129,9 @@ const FIELD_TYPES = {
134
129
  'reranker.candidateFloor': 'number',
135
130
  'logging.level': 'string',
136
131
  'logging.dir': 'string',
137
- 'logging.searchMetrics': 'boolean',
138
132
  'workspaceRoot': 'string',
139
133
  };
140
134
  exports.ALL_KEYS = Object.keys(FIELD_TYPES);
141
- /**
142
- * Single source of truth for built-in defaults, keyed by raw config.json dotted
143
- * key. Consumed both by the web dashboard (`GET /api/defaults`) and by
144
- * `resolvedSchema` in `src/config.ts`, whose `.default(...)` calls reference
145
- * these values — so the runtime default and the dashboard-displayed default
146
- * cannot diverge. `as const` keeps the literal types so those `.default()`
147
- * lookups stay type-safe. Keys omitted here have no static default: required
148
- * fields (db.host/user/password) and values derived at runtime — db.name →
149
- * rag_<user>, and the provider-dependent URLs (embedding.baseURL,
150
- * reranker.baseURL, reranker.url), which are computed in the `Config`
151
- * constructor per provider rather than through a schema `.default(...)`.
152
- */
153
135
  exports.CONFIG_DEFAULTS = {
154
136
  'db.port': 5433,
155
137
  'embedding.provider': 'infinity',
@@ -161,7 +143,6 @@ exports.CONFIG_DEFAULTS = {
161
143
  'indexing.embedBatchSize': 5,
162
144
  'indexing.astBatchSize': 3000,
163
145
  'indexing.chunkStrategy': 'ast',
164
- 'search.similarityThreshold': 0.6,
165
146
  'search.defaultLimit': 5,
166
147
  'search.maxLimit': 20,
167
148
  'reranker.enabled': true,
@@ -171,7 +152,6 @@ exports.CONFIG_DEFAULTS = {
171
152
  'reranker.overfetch': 5,
172
153
  'reranker.candidateFloor': 80,
173
154
  'logging.level': 'error',
174
- 'logging.searchMetrics': false,
175
155
  };
176
156
  function readConfigJson() {
177
157
  if (!fs.existsSync(exports.CONFIG_FILE))
@@ -181,7 +161,7 @@ function readConfigJson() {
181
161
  raw = fs.readFileSync(exports.CONFIG_FILE, 'utf-8');
182
162
  }
183
163
  catch (e) {
184
- throw new Error(`Cannot read ${exports.CONFIG_FILE}: ${e.message}`);
164
+ throw new Error(`Cannot read ${exports.CONFIG_FILE}: ${e.message}`, { cause: e });
185
165
  }
186
166
  let parsed;
187
167
  try {
@@ -189,7 +169,7 @@ function readConfigJson() {
189
169
  }
190
170
  catch (e) {
191
171
  throw new Error(`Invalid JSON in ${exports.CONFIG_FILE}: ${e.message}\n` +
192
- `Fix the file manually or delete it and run: rag-setup`);
172
+ `Fix the file manually or delete it and run: rag-setup`, { cause: e });
193
173
  }
194
174
  return parseConfig(parsed, exports.CONFIG_FILE);
195
175
  }
@@ -198,19 +178,9 @@ const OLLAMA_MIGRATION_REMEDY = 'The "ollama" embedding provider has been remove
198
178
  'and embedding.baseURL to "http://localhost:11434/v1" — via `rag-config edit` (or by ' +
199
179
  'editing the config file directly) or by re-running `rag-setup`. After switching, rebuild ' +
200
180
  'the index with `rag-index --reindex`.';
201
- /** Strip a trailing `:tag` (Docker-style) from a model name, if present. */
202
181
  function stripModelTag(model) {
203
182
  return model.replace(/:[^:]*$/, '');
204
183
  }
205
- /**
206
- * Detect a raw (pre-migration) config object that still selects the removed
207
- * `ollama` embedding provider — explicitly, via a legacy top-level `ollama`
208
- * block, or implicitly (no `provider` set, but `baseURL`/`model` point at
209
- * Ollama's defaults) — and throw a `ConfigError` with migration guidance
210
- * instead of letting it validate under a silently reinterpreted provider.
211
- * Runs before `migrateRawConfig` so a legacy `ollama.*` block is never
212
- * converted into an `embedding` block first. Pure — never mutates `raw`.
213
- */
214
184
  function detectFormerOllamaConfig(raw) {
215
185
  if (raw == null || typeof raw !== 'object')
216
186
  return;
@@ -227,7 +197,7 @@ function detectFormerOllamaConfig(raw) {
227
197
  try {
228
198
  port = new URL(e.baseURL).port;
229
199
  }
230
- catch { /* unparsable — not a signal */ }
200
+ catch { }
231
201
  if (port === '11434') {
232
202
  throw new config_error_1.ConfigError(`Config's embedding.baseURL targets Ollama's default port (11434) with no embedding.provider set. ${OLLAMA_MIGRATION_REMEDY}`);
233
203
  }
@@ -242,21 +212,6 @@ function detectFormerOllamaConfig(raw) {
242
212
  throw new config_error_1.ConfigError(`Config has a legacy "ollama" configuration block. ${OLLAMA_MIGRATION_REMEDY}`);
243
213
  }
244
214
  }
245
- /**
246
- * Migrate a legacy raw config object to the current shape, in place of a
247
- * versioned migration system. Pure — returns a new object, never mutates input.
248
- *
249
- * - Removed translation keys (`search.autoTranslate`, `search.translateModel`)
250
- * are dropped so they neither validate-fail nor take effect.
251
- * - Legacy `reranker.provider: 'ollama'` (a dead value — Ollama has no rerank
252
- * API) is rewritten to `openai-compatible`, and a stale `/api/rerank` URL is
253
- * dropped so it re-derives to `/rerank`. Otherwise the tightened enum would
254
- * fail validation on existing configs and lock the user out.
255
- *
256
- * A legacy top-level `ollama` block reaches here only when `detectFormerOllamaConfig`
257
- * did not already reject it (i.e. an `embedding` block is also present); it is
258
- * dropped rather than merged. Exported for unit testing.
259
- */
260
215
  function migrateRawConfig(raw) {
261
216
  if (raw == null || typeof raw !== 'object')
262
217
  return raw;
@@ -274,16 +229,6 @@ function migrateRawConfig(raw) {
274
229
  }
275
230
  return obj;
276
231
  }
277
- /**
278
- * Validate a raw (pre-migration) config object against the Zod schema: first
279
- * `detectFormerOllamaConfig` (a `ConfigError` on a former-Ollama config takes
280
- * priority over both migration and the regular Zod enum rejection), then
281
- * `migrateRawConfig`, then the schema itself. Unknown keys (e.g. the "$schema"
282
- * editor reference) are stripped. Throws with a caller-friendly message on
283
- * validation failure. The single entry point for both `readConfigJson` and
284
- * `PUT /api/config`, so both apply identical rules with an identical message.
285
- * Pure — no file I/O.
286
- */
287
232
  function parseConfig(raw, source = exports.CONFIG_FILE) {
288
233
  detectFormerOllamaConfig(raw);
289
234
  const migrated = migrateRawConfig(raw);
@@ -295,7 +240,6 @@ function parseConfig(raw, source = exports.CONFIG_FILE) {
295
240
  }
296
241
  return result.data;
297
242
  }
298
- /** Build the JSON Schema object generated from the Zod config schema. Pure. */
299
243
  function buildJsonSchema() {
300
244
  return {
301
245
  $id: 'https://github.com/oleksandr-antoniuk/RAG/config.schema.json',
@@ -306,15 +250,9 @@ function buildJsonSchema() {
306
250
  function writeConfigJson(data) {
307
251
  fs.mkdirSync(exports.CONFIG_DIR, { recursive: true });
308
252
  writeSchemaFile();
309
- // $schema first so editors pick it up; readConfigJson strips it on validation.
310
253
  const withSchema = { $schema: SCHEMA_REF, ...data };
311
254
  fs.writeFileSync(exports.CONFIG_FILE, JSON.stringify(withSchema, null, 2) + '\n', { mode: 0o600 });
312
255
  }
313
- /**
314
- * Generate a JSON Schema from the Zod config schema and write it next to
315
- * config.json. Editors resolve it via the "$schema" reference and provide
316
- * key autocomplete, type hints, and inline validation while editing.
317
- */
318
256
  function writeSchemaFile() {
319
257
  fs.mkdirSync(exports.CONFIG_DIR, { recursive: true });
320
258
  fs.writeFileSync(exports.SCHEMA_FILE, JSON.stringify(buildJsonSchema(), null, 2) + '\n');
@@ -1,13 +1,12 @@
1
+ import { type JsonConfig } from './config-store';
1
2
  import { ConfigError } from './config-error';
2
3
  export { ConfigError };
3
- /**
4
- * Resolve a config value that may reference an environment variable. A value of
5
- * the form `env:VAR_NAME` resolves to `process.env.VAR_NAME`; any other string
6
- * (including empty) is returned verbatim. A referenced-but-unset variable throws
7
- * a clear error naming the variable and the `.env` file. Pure aside from the
8
- * injected env map. See `src/app.ts` for how `.env` is loaded into the process.
9
- */
10
4
  export declare function resolveEnvRef(value: string, env?: NodeJS.ProcessEnv): string;
5
+ export declare function rerankContext(raw: JsonConfig): {
6
+ wanted: boolean;
7
+ missingKey: boolean;
8
+ model: string;
9
+ };
11
10
  export declare class Config {
12
11
  private readonly data;
13
12
  get db(): {
@@ -17,13 +16,6 @@ export declare class Config {
17
16
  password: string;
18
17
  database: string;
19
18
  };
20
- /**
21
- * Embedding config. `apiKey` is returned **raw** (possibly an `env:VAR` ref) —
22
- * callers resolve it lazily via `resolveEnvRef` at the moment they build a
23
- * request, so an unset referenced variable fails only when the key is actually
24
- * needed (during embed/search) rather than crashing container construction and
25
- * locking the user out of `rag-web`/`rag-mcp`.
26
- */
27
19
  get embedding(): {
28
20
  provider: "openai-compatible" | "voyage" | "infinity";
29
21
  baseURL: string;
@@ -32,14 +24,14 @@ export declare class Config {
32
24
  dimensions: number | null;
33
25
  batchSize: number;
34
26
  };
35
- /** Reranker config. `apiKey` is raw — resolve lazily with `resolveEnvRef`. */
36
27
  get reranker(): {
37
28
  enabled: boolean;
38
- provider: "openai-compatible";
29
+ provider: "openai-compatible" | "voyage";
39
30
  baseURL: string;
40
31
  apiKey: string;
41
32
  model: string;
42
33
  url: string;
34
+ missingApiKey: boolean;
43
35
  overfetch: number;
44
36
  candidateFloor: number;
45
37
  };
@@ -51,13 +43,12 @@ export declare class Config {
51
43
  chunkStrategy: "ast" | "character";
52
44
  };
53
45
  get search(): {
54
- similarityThreshold: number;
55
46
  defaultLimit: number;
56
47
  maxLimit: number;
48
+ similarityThreshold?: number | undefined;
57
49
  };
58
50
  get logging(): {
59
51
  level: "error" | "debug" | "info" | "warn";
60
- searchMetrics: boolean;
61
52
  dir?: string | undefined;
62
53
  };
63
54
  get workspaceRoot(): string;
@@ -35,18 +35,13 @@ var __importStar = (this && this.__importStar) || (function () {
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.Config = exports.ConfigError = void 0;
37
37
  exports.resolveEnvRef = resolveEnvRef;
38
+ exports.rerankContext = rerankContext;
38
39
  const os = __importStar(require("os"));
39
40
  const zod_1 = require("zod");
40
41
  const config_store_1 = require("./config-store");
42
+ const constants_1 = require("./constants");
41
43
  const config_error_1 = require("./config-error");
42
44
  Object.defineProperty(exports, "ConfigError", { enumerable: true, get: function () { return config_error_1.ConfigError; } });
43
- /**
44
- * Resolve a config value that may reference an environment variable. A value of
45
- * the form `env:VAR_NAME` resolves to `process.env.VAR_NAME`; any other string
46
- * (including empty) is returned verbatim. A referenced-but-unset variable throws
47
- * a clear error naming the variable and the `.env` file. Pure aside from the
48
- * injected env map. See `src/app.ts` for how `.env` is loaded into the process.
49
- */
50
45
  function resolveEnvRef(value, env = process.env) {
51
46
  if (!value.startsWith('env:'))
52
47
  return value;
@@ -66,12 +61,19 @@ const DEFAULT_BASE_URLS = {
66
61
  function defaultBaseURL(provider) {
67
62
  return DEFAULT_BASE_URLS[provider] ?? DEFAULT_BASE_URLS.infinity;
68
63
  }
69
- // Reranking is served only by OpenAI-compatible `/rerank` endpoints (Infinity,
70
- // TEI, vLLM, Jina/Cohere-shape) — a single endpoint shape. Normalize a trailing
71
- // `/embeddings` or `/v1` to the server root so a baseURL written with an
72
- // OpenAI-style suffix still yields `<root>/rerank`.
73
- function deriveRerankUrl(baseURL) {
74
- const root = baseURL.replace(/\/+$/, '').replace(/\/(embeddings|v1)$/, '');
64
+ function rerankContext(raw) {
65
+ const rr = raw.reranker;
66
+ const embProvider = raw.embedding?.provider ?? config_store_1.CONFIG_DEFAULTS['embedding.provider'];
67
+ const isVoyage = (rr?.provider ?? config_store_1.CONFIG_DEFAULTS['reranker.provider']) === 'voyage';
68
+ return {
69
+ wanted: embProvider === 'infinity' || rr?.provider != null || rr?.baseURL != null || rr?.url != null,
70
+ missingKey: isVoyage && !rr?.apiKey,
71
+ model: isVoyage ? constants_1.VOYAGE_RERANK_MODELS[0] : config_store_1.CONFIG_DEFAULTS['reranker.model'],
72
+ };
73
+ }
74
+ function deriveRerankUrl(provider, baseURL) {
75
+ const trimmed = baseURL.replace(/\/+$/, '');
76
+ const root = provider === 'voyage' ? trimmed : trimmed.replace(/\/(embeddings|v1)$/, '');
75
77
  return `${root}/rerank`;
76
78
  }
77
79
  const resolvedSchema = zod_1.z.object({
@@ -91,12 +93,13 @@ const resolvedSchema = zod_1.z.object({
91
93
  batchSize: zod_1.z.number().int().positive().default(config_store_1.CONFIG_DEFAULTS['embedding.batchSize']),
92
94
  }),
93
95
  reranker: zod_1.z.object({
94
- enabled: zod_1.z.boolean().default(config_store_1.CONFIG_DEFAULTS['reranker.enabled']),
95
- provider: zod_1.z.enum(['openai-compatible']).default(config_store_1.CONFIG_DEFAULTS['reranker.provider']),
96
+ enabled: zod_1.z.boolean(),
97
+ provider: zod_1.z.enum(['openai-compatible', 'voyage']).default(config_store_1.CONFIG_DEFAULTS['reranker.provider']),
96
98
  baseURL: zod_1.z.string().min(1),
97
99
  apiKey: zod_1.z.string().default(config_store_1.CONFIG_DEFAULTS['reranker.apiKey']),
98
- model: zod_1.z.string().default(config_store_1.CONFIG_DEFAULTS['reranker.model']),
100
+ model: zod_1.z.string(),
99
101
  url: zod_1.z.string().min(1),
102
+ missingApiKey: zod_1.z.boolean(),
100
103
  overfetch: zod_1.z.number().int().min(1).max(20).default(config_store_1.CONFIG_DEFAULTS['reranker.overfetch']),
101
104
  candidateFloor: zod_1.z.number().int().min(1).default(config_store_1.CONFIG_DEFAULTS['reranker.candidateFloor']),
102
105
  }),
@@ -108,29 +111,20 @@ const resolvedSchema = zod_1.z.object({
108
111
  chunkStrategy: zod_1.z.enum(['ast', 'character']).default(config_store_1.CONFIG_DEFAULTS['indexing.chunkStrategy']),
109
112
  }),
110
113
  search: zod_1.z.object({
111
- similarityThreshold: zod_1.z.number().min(0).max(1).default(config_store_1.CONFIG_DEFAULTS['search.similarityThreshold']),
114
+ similarityThreshold: zod_1.z.number().min(0).max(1).optional(),
112
115
  defaultLimit: zod_1.z.number().int().positive().default(config_store_1.CONFIG_DEFAULTS['search.defaultLimit']),
113
116
  maxLimit: zod_1.z.number().int().positive().default(config_store_1.CONFIG_DEFAULTS['search.maxLimit']),
114
117
  }),
115
118
  logging: zod_1.z.object({
116
119
  level: zod_1.z.enum(['debug', 'info', 'warn', 'error']).default(config_store_1.CONFIG_DEFAULTS['logging.level']),
117
120
  dir: zod_1.z.string().optional(),
118
- searchMetrics: zod_1.z.boolean().default(config_store_1.CONFIG_DEFAULTS['logging.searchMetrics']),
119
121
  }),
120
122
  workspaceRoot: zod_1.z.string().default(''),
121
123
  });
122
124
  class Config {
123
125
  data;
124
126
  get db() { return this.data.db; }
125
- /**
126
- * Embedding config. `apiKey` is returned **raw** (possibly an `env:VAR` ref) —
127
- * callers resolve it lazily via `resolveEnvRef` at the moment they build a
128
- * request, so an unset referenced variable fails only when the key is actually
129
- * needed (during embed/search) rather than crashing container construction and
130
- * locking the user out of `rag-web`/`rag-mcp`.
131
- */
132
127
  get embedding() { return this.data.embedding; }
133
- /** Reranker config. `apiKey` is raw — resolve lazily with `resolveEnvRef`. */
134
128
  get reranker() { return this.data.reranker; }
135
129
  get indexer() { return this.data.indexer; }
136
130
  get search() { return this.data.search; }
@@ -142,8 +136,15 @@ class Config {
142
136
  throw new config_error_1.ConfigError('Config not found. Run rag-setup.');
143
137
  const embProvider = (raw.embedding?.provider ?? config_store_1.CONFIG_DEFAULTS['embedding.provider']);
144
138
  const embBaseURL = raw.embedding?.baseURL ?? defaultBaseURL(embProvider);
145
- const rerankBaseURL = raw.reranker?.baseURL ?? embBaseURL;
146
- const rerankUrl = raw.reranker?.url ?? deriveRerankUrl(rerankBaseURL);
139
+ const rr = raw.reranker;
140
+ const rerankProvider = (rr?.provider ?? config_store_1.CONFIG_DEFAULTS['reranker.provider']);
141
+ const isVoyageRerank = rerankProvider === 'voyage';
142
+ const rerankBaseURL = rr?.baseURL ?? (isVoyageRerank ? DEFAULT_BASE_URLS.voyage : embBaseURL);
143
+ const rerankUrl = rr?.url ?? deriveRerankUrl(rerankProvider, rerankBaseURL);
144
+ const rerankCtx = rerankContext(raw);
145
+ const rerankModel = rr?.model ?? rerankCtx.model;
146
+ const rerankWanted = rr?.enabled ?? rerankCtx.wanted;
147
+ const missingApiKey = rerankWanted && rerankCtx.missingKey;
147
148
  const result = resolvedSchema.safeParse({
148
149
  db: {
149
150
  host: raw.db?.host,
@@ -161,14 +162,15 @@ class Config {
161
162
  batchSize: raw.embedding?.batchSize,
162
163
  },
163
164
  reranker: {
164
- enabled: raw.reranker?.enabled,
165
- provider: raw.reranker?.provider,
165
+ enabled: rerankWanted && !missingApiKey,
166
+ provider: rr?.provider,
166
167
  baseURL: rerankBaseURL,
167
- apiKey: raw.reranker?.apiKey,
168
- model: raw.reranker?.model,
168
+ apiKey: rr?.apiKey,
169
+ model: rerankModel,
169
170
  url: rerankUrl,
170
- overfetch: raw.reranker?.overfetch,
171
- candidateFloor: raw.reranker?.candidateFloor,
171
+ missingApiKey,
172
+ overfetch: rr?.overfetch,
173
+ candidateFloor: rr?.candidateFloor,
172
174
  },
173
175
  indexer: {
174
176
  chunkSize: raw.indexing?.chunkSize,
@@ -185,7 +187,6 @@ class Config {
185
187
  logging: {
186
188
  level: raw.logging?.level,
187
189
  dir: raw.logging?.dir,
188
- searchMetrics: raw.logging?.searchMetrics,
189
190
  },
190
191
  workspaceRoot: raw.workspaceRoot,
191
192
  });
@@ -1,42 +1,31 @@
1
1
  export type EmbeddingProvider = 'openai-compatible' | 'voyage' | 'infinity';
2
- /**
3
- * pgvector's HNSW / IVFFlat index hard limit. The effective embedding dimension
4
- * must not exceed this; larger cloud models must reduce via the Matryoshka
5
- * `dimensions` request parameter (`embedding.dimensions`).
6
- */
2
+ export type RerankProvider = 'openai-compatible' | 'voyage';
3
+ export declare const VOYAGE_RERANK_MODELS: readonly ["rerank-3", "rerank-3-lite"];
7
4
  export declare const MAX_EMBED_DIM = 2000;
8
5
  export interface ModelInfo {
9
6
  provider: EmbeddingProvider;
10
- /** Native / default output width. */
11
7
  dimensions: number;
12
- /** Model supports Matryoshka dimension reduction via a request parameter. */
13
8
  dimConfigurable?: boolean;
14
- /** Max width that can be indexed under the pgvector cap (advisory). */
15
9
  maxIndexable?: number;
16
- /** Max width the model itself can emit (advisory). */
17
10
  maxDim?: number;
11
+ defaultThreshold?: number;
18
12
  }
19
- /**
20
- * Advisory (NOT exhaustive) registry of known embedding models. Used to resolve
21
- * a model's dimension without a runtime probe and to suggest models in the
22
- * dashboard. Models absent here still work — their dimension is probed at index
23
- * time (see `resolveDimension`).
24
- */
25
13
  export declare const MODEL_REGISTRY: Record<string, ModelInfo>;
26
14
  export declare const DEFAULT_EMBED_MODEL = "jinaai/jina-embeddings-v2-base-code";
27
- /**
28
- * Former Ollama registry model names, kept only so config validation can
29
- * recognise an implicit (provider-less) config that still targets Ollama —
30
- * see `detectFormerOllamaConfig` in `config-store.ts`.
31
- */
32
15
  export declare const FORMER_OLLAMA_MODELS: readonly ["bge-m3", "nomic-embed-text", "mxbai-embed-large"];
33
- /** Advisory dimension for a model, or `undefined` when the model is unknown. */
34
16
  export declare function registryDimension(model: string): number | undefined;
35
- /**
36
- * Resolve the effective vector dimension: explicit override → registry → probe.
37
- * Validates the result is ≤ MAX_EMBED_DIM, throwing an error that names
38
- * `embedding.dimensions` as the fix. `probeFn` embeds a short string once and
39
- * returns the observed length; only called when neither override nor registry
40
- * yields a value. Pure aside from the injected probe.
41
- */
17
+ export type ThresholdSource = 'call' | 'config' | 'model' | 'fallback';
18
+ export interface ResolvedThreshold {
19
+ value: number;
20
+ source: ThresholdSource;
21
+ }
22
+ export declare const FALLBACK_THRESHOLD = 1;
23
+ export declare function resolveThreshold({ callValue, configValue, model, registry }: {
24
+ callValue?: number;
25
+ configValue?: number;
26
+ model: string;
27
+ registry?: Record<string, ModelInfo>;
28
+ }): ResolvedThreshold;
29
+ export declare function formatThreshold(value: number): string;
30
+ export declare function thresholdMismatchWarning(configValue: number | undefined, model: string, registry?: Record<string, ModelInfo>): string | null;
42
31
  export declare function resolveDimension(override: number | null | undefined, model: string, probeFn: () => Promise<number>, registry?: Record<string, ModelInfo>): Promise<number>;
@@ -1,48 +1,54 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.FORMER_OLLAMA_MODELS = exports.DEFAULT_EMBED_MODEL = exports.MODEL_REGISTRY = exports.MAX_EMBED_DIM = void 0;
3
+ exports.FALLBACK_THRESHOLD = exports.FORMER_OLLAMA_MODELS = exports.DEFAULT_EMBED_MODEL = exports.MODEL_REGISTRY = exports.MAX_EMBED_DIM = exports.VOYAGE_RERANK_MODELS = void 0;
4
4
  exports.registryDimension = registryDimension;
5
+ exports.resolveThreshold = resolveThreshold;
6
+ exports.formatThreshold = formatThreshold;
7
+ exports.thresholdMismatchWarning = thresholdMismatchWarning;
5
8
  exports.resolveDimension = resolveDimension;
6
- /**
7
- * pgvector's HNSW / IVFFlat index hard limit. The effective embedding dimension
8
- * must not exceed this; larger cloud models must reduce via the Matryoshka
9
- * `dimensions` request parameter (`embedding.dimensions`).
10
- */
9
+ exports.VOYAGE_RERANK_MODELS = ['rerank-3', 'rerank-3-lite'];
11
10
  exports.MAX_EMBED_DIM = 2000;
12
- /**
13
- * Advisory (NOT exhaustive) registry of known embedding models. Used to resolve
14
- * a model's dimension without a runtime probe and to suggest models in the
15
- * dashboard. Models absent here still work — their dimension is probed at index
16
- * time (see `resolveDimension`).
17
- */
18
11
  exports.MODEL_REGISTRY = {
19
12
  'text-embedding-3-small': { provider: 'openai-compatible', dimensions: 1536, dimConfigurable: true },
20
13
  'text-embedding-3-large': { provider: 'openai-compatible', dimensions: 3072, dimConfigurable: true, maxIndexable: 2000 },
21
14
  'text-embedding-ada-002': { provider: 'openai-compatible', dimensions: 1536 },
22
- 'voyage-code-3': { provider: 'voyage', dimensions: 1024, dimConfigurable: true, maxDim: 2048 },
23
- 'voyage-3': { provider: 'voyage', dimensions: 1024, dimConfigurable: true },
24
- 'voyage-3-lite': { provider: 'voyage', dimensions: 512 },
15
+ 'voyage-code-4': { provider: 'voyage', dimensions: 1024, dimConfigurable: true, maxDim: 2048, defaultThreshold: 0.95 },
16
+ 'voyage-4-large': { provider: 'voyage', dimensions: 1024, dimConfigurable: true, maxDim: 2048, defaultThreshold: 0.95 },
17
+ 'voyage-4': { provider: 'voyage', dimensions: 1024, dimConfigurable: true, maxDim: 2048, defaultThreshold: 0.95 },
18
+ 'voyage-4-lite': { provider: 'voyage', dimensions: 1024, dimConfigurable: true, maxDim: 2048, defaultThreshold: 0.95 },
25
19
  'BAAI/bge-m3': { provider: 'infinity', dimensions: 1024 },
26
- 'jinaai/jina-embeddings-v2-base-code': { provider: 'infinity', dimensions: 768 },
20
+ 'jinaai/jina-embeddings-v2-base-code': { provider: 'infinity', dimensions: 768, defaultThreshold: 0.6 },
27
21
  };
28
22
  exports.DEFAULT_EMBED_MODEL = 'jinaai/jina-embeddings-v2-base-code';
29
- /**
30
- * Former Ollama registry model names, kept only so config validation can
31
- * recognise an implicit (provider-less) config that still targets Ollama —
32
- * see `detectFormerOllamaConfig` in `config-store.ts`.
33
- */
34
23
  exports.FORMER_OLLAMA_MODELS = ['bge-m3', 'nomic-embed-text', 'mxbai-embed-large'];
35
- /** Advisory dimension for a model, or `undefined` when the model is unknown. */
36
24
  function registryDimension(model) {
37
25
  return exports.MODEL_REGISTRY[model]?.dimensions;
38
26
  }
39
- /**
40
- * Resolve the effective vector dimension: explicit override → registry → probe.
41
- * Validates the result is ≤ MAX_EMBED_DIM, throwing an error that names
42
- * `embedding.dimensions` as the fix. `probeFn` embeds a short string once and
43
- * returns the observed length; only called when neither override nor registry
44
- * yields a value. Pure aside from the injected probe.
45
- */
27
+ exports.FALLBACK_THRESHOLD = 1.0;
28
+ const THRESHOLD_MISMATCH_TOLERANCE = 0.1;
29
+ const FLOAT_EPSILON = 1e-9;
30
+ function resolveThreshold({ callValue, configValue, model, registry = exports.MODEL_REGISTRY }) {
31
+ if (callValue !== undefined)
32
+ return { value: callValue, source: 'call' };
33
+ if (configValue !== undefined)
34
+ return { value: configValue, source: 'config' };
35
+ const recommended = registry[model]?.defaultThreshold;
36
+ if (recommended !== undefined)
37
+ return { value: recommended, source: 'model' };
38
+ return { value: exports.FALLBACK_THRESHOLD, source: 'fallback' };
39
+ }
40
+ function formatThreshold(value) {
41
+ return Number.isInteger(value) ? value.toFixed(1) : String(value);
42
+ }
43
+ function thresholdMismatchWarning(configValue, model, registry = exports.MODEL_REGISTRY) {
44
+ const recommended = registry[model]?.defaultThreshold;
45
+ if (configValue === undefined || recommended === undefined)
46
+ return null;
47
+ if (Math.abs(configValue - recommended) <= THRESHOLD_MISMATCH_TOLERANCE + FLOAT_EPSILON)
48
+ return null;
49
+ return `search.similarityThreshold is ${formatThreshold(configValue)}, but the recommended value for ${model} is ${formatThreshold(recommended)}. `
50
+ + 'Searches may miss relevant code or return weak matches. Remove the key to follow the model, or retune it (rag-config edit).';
51
+ }
46
52
  async function resolveDimension(override, model, probeFn, registry = exports.MODEL_REGISTRY) {
47
53
  let dim;
48
54
  if (override != null) {
@@ -1,19 +1,27 @@
1
1
  import { Config } from './config';
2
2
  import { IndexerService } from './services/IndexerService';
3
+ import { type SearchServices } from './search/create-search-services';
3
4
  import { McpServer } from './services/McpServer';
5
+ import { LoggerService } from './services/LoggerService';
4
6
  import type { IDatabase } from './interfaces';
5
7
  import type { IEmbedder } from './interfaces';
6
- import type { ISearcher } from './interfaces';
7
8
  import type { ILogger } from './interfaces';
8
9
  import type { IProjectDiscovery } from './interfaces';
10
+ import type { IMcpReadiness } from './interfaces';
9
11
  export interface Container {
10
12
  config: Config;
11
13
  db: IDatabase;
12
14
  embedder: IEmbedder;
13
15
  indexer: IndexerService;
14
- searcher: ISearcher;
16
+ search: SearchServices;
17
+ readiness: IMcpReadiness;
15
18
  mcp: McpServer;
16
19
  logger: ILogger;
17
20
  discovery: IProjectDiscovery;
18
21
  }
22
+ export declare function loggerBindingsFor(loggerName?: string): Record<string, unknown> | undefined;
23
+ export declare function createLogger(cfg: {
24
+ level: string;
25
+ dir?: string;
26
+ }, loggerName?: string): LoggerService;
19
27
  export declare function createContainer(loggerName?: string): Container;
@@ -1,27 +1,38 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.loggerBindingsFor = loggerBindingsFor;
4
+ exports.createLogger = createLogger;
3
5
  exports.createContainer = createContainer;
6
+ const crypto_1 = require("crypto");
4
7
  const config_1 = require("./config");
5
8
  const DatabaseService_1 = require("./services/DatabaseService");
6
9
  const EmbedderFactory_1 = require("./services/EmbedderFactory");
7
10
  const AstParserService_1 = require("./services/AstParserService");
8
- const AstChunker_1 = require("./services/AstChunker");
11
+ const create_chunker_1 = require("./chunking/create-chunker");
9
12
  const IndexerService_1 = require("./services/IndexerService");
10
- const SearcherService_1 = require("./services/SearcherService");
13
+ const create_search_services_1 = require("./search/create-search-services");
11
14
  const McpServer_1 = require("./services/McpServer");
15
+ const McpReadiness_1 = require("./services/McpReadiness");
12
16
  const LoggerService_1 = require("./services/LoggerService");
13
17
  const MonorepoAwareDiscoveryService_1 = require("./services/MonorepoAwareDiscoveryService");
14
18
  const NxMonorepoResolver_1 = require("./services/NxMonorepoResolver");
19
+ function loggerBindingsFor(loggerName) {
20
+ return loggerName === 'mcp' ? { connectionId: (0, crypto_1.randomUUID)() } : undefined;
21
+ }
22
+ function createLogger(cfg, loggerName) {
23
+ return LoggerService_1.LoggerService.fromConfig(cfg, loggerName, loggerBindingsFor(loggerName));
24
+ }
15
25
  function createContainer(loggerName) {
16
26
  const config = new config_1.Config();
17
- const logger = LoggerService_1.LoggerService.fromConfig(config.logging, loggerName);
18
- const db = new DatabaseService_1.DatabaseService(config);
27
+ const logger = createLogger(config.logging, loggerName);
28
+ const db = new DatabaseService_1.DatabaseService(config, logger);
19
29
  const embedder = (0, EmbedderFactory_1.createEmbedder)(config, logger);
20
30
  const ast = new AstParserService_1.AstParserService(logger);
21
- const chunker = new AstChunker_1.AstChunker(config);
31
+ const chunker = (0, create_chunker_1.createChunker)(config);
22
32
  const discovery = new MonorepoAwareDiscoveryService_1.MonorepoAwareDiscoveryService([new NxMonorepoResolver_1.NxMonorepoResolver(logger)], logger);
23
33
  const indexer = new IndexerService_1.IndexerService(db, embedder, ast, chunker, config, logger);
24
- const searcher = new SearcherService_1.SearcherService(db, embedder, discovery, config, logger);
25
- const mcp = new McpServer_1.McpServer(searcher, config, logger);
26
- return { config, db, embedder, indexer, searcher, mcp, logger, discovery };
34
+ const search = (0, create_search_services_1.createSearchServices)(db, embedder, discovery, config, logger);
35
+ const readiness = new McpReadiness_1.McpReadiness(db, search.identity, logger);
36
+ const mcp = new McpServer_1.McpServer(search, readiness, config, logger);
37
+ return { config, db, embedder, indexer, search, readiness, mcp, logger, discovery };
27
38
  }
@@ -0,0 +1,7 @@
1
+ import type { NodePgDatabase, NodePgTransaction } from 'drizzle-orm/node-postgres';
2
+ import type { ExtractTablesWithRelations } from 'drizzle-orm/relations';
3
+ import * as schema from './schema';
4
+ type Schema = typeof schema;
5
+ export type DrizzleDb = NodePgDatabase<Schema>;
6
+ export type DrizzleTx = NodePgTransaction<Schema, ExtractTablesWithRelations<Schema>>;
7
+ export {};
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -1,2 +1,3 @@
1
1
  export { codeChunk, codeDependency, codeSymbol, codeCall, indexMeta } from './schema';
2
2
  export type { CodeChunkInsert } from './schema';
3
+ export type { DrizzleDb, DrizzleTx } from './drizzle-types';