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
@@ -37,27 +37,6 @@ exports.NxMonorepoResolver = void 0;
37
37
  const fs = __importStar(require("fs"));
38
38
  const path = __importStar(require("path"));
39
39
  const file_utils_1 = require("../file-utils");
40
- /**
41
- * Nx monorepo resolver.
42
- *
43
- * Detection: presence of `nx.json` at the workspace root.
44
- *
45
- * Project discovery strategies (results deduplicated by absolute path):
46
- * 1. Read `workspace.json` or `angular.json` → projects map
47
- * 2. Scan standard Nx directories (`apps/`, `libs/`, `packages/`) for
48
- * `project.json`, then `package.json` (only when strategy 1 found nothing)
49
- * 3. `tsconfig.base.json` `paths` — root-level libs referenced only by path
50
- * alias (e.g. `contracts/`, `interfaces/`) that the directory scan misses
51
- * 4. Root-level fallback: treat the workspace root itself as a project
52
- * (standalone Nx setup) when nothing else matched
53
- *
54
- * tsconfig resolution:
55
- * - Returns `tsconfig.base.json` at workspace root (Nx convention)
56
- * - Falls back to `tsconfig.json` at workspace root
57
- *
58
- * Cross-project import resolution is handled by the AST parser via the
59
- * workspace-wide tsconfig `paths` (tsconfig.base.json), so no scope map is built here.
60
- */
61
40
  class NxMonorepoResolver {
62
41
  logger;
63
42
  constructor(logger) {
@@ -67,15 +46,12 @@ class NxMonorepoResolver {
67
46
  return fs.existsSync(path.join(rootDir, 'nx.json'));
68
47
  }
69
48
  discoverProjects(rootDir) {
70
- // Deduplicate across strategies by absolute project path.
71
49
  const byPath = new Map();
72
50
  const add = (p) => { if (p && !byPath.has(p.path))
73
51
  byPath.set(p.path, p); };
74
- // Strategy 1: workspace.json / angular.json (authoritative when present)
75
52
  const workspaceProjects = this.readWorkspaceJson(rootDir);
76
53
  for (const p of workspaceProjects)
77
54
  add(p);
78
- // Strategy 2 & 3: scan standard directories (only when no workspace.json map)
79
55
  if (byPath.size === 0) {
80
56
  for (const dir of ['apps', 'libs', 'packages']) {
81
57
  const fullDir = path.join(rootDir, dir);
@@ -86,13 +62,8 @@ class NxMonorepoResolver {
86
62
  add(p);
87
63
  }
88
64
  }
89
- // Strategy 4: tsconfig.base.json `paths` — captures libs that live at the
90
- // repo root (e.g. `contracts/`, `interfaces/`) referenced by path aliases,
91
- // which the apps/libs/packages scan misses. Only real Nx projects (with a
92
- // project.json/package.json) are added; dedup handles overlap with the scan.
93
65
  for (const p of this.discoverFromTsconfigPaths(rootDir))
94
66
  add(p);
95
- // Root-level fallback (standalone Nx setup)
96
67
  if (byPath.size === 0) {
97
68
  const rootProject = this.tryReadProject(rootDir, rootDir);
98
69
  if (rootProject)
@@ -102,13 +73,6 @@ class NxMonorepoResolver {
102
73
  this.logger.debug('NxMonorepoResolver: discovered projects', { count: projects.length });
103
74
  return projects;
104
75
  }
105
- /**
106
- * Discover projects from `tsconfig.base.json` `compilerOptions.paths`. Each
107
- * alias (e.g. `@scope/interfaces` → `interfaces/src/index.ts`) resolves to a
108
- * lib root (the path before `/src/`), which for real Nx libs contains a
109
- * project.json. Aliases pointing at non-projects (no project.json/package.json,
110
- * e.g. `@env` → `environments/environment.ts`) are skipped.
111
- */
112
76
  discoverFromTsconfigPaths(rootDir) {
113
77
  const tsconfigPath = this.getRootTsConfigPath(rootDir);
114
78
  if (!tsconfigPath)
@@ -118,7 +82,7 @@ class NxMonorepoResolver {
118
82
  json = this.parseJsonc(fs.readFileSync(tsconfigPath, 'utf-8'));
119
83
  }
120
84
  catch (err) {
121
- this.logger.warn('NxMonorepoResolver: failed to parse tsconfig paths', { file: tsconfigPath, reason: err.message });
85
+ this.logger.warn('NxMonorepoResolver: failed to parse tsconfig paths', { file: tsconfigPath, err });
122
86
  return [];
123
87
  }
124
88
  const co = json?.compilerOptions ?? {};
@@ -134,13 +98,12 @@ class NxMonorepoResolver {
134
98
  const srcIdx = target.indexOf('/src/');
135
99
  const relRoot = srcIdx >= 0 ? target.slice(0, srcIdx) : path.dirname(target);
136
100
  const libRoot = path.resolve(rootDir, baseUrl, relRoot);
137
- const project = this.tryReadProject(libRoot, rootDir); // null unless a real project marker exists
101
+ const project = this.tryReadProject(libRoot, rootDir);
138
102
  if (project)
139
103
  projects.push(project);
140
104
  }
141
105
  return projects;
142
106
  }
143
- /** Parse JSON that may contain comments / trailing commas (tsconfig style). */
144
107
  parseJsonc(text) {
145
108
  try {
146
109
  return JSON.parse(text);
@@ -154,17 +117,14 @@ class NxMonorepoResolver {
154
117
  }
155
118
  }
156
119
  getRootTsConfigPath(rootDir) {
157
- // Nx convention: tsconfig.base.json at workspace root
158
120
  const basePath = path.join(rootDir, 'tsconfig.base.json');
159
121
  if (fs.existsSync(basePath))
160
122
  return basePath;
161
- // Fallback: tsconfig.json at workspace root
162
123
  const rootPath = path.join(rootDir, 'tsconfig.json');
163
124
  if (fs.existsSync(rootPath))
164
125
  return rootPath;
165
126
  return null;
166
127
  }
167
- // ── Private helpers ─────────────────────────────────────────────────────────
168
128
  readWorkspaceJson(rootDir) {
169
129
  const projects = [];
170
130
  for (const filename of ['workspace.json', 'angular.json']) {
@@ -175,9 +135,6 @@ class NxMonorepoResolver {
175
135
  const content = JSON.parse(fs.readFileSync(filePath, 'utf-8'));
176
136
  const projectsMap = content.projects ?? {};
177
137
  for (const [name, value] of Object.entries(projectsMap)) {
178
- // value can be a string (path) or an object with a `root` property.
179
- // Guard per-entry: a malformed entry (object without `root`) must not
180
- // abort discovery of the remaining projects in this file.
181
138
  const rawRoot = typeof value === 'string'
182
139
  ? value
183
140
  : value?.root;
@@ -196,7 +153,7 @@ class NxMonorepoResolver {
196
153
  catch (err) {
197
154
  this.logger.warn('NxMonorepoResolver: failed to parse workspace file', {
198
155
  file: filePath,
199
- reason: err.message,
156
+ err,
200
157
  });
201
158
  }
202
159
  }
@@ -222,14 +179,12 @@ class NxMonorepoResolver {
222
179
  projects.push(project);
223
180
  continue;
224
181
  }
225
- // Check for nested grouping directories (e.g. libs/shared/utils)
226
182
  const nested = this.scanDirectory(projectPath, defaultType, rootDir);
227
183
  projects.push(...nested);
228
184
  }
229
185
  return projects;
230
186
  }
231
187
  tryReadProject(projectPath, rootDir, defaultType = 'lib') {
232
- // Check for project.json (Nx project marker)
233
188
  const projectJsonPath = path.join(projectPath, 'project.json');
234
189
  const packageJsonPath = path.join(projectPath, 'package.json');
235
190
  const hasProjectJson = fs.existsSync(projectJsonPath);
@@ -239,7 +194,6 @@ class NxMonorepoResolver {
239
194
  let name = path.relative(rootDir, projectPath).replace(/\\/g, '/');
240
195
  let type = defaultType;
241
196
  let packageName = null;
242
- // Read project.json for name and type
243
197
  if (hasProjectJson) {
244
198
  try {
245
199
  const projectJson = JSON.parse(fs.readFileSync(projectJsonPath, 'utf-8'));
@@ -253,14 +207,12 @@ class NxMonorepoResolver {
253
207
  catch (err) {
254
208
  this.logger.warn('NxMonorepoResolver: failed to parse project.json', {
255
209
  file: projectJsonPath,
256
- reason: err.message,
210
+ err,
257
211
  });
258
212
  }
259
213
  }
260
- // Read package.json for npm scope
261
214
  if (hasPackageJson) {
262
215
  packageName = this.readPackageName(projectPath);
263
- // If no project.json name, use package name without scope
264
216
  if (!hasProjectJson && packageName) {
265
217
  const shortName = packageName.replace(/^@[^/]+\//, '');
266
218
  name = shortName;
@@ -281,7 +233,6 @@ class NxMonorepoResolver {
281
233
  }
282
234
  }
283
235
  inferProjectType(projectPath, name) {
284
- // Check project.json
285
236
  const projectJsonPath = path.join(projectPath, 'project.json');
286
237
  if (fs.existsSync(projectJsonPath)) {
287
238
  try {
@@ -291,15 +242,13 @@ class NxMonorepoResolver {
291
242
  if (projectJson.projectType === 'library')
292
243
  return 'lib';
293
244
  }
294
- catch { /* fall through */ }
245
+ catch { }
295
246
  }
296
- // Infer from path
297
247
  const rel = projectPath.replace(/\\/g, '/');
298
248
  if (rel.includes('/apps/') || rel.includes('/app/'))
299
249
  return 'app';
300
250
  if (rel.includes('/libs/') || rel.includes('/lib/') || rel.includes('/packages/'))
301
251
  return 'lib';
302
- // Infer from name
303
252
  if (name.includes('lib') || name.includes('shared') || name.includes('util'))
304
253
  return 'lib';
305
254
  return 'app';
@@ -5,12 +5,6 @@ export interface EmbedderDeps {
5
5
  fetchImpl?: typeof fetch;
6
6
  baseDelayMs?: number;
7
7
  }
8
- /**
9
- * Embedder for any server exposing an OpenAI-style `/embeddings` endpoint:
10
- * OpenAI cloud, Infinity, TEI, vLLM, LM Studio, LocalAI. One request carries all
11
- * inputs (`{ input: string[], model, dimensions? }`) and returns
12
- * `{ data: [{ embedding, index }] }`, re-ordered to input order.
13
- */
14
8
  export declare class OpenAICompatibleEmbedder implements IEmbedder {
15
9
  protected config: Config;
16
10
  private logger;
@@ -6,12 +6,6 @@ const config_1 = require("../config");
6
6
  const reranker_1 = require("./reranker");
7
7
  const http_retry_1 = require("./http-retry");
8
8
  const constants_1 = require("../constants");
9
- /**
10
- * Embedder for any server exposing an OpenAI-style `/embeddings` endpoint:
11
- * OpenAI cloud, Infinity, TEI, vLLM, LM Studio, LocalAI. One request carries all
12
- * inputs (`{ input: string[], model, dimensions? }`) and returns
13
- * `{ data: [{ embedding, index }] }`, re-ordered to input order.
14
- */
15
9
  class OpenAICompatibleEmbedder {
16
10
  config;
17
11
  logger;
@@ -24,7 +18,6 @@ class OpenAICompatibleEmbedder {
24
18
  this.config = config;
25
19
  this.logger = logger;
26
20
  const base = config.embedding.baseURL.replace(/\/+$/, '');
27
- // Allow a baseURL that already includes the path (…/v1) or not.
28
21
  this.url = /\/embeddings$/.test(base) ? base : `${base}/embeddings`;
29
22
  this.doFetch = deps.fetchImpl ?? fetch;
30
23
  this.baseDelayMs = deps.baseDelayMs;
@@ -40,8 +33,6 @@ class OpenAICompatibleEmbedder {
40
33
  return [];
41
34
  return (0, http_retry_1.withRetry)(async () => {
42
35
  const headers = { 'Content-Type': 'application/json' };
43
- // Resolve the key lazily — an unset `env:` ref throws here (request time),
44
- // not at construction, so `rag-web`/`rag-mcp` still start.
45
36
  const apiKey = (0, config_1.resolveEnvRef)(this.config.embedding.apiKey);
46
37
  if (apiKey)
47
38
  headers['Authorization'] = `Bearer ${apiKey}`;
@@ -51,7 +42,6 @@ class OpenAICompatibleEmbedder {
51
42
  const res = await this.doFetch(this.url, {
52
43
  method: 'POST',
53
44
  headers,
54
- // CPU inference of one batch of token-dense text (e.g. pseudo-localized strings) takes well over 2 min.
55
45
  signal: AbortSignal.timeout(240_000),
56
46
  body: JSON.stringify(body),
57
47
  });
@@ -60,13 +50,9 @@ class OpenAICompatibleEmbedder {
60
50
  throw new http_retry_1.HttpError(res.status, `embeddings request failed: ${res.status} ${errBody}`);
61
51
  }
62
52
  const data = await res.json();
63
- // Guard against a partial/mismatched response — a missing vector would
64
- // otherwise be inserted as "[undefined]" and fail the whole file, or (with
65
- // reordering + no index) silently misalign vectors to the wrong chunks.
66
53
  if (!Array.isArray(data.data) || data.data.length !== texts.length) {
67
54
  throw new Error(`embeddings response returned ${data.data?.length ?? 0} vectors for ${texts.length} inputs`);
68
55
  }
69
- // Sort by `index` so vectors line up with input order regardless of server ordering.
70
56
  return [...data.data]
71
57
  .sort((a, b) => (a.index ?? 0) - (b.index ?? 0))
72
58
  .map(d => d.embedding);
@@ -1,8 +1,4 @@
1
1
  import type { IProjectDiscovery, DiscoveredProject } from '../interfaces/IProjectDiscovery';
2
- /**
3
- * Default project discovery: finds immediate subdirectories
4
- * of the workspace root that contain a package.json.
5
- */
6
2
  export declare class ProjectDiscoveryService implements IProjectDiscovery {
7
3
  discover(rootDir: string): DiscoveredProject[];
8
4
  }
@@ -37,10 +37,6 @@ exports.ProjectDiscoveryService = void 0;
37
37
  const fs = __importStar(require("fs"));
38
38
  const path = __importStar(require("path"));
39
39
  const file_utils_1 = require("../file-utils");
40
- /**
41
- * Default project discovery: finds immediate subdirectories
42
- * of the workspace root that contain a package.json.
43
- */
44
40
  class ProjectDiscoveryService {
45
41
  discover(rootDir) {
46
42
  return fs.readdirSync(rootDir, { withFileTypes: true })
@@ -2,12 +2,6 @@ import type { Config } from '../config';
2
2
  import type { IEmbedder, InputType } from '../interfaces/IEmbedder';
3
3
  import type { ILogger } from '../interfaces/ILogger';
4
4
  import type { EmbedderDeps } from './OpenAICompatibleEmbedder';
5
- /**
6
- * Voyage AI embedder. Voyage's schema differs from OpenAI's: `input` is an array
7
- * of strings, `input_type` (`query` | `document`) is required for best quality,
8
- * and the optional `output_dimension` requests Matryoshka truncation. Response
9
- * is `{ data: [{ embedding, index }] }`.
10
- */
11
5
  export declare class VoyageEmbedder implements IEmbedder {
12
6
  private config;
13
7
  private logger;
@@ -6,12 +6,6 @@ const config_1 = require("../config");
6
6
  const reranker_1 = require("./reranker");
7
7
  const http_retry_1 = require("./http-retry");
8
8
  const constants_1 = require("../constants");
9
- /**
10
- * Voyage AI embedder. Voyage's schema differs from OpenAI's: `input` is an array
11
- * of strings, `input_type` (`query` | `document`) is required for best quality,
12
- * and the optional `output_dimension` requests Matryoshka truncation. Response
13
- * is `{ data: [{ embedding, index }] }`.
14
- */
15
9
  class VoyageEmbedder {
16
10
  config;
17
11
  logger;
@@ -1,5 +1,5 @@
1
1
  import { Config } from '../config';
2
- import type { ISearcher } from '../interfaces';
2
+ import type { IProjectCatalog, IDependencyGraph } from '../interfaces';
3
3
  import type { IEmbedder } from '../interfaces';
4
4
  import type { ILogger } from '../interfaces';
5
5
  import { type JsonConfig } from '../config-store';
@@ -17,47 +17,20 @@ export interface BackendStatus {
17
17
  finishedAt: string | null;
18
18
  }
19
19
  export interface WebServerDeps {
20
- /** Path to the managed docker-compose.yml. Defaults to `CONFIG_DIR/docker-compose.yml`. */
21
20
  composePath?: string;
22
- /** Injection seams (fetchImpl/runCommand/pollIntervalMs/readinessTimeoutMs) for the readiness primitive. */
23
21
  provisioning?: ProvisioningDeps;
24
- /** Reads the just-saved config back — defaults to `() => new Config()`. Injectable for tests. */
25
22
  readSavedConfig?: () => Config;
26
23
  }
27
- /**
28
- * Per-field choice lists for the config form. `strict` → render a dropdown that
29
- * only accepts a listed value (e.g. the embedding model, tied to the vector
30
- * dimension). Non-strict → a combobox: the values are suggestions but free text
31
- * is still allowed (e.g. any model served by a self-hosted backend).
32
- */
33
24
  export interface FieldOption {
34
25
  values: string[];
35
26
  strict: boolean;
36
27
  }
37
- /** Placeholder shown to the browser instead of a real secret. */
38
28
  export declare const PASSWORD_MASK = "********";
39
- /**
40
- * Merge a config submitted from the browser with the stored one. Any secret
41
- * field (DB password, embedding/reranker API keys) still holding the mask means
42
- * the user did not change it — restore the stored value rather than overwrite it
43
- * with the placeholder. `env:` references are not masked and round-trip as-is.
44
- * Pure — no I/O. Exported for unit testing.
45
- */
46
29
  export declare function mergeConfigForSave(incoming: JsonConfig, existing: JsonConfig | null): JsonConfig;
47
- /**
48
- * Return a copy of the config with raw secrets (DB password, raw API keys)
49
- * replaced by the mask, so real secrets never reach the browser. `env:`
50
- * references are left verbatim — they are not secret and the dashboard shows
51
- * them as "set via <VAR>". The masked value round-trips through
52
- * `mergeConfigForSave`. Pure — no I/O. Exported for unit testing.
53
- */
54
30
  export declare function maskConfig(cfg: JsonConfig): JsonConfig;
55
- /**
56
- * Local HTTP dashboard. Serves a schema-driven config editor, a project
57
- * overview, and the dependency graph. Bind to 127.0.0.1 only — no auth.
58
- */
59
31
  export declare class WebServer {
60
- private readonly searcher;
32
+ private readonly catalog;
33
+ private readonly dependencies;
61
34
  private readonly config;
62
35
  private readonly logger;
63
36
  private readonly embedder;
@@ -68,46 +41,22 @@ export declare class WebServer {
68
41
  private backendStatus;
69
42
  private taskInFlight;
70
43
  private pending;
71
- constructor(searcher: ISearcher, config: Config, logger: ILogger, embedder: IEmbedder, deps?: WebServerDeps);
44
+ constructor(catalog: IProjectCatalog, dependencies: IDependencyGraph, config: Config, logger: ILogger, embedder: IEmbedder, deps?: WebServerDeps);
72
45
  start(port: number, host: string): Promise<void>;
73
46
  stop(): Promise<void>;
74
- /** The bound address once started (e.g. `.port` after listen(0)); null otherwise. */
75
47
  address(): {
76
48
  port: number;
77
49
  } | null;
78
50
  private handle;
79
51
  private maskedConfig;
80
52
  private saveConfig;
81
- /**
82
- * After a successful config write, decide the Infinity backend action per
83
- * the first-match decision table (`local-backend-provisioning`). Computes
84
- * the required set from the SAVED config (a fresh `Config` re-read from the
85
- * file just written — never the server's startup config/embedder). Never
86
- * throws — an unexpected error becomes `{ action: 'failed', message }`; the
87
- * saved config and `GET /api/backend-status` are unaffected either way.
88
- */
89
53
  private evaluateBackendAfterSave;
90
- /** Kick off (or continue, via a follow-up) a background Infinity recreate. */
91
54
  private startBackgroundTask;
92
- /**
93
- * Choice lists for model fields. Both are non-strict comboboxes (free text
94
- * allowed): the embedding model suggests the known registry models plus any
95
- * locally-installed models; the reranker model suggests installed models.
96
- * Backends beyond the registry (e.g. arbitrary HuggingFace models on Infinity)
97
- * still work — their dimension is probed at index time.
98
- */
55
+ private defaults;
99
56
  private fieldOptions;
100
57
  private installedModels;
101
- /** Tabbed graph views (Workspace + one per nested Nx repo). */
102
58
  private graphViews;
103
- /** `/api/graph` — the Workspace view's raw `{ nodes, edges }` (back-compat). */
104
59
  private graphData;
105
- /**
106
- * The full interactive graph page — the same HTML as the standalone
107
- * `project-graph.html` (inner tabs, filters, legend, project toggles). The
108
- * dashboard's Graph tab embeds this via an iframe rather than re-implementing
109
- * vis-network.
110
- */
111
60
  private graphPage;
112
61
  private readBody;
113
62
  private json;
@@ -47,20 +47,11 @@ const infinity_provisioning_1 = require("./infinity-provisioning");
47
47
  function sameModelSet(a, b) {
48
48
  return a.join(';') === b.join(';');
49
49
  }
50
- /** Placeholder shown to the browser instead of a real secret. */
51
50
  exports.PASSWORD_MASK = '********';
52
- const MAX_BODY = 1_000_000; // 1 MB — config payloads are tiny
53
- /** A secret worth masking: a non-empty string that is not an `env:` reference. */
51
+ const MAX_BODY = 1_000_000;
54
52
  function isRawSecret(v) {
55
53
  return typeof v === 'string' && v !== '' && !v.startsWith('env:');
56
54
  }
57
- /**
58
- * Merge a config submitted from the browser with the stored one. Any secret
59
- * field (DB password, embedding/reranker API keys) still holding the mask means
60
- * the user did not change it — restore the stored value rather than overwrite it
61
- * with the placeholder. `env:` references are not masked and round-trip as-is.
62
- * Pure — no I/O. Exported for unit testing.
63
- */
64
55
  function mergeConfigForSave(incoming, existing) {
65
56
  const merged = JSON.parse(JSON.stringify(incoming ?? {}));
66
57
  const restore = (grp, field) => {
@@ -78,13 +69,6 @@ function mergeConfigForSave(incoming, existing) {
78
69
  restore('reranker', 'apiKey');
79
70
  return merged;
80
71
  }
81
- /**
82
- * Return a copy of the config with raw secrets (DB password, raw API keys)
83
- * replaced by the mask, so real secrets never reach the browser. `env:`
84
- * references are left verbatim — they are not secret and the dashboard shows
85
- * them as "set via <VAR>". The masked value round-trips through
86
- * `mergeConfigForSave`. Pure — no I/O. Exported for unit testing.
87
- */
88
72
  function maskConfig(cfg) {
89
73
  const clone = JSON.parse(JSON.stringify(cfg ?? {}));
90
74
  if (clone.db?.password)
@@ -95,12 +79,9 @@ function maskConfig(cfg) {
95
79
  clone.reranker.apiKey = exports.PASSWORD_MASK;
96
80
  return clone;
97
81
  }
98
- /**
99
- * Local HTTP dashboard. Serves a schema-driven config editor, a project
100
- * overview, and the dependency graph. Bind to 127.0.0.1 only — no auth.
101
- */
102
82
  class WebServer {
103
- searcher;
83
+ catalog;
84
+ dependencies;
104
85
  config;
105
86
  logger;
106
87
  embedder;
@@ -108,13 +89,12 @@ class WebServer {
108
89
  composePath;
109
90
  provisioningDeps;
110
91
  readSavedConfig;
111
- // Background Infinity-recreate task state (D6). In-memory, per-process — see
112
- // `GET /api/backend-status`. `pending` holds at most one queued follow-up.
113
92
  backendStatus = { state: 'idle', message: null, startedAt: null, finishedAt: null };
114
93
  taskInFlight = false;
115
94
  pending = null;
116
- constructor(searcher, config, logger, embedder, deps = {}) {
117
- this.searcher = searcher;
95
+ constructor(catalog, dependencies, config, logger, embedder, deps = {}) {
96
+ this.catalog = catalog;
97
+ this.dependencies = dependencies;
118
98
  this.config = config;
119
99
  this.logger = logger;
120
100
  this.embedder = embedder;
@@ -125,7 +105,7 @@ class WebServer {
125
105
  async start(port, host) {
126
106
  this.server = http.createServer((req, res) => {
127
107
  this.handle(req, res).catch(err => {
128
- this.logger.error('WebServer: request failed', { reason: err instanceof Error ? err.message : String(err) });
108
+ this.logger.error('WebServer: request failed', { err });
129
109
  if (!res.headersSent) {
130
110
  res.writeHead(500);
131
111
  res.end('Internal error');
@@ -144,7 +124,6 @@ class WebServer {
144
124
  await new Promise(resolve => this.server.close(() => resolve()));
145
125
  this.server = undefined;
146
126
  }
147
- /** The bound address once started (e.g. `.port` after listen(0)); null otherwise. */
148
127
  address() {
149
128
  const a = this.server?.address();
150
129
  return a && typeof a === 'object' ? { port: a.port } : null;
@@ -158,7 +137,7 @@ class WebServer {
158
137
  if (m === 'GET' && p === '/api/schema')
159
138
  return this.json(res, 200, (0, config_store_1.buildJsonSchema)());
160
139
  if (m === 'GET' && p === '/api/defaults')
161
- return this.json(res, 200, config_store_1.CONFIG_DEFAULTS);
140
+ return this.json(res, 200, this.defaults());
162
141
  if (m === 'GET' && p === '/api/field-options')
163
142
  return this.json(res, 200, await this.fieldOptions());
164
143
  if (m === 'GET' && p === '/api/config')
@@ -168,7 +147,7 @@ class WebServer {
168
147
  if (m === 'GET' && p === '/api/backend-status')
169
148
  return this.json(res, 200, this.backendStatus);
170
149
  if (m === 'GET' && p === '/api/projects')
171
- return this.json(res, 200, await this.searcher.listProjects());
150
+ return this.json(res, 200, await this.catalog.listProjects());
172
151
  if (m === 'GET' && p === '/api/graph')
173
152
  return this.json(res, 200, await this.graphData());
174
153
  if (m === 'GET' && p === '/graph')
@@ -184,7 +163,6 @@ class WebServer {
184
163
  body = await this.readBody(req);
185
164
  }
186
165
  catch (e) {
187
- // Distinguish the size limit from other stream errors.
188
166
  return this.json(res, 413, { error: e instanceof Error ? e.message : 'Request body too large' });
189
167
  }
190
168
  let incoming;
@@ -207,14 +185,6 @@ class WebServer {
207
185
  const backend = await this.evaluateBackendAfterSave(validated);
208
186
  this.json(res, 200, { ok: true, backend });
209
187
  }
210
- /**
211
- * After a successful config write, decide the Infinity backend action per
212
- * the first-match decision table (`local-backend-provisioning`). Computes
213
- * the required set from the SAVED config (a fresh `Config` re-read from the
214
- * file just written — never the server's startup config/embedder). Never
215
- * throws — an unexpected error becomes `{ action: 'failed', message }`; the
216
- * saved config and `GET /api/backend-status` are unaffected either way.
217
- */
218
188
  async evaluateBackendAfterSave(saved) {
219
189
  const provider = saved.embedding?.provider ?? config_store_1.CONFIG_DEFAULTS['embedding.provider'];
220
190
  if (provider !== 'infinity') {
@@ -232,7 +202,6 @@ class WebServer {
232
202
  this.pending = { modelSet, baseURL, composePath };
233
203
  return { action: 'already-running', message: 'A backend recreate is already in progress; this configuration will be applied next.' };
234
204
  }
235
- // No longer targets the managed container the in-flight task owns.
236
205
  this.pending = null;
237
206
  }
238
207
  const evaluation = await (0, infinity_provisioning_1.evaluateBackend)(baseURL, composePath, modelSet, this.provisioningDeps);
@@ -252,7 +221,6 @@ class WebServer {
252
221
  return { action: 'failed', message: err instanceof Error ? err.message : String(err) };
253
222
  }
254
223
  }
255
- /** Kick off (or continue, via a follow-up) a background Infinity recreate. */
256
224
  startBackgroundTask(baseURL, composePath, modelSet) {
257
225
  this.taskInFlight = true;
258
226
  this.backendStatus = { state: 'recreating', message: null, startedAt: new Date().toISOString(), finishedAt: null };
@@ -276,19 +244,23 @@ class WebServer {
276
244
  }
277
245
  });
278
246
  }
279
- /**
280
- * Choice lists for model fields. Both are non-strict comboboxes (free text
281
- * allowed): the embedding model suggests the known registry models plus any
282
- * locally-installed models; the reranker model suggests installed models.
283
- * Backends beyond the registry (e.g. arbitrary HuggingFace models on Infinity)
284
- * still work — their dimension is probed at index time.
285
- */
247
+ defaults() {
248
+ const saved = (0, config_store_1.readConfigJson)() ?? {};
249
+ const ctx = (0, config_1.rerankContext)(saved);
250
+ return {
251
+ ...config_store_1.CONFIG_DEFAULTS,
252
+ 'reranker.enabled': ctx.wanted && !ctx.missingKey,
253
+ 'reranker.model': ctx.model,
254
+ 'search.similarityThreshold': (0, constants_1.resolveThreshold)({ model: saved.embedding?.model ?? config_store_1.CONFIG_DEFAULTS['embedding.model'] }).value,
255
+ };
256
+ }
286
257
  async fieldOptions() {
287
258
  const installed = await this.installedModels();
288
259
  const registryModels = Object.keys(constants_1.MODEL_REGISTRY);
260
+ const rerankModels = (0, config_store_1.readConfigJson)()?.reranker?.provider === 'voyage' ? [...constants_1.VOYAGE_RERANK_MODELS] : installed;
289
261
  return {
290
262
  'embedding.model': { values: [...new Set([...registryModels, ...installed])], strict: false },
291
- 'reranker.model': { values: installed, strict: false },
263
+ 'reranker.model': { values: rerankModels, strict: false },
292
264
  };
293
265
  }
294
266
  async installedModels() {
@@ -296,32 +268,22 @@ class WebServer {
296
268
  return (await this.embedder.listModels?.()) ?? [];
297
269
  }
298
270
  catch (err) {
299
- this.logger.warn('WebServer: could not list models', { reason: err instanceof Error ? err.message : String(err) });
271
+ this.logger.warn('WebServer: could not list models', { err });
300
272
  return [];
301
273
  }
302
274
  }
303
- /** Tabbed graph views (Workspace + one per nested Nx repo). */
304
275
  async graphViews() {
305
- const projects = (await this.searcher.listProjects()).map(p => ({
276
+ const projects = (await this.catalog.listProjects()).map(p => ({
306
277
  name: p.serviceName,
307
- // Real project root (resolved via discovery — handles nested-monorepo
308
- // names). Fall back to the flat assumption if listProjects omits it.
309
278
  path: p.path ?? path.join(this.config.workspaceRoot, p.serviceName),
310
279
  }));
311
- const projectEdges = await this.searcher.getProjectEdges();
280
+ const projectEdges = await this.dependencies.getProjectEdges();
312
281
  return (0, graph_1.buildGraphViews)(projects, projectEdges, this.config.workspaceRoot);
313
282
  }
314
- /** `/api/graph` — the Workspace view's raw `{ nodes, edges }` (back-compat). */
315
283
  async graphData() {
316
284
  const views = await this.graphViews();
317
285
  return { nodes: views[0].nodes, edges: views[0].edges };
318
286
  }
319
- /**
320
- * The full interactive graph page — the same HTML as the standalone
321
- * `project-graph.html` (inner tabs, filters, legend, project toggles). The
322
- * dashboard's Graph tab embeds this via an iframe rather than re-implementing
323
- * vis-network.
324
- */
325
287
  async graphPage() {
326
288
  return (0, graph_1.buildHtml)(await this.graphViews());
327
289
  }
@@ -331,7 +293,7 @@ class WebServer {
331
293
  let tooLarge = false;
332
294
  req.on('data', chunk => {
333
295
  if (tooLarge)
334
- return; // stop growing `data`; keep the socket alive so the 413 flushes
296
+ return;
335
297
  data += chunk;
336
298
  if (data.length > MAX_BODY) {
337
299
  tooLarge = true;
@@ -4,16 +4,9 @@ export declare class HttpError extends Error {
4
4
  constructor(status: number, message: string);
5
5
  }
6
6
  export interface RetryOpts {
7
- /** Total attempts including the first (default 4). */
8
7
  attempts?: number;
9
- /** Base backoff in ms; grows exponentially (default 500). Set 0 in tests. */
10
8
  baseDelayMs?: number;
11
9
  logger?: ILogger;
12
10
  label?: string;
13
11
  }
14
- /**
15
- * Run `fn` with bounded exponential backoff on HTTP 429/5xx and network errors.
16
- * Re-throws the last error once attempts are exhausted or the error is not
17
- * transient.
18
- */
19
12
  export declare function withRetry<T>(fn: () => Promise<T>, opts?: RetryOpts): Promise<T>;