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
@@ -1,38 +1,32 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ListFilesTool = void 0;
4
+ const zod_1 = require("zod");
4
5
  const format_helpers_1 = require("./format-helpers");
5
- class ListFilesTool {
6
- searcher;
7
- logger;
8
- constructor(searcher, logger) {
9
- this.searcher = searcher;
10
- this.logger = logger;
11
- }
12
- definition() {
13
- return {
6
+ const McpTool_1 = require("./McpTool");
7
+ const tool_args_1 = require("./tool-args");
8
+ const ARGS = zod_1.z.object({
9
+ path: (0, tool_args_1.pathArg)((0, format_helpers_1.pathArgDescription)('directory'), 'directory'),
10
+ depth: (0, tool_args_1.intInRange)('Tree depth: 1 = immediate children only, up to 5. Default: 2.', { min: 1, max: 5, fallback: 2 }),
11
+ pattern: (0, tool_args_1.optionalText)('Optional filename filter (substring or extension like ".ts"). Only matching files are shown.'),
12
+ });
13
+ class ListFilesTool extends McpTool_1.McpTool {
14
+ paths;
15
+ files;
16
+ constructor(paths, files, logger) {
17
+ super({
14
18
  name: 'list_files',
15
19
  description: 'List files and directories under a workspace directory as an indented tree. Use to understand project structure before reading files; list_projects prints each project\'s directory.',
16
- inputSchema: {
17
- type: 'object',
18
- properties: {
19
- path: { type: 'string', description: (0, format_helpers_1.pathArgDescription)('directory') },
20
- depth: { type: 'number', description: 'Tree depth: 1 = immediate children only, up to 5. Default: 2.' },
21
- pattern: { type: 'string', description: 'Optional filename filter (substring or extension like ".ts"). Only matching files are shown.' },
22
- },
23
- required: ['path'],
24
- },
25
- };
20
+ args: ARGS,
21
+ }, logger);
22
+ this.paths = paths;
23
+ this.files = files;
26
24
  }
27
- async handle(args) {
28
- const input = args.path == null ? '' : String(args.path);
29
- const rawDepth = Number(args.depth);
30
- const depth = isNaN(rawDepth) || rawDepth < 1 ? 2 : Math.min(5, rawDepth);
31
- const pattern = args.pattern ? String(args.pattern) : null;
32
- const resolved = await this.searcher.resolveToolPath(input);
25
+ async run({ path: input, depth, pattern }) {
26
+ const resolved = await this.paths.resolveToolPath(input);
33
27
  if (!resolved.ok)
34
28
  return (0, format_helpers_1.pathErrorResponse)(this.logger, 'list_files', 'path', input, input, resolved, 'directory');
35
- const result = await this.searcher.listFiles(resolved.relPath, depth, pattern);
29
+ const result = await this.files.listFiles(resolved.relPath, depth, pattern ?? null);
36
30
  if (!result.ok)
37
31
  return (0, format_helpers_1.pathErrorResponse)(this.logger, 'list_files', 'path', input, resolved.relPath, result, 'directory');
38
32
  return (0, format_helpers_1.textResponse)(`**Directory:** ${resolved.relPath}\n\`\`\`\n${result.tree}\n\`\`\``);
@@ -1,8 +1,12 @@
1
- import type { IMcpToolHandler, ToolDefinition, ToolResponse } from '../interfaces/IMcpToolHandler';
2
- import type { ISearcher } from '../interfaces/ISearcher';
3
- export declare class ListProjectsTool implements IMcpToolHandler {
4
- private searcher;
5
- constructor(searcher: ISearcher);
6
- definition(): ToolDefinition;
7
- handle(_args: Record<string, unknown>): Promise<ToolResponse>;
1
+ import { z } from 'zod';
2
+ import type { ToolResponse } from '../interfaces/IMcpToolHandler';
3
+ import type { IProjectCatalog } from '../interfaces/IProjectCatalog';
4
+ import type { ILogger } from '../interfaces/ILogger';
5
+ import { McpTool } from './McpTool';
6
+ declare const ARGS: z.ZodObject<{}, z.core.$strip>;
7
+ export declare class ListProjectsTool extends McpTool<typeof ARGS> {
8
+ private catalog;
9
+ constructor(catalog: IProjectCatalog, logger?: ILogger);
10
+ protected run(): Promise<ToolResponse>;
8
11
  }
12
+ export {};
@@ -1,21 +1,23 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ListProjectsTool = void 0;
4
+ const zod_1 = require("zod");
5
+ const LoggerService_1 = require("../services/LoggerService");
4
6
  const format_helpers_1 = require("./format-helpers");
5
- class ListProjectsTool {
6
- searcher;
7
- constructor(searcher) {
8
- this.searcher = searcher;
9
- }
10
- definition() {
11
- return {
7
+ const McpTool_1 = require("./McpTool");
8
+ const ARGS = zod_1.z.object({});
9
+ class ListProjectsTool extends McpTool_1.McpTool {
10
+ catalog;
11
+ constructor(catalog, logger = LoggerService_1.LoggerService.silent()) {
12
+ super({
12
13
  name: 'list_projects',
13
14
  description: 'List all indexed projects with their chunk counts, workspace-relative directory (`path:`) and metadata (description, stack, notes, relations from .ragmeta.json).',
14
- inputSchema: { type: 'object', properties: {} },
15
- };
15
+ args: ARGS,
16
+ }, logger);
17
+ this.catalog = catalog;
16
18
  }
17
- async handle(_args) {
18
- const rows = await this.searcher.listProjects();
19
+ async run() {
20
+ const rows = await this.catalog.listProjects();
19
21
  if (rows.length === 0) {
20
22
  return (0, format_helpers_1.textResponse)('No indexed projects found.');
21
23
  }
@@ -0,0 +1,17 @@
1
+ import type { z } from 'zod';
2
+ import type { IMcpToolHandler, ToolDefinition, ToolResponse } from '../interfaces/IMcpToolHandler';
3
+ import type { ILogger } from '../interfaces/ILogger';
4
+ export interface McpToolSpec<S extends z.ZodObject> {
5
+ name: string;
6
+ description: string;
7
+ args: S;
8
+ }
9
+ export declare abstract class McpTool<S extends z.ZodObject> implements IMcpToolHandler {
10
+ private readonly spec;
11
+ protected readonly logger: ILogger;
12
+ private cachedDefinition?;
13
+ constructor(spec: McpToolSpec<S>, logger: ILogger);
14
+ definition(): ToolDefinition;
15
+ handle(raw: Record<string, unknown>): Promise<ToolResponse>;
16
+ protected abstract run(args: z.output<S>): Promise<ToolResponse>;
17
+ }
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.McpTool = void 0;
4
+ const format_helpers_1 = require("./format-helpers");
5
+ const tool_args_1 = require("./tool-args");
6
+ class McpTool {
7
+ spec;
8
+ logger;
9
+ cachedDefinition;
10
+ constructor(spec, logger) {
11
+ this.spec = spec;
12
+ this.logger = logger;
13
+ }
14
+ definition() {
15
+ const { name, description, args } = this.spec;
16
+ return this.cachedDefinition ??= { name, description, inputSchema: (0, tool_args_1.toInputSchema)(args) };
17
+ }
18
+ async handle(raw) {
19
+ const parsed = (0, tool_args_1.parseToolArgs)(this.spec.args, raw);
20
+ if (parsed.ok)
21
+ return this.run(parsed.args);
22
+ const { failure } = parsed;
23
+ return failure.kind === 'missing-path'
24
+ ? (0, format_helpers_1.pathErrorResponse)(this.logger, this.spec.name, failure.arg, '', '', { ok: false, reason: 'invalid', missing: true }, failure.pathKind)
25
+ : (0, format_helpers_1.errorResponse)(failure.text);
26
+ }
27
+ }
28
+ exports.McpTool = McpTool;
@@ -1,10 +1,18 @@
1
- import type { IMcpToolHandler, ToolDefinition, ToolResponse } from '../interfaces/IMcpToolHandler';
2
- import type { ISearcher } from '../interfaces/ISearcher';
1
+ import { z } from 'zod';
2
+ import type { ToolResponse } from '../interfaces/IMcpToolHandler';
3
+ import type { IToolPaths } from '../interfaces/IToolPaths';
4
+ import type { IWorkspaceFiles } from '../interfaces/IWorkspaceFiles';
3
5
  import type { ILogger } from '../interfaces/ILogger';
4
- export declare class ReadFileRangeTool implements IMcpToolHandler {
5
- private searcher;
6
- private logger;
7
- constructor(searcher: ISearcher, logger: ILogger);
8
- definition(): ToolDefinition;
9
- handle(args: Record<string, unknown>): Promise<ToolResponse>;
6
+ import { McpTool } from './McpTool';
7
+ declare const ARGS: z.ZodObject<{
8
+ file_path: z.ZodType<string, unknown, z.core.$ZodTypeInternals<string, unknown>>;
9
+ start_line: z.ZodType<number, unknown, z.core.$ZodTypeInternals<number, unknown>>;
10
+ end_line: z.ZodType<number | undefined, unknown, z.core.$ZodTypeInternals<number | undefined, unknown>>;
11
+ }, z.core.$strip>;
12
+ export declare class ReadFileRangeTool extends McpTool<typeof ARGS> {
13
+ private paths;
14
+ private files;
15
+ constructor(paths: IToolPaths, files: IWorkspaceFiles, logger: ILogger);
16
+ protected run(args: z.output<typeof ARGS>): Promise<ToolResponse>;
10
17
  }
18
+ export {};
@@ -1,37 +1,35 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ReadFileRangeTool = void 0;
4
+ const zod_1 = require("zod");
4
5
  const format_helpers_1 = require("./format-helpers");
5
- class ReadFileRangeTool {
6
- searcher;
7
- logger;
8
- constructor(searcher, logger) {
9
- this.searcher = searcher;
10
- this.logger = logger;
11
- }
12
- definition() {
13
- return {
6
+ const McpTool_1 = require("./McpTool");
7
+ const tool_args_1 = require("./tool-args");
8
+ const ARGS = zod_1.z.object({
9
+ file_path: (0, tool_args_1.pathArg)((0, format_helpers_1.pathArgDescription)()),
10
+ start_line: (0, tool_args_1.intInRange)('First line to read (1-based). Use the **Line** number from search_codebase results. Default: 1.', { min: 1, fallback: 1 }),
11
+ end_line: (0, tool_args_1.intInRange)('Last line to read (1-based, inclusive). Default: start_line + 99.'),
12
+ });
13
+ class ReadFileRangeTool extends McpTool_1.McpTool {
14
+ paths;
15
+ files;
16
+ constructor(paths, files, logger) {
17
+ super({
14
18
  name: 'read_file_range',
15
19
  description: 'Read a specific line range from a file under the workspace, indexed or not. Use this when a search result looks incomplete — read the surrounding lines to get full context.',
16
- inputSchema: {
17
- type: 'object',
18
- properties: {
19
- file_path: { type: 'string', description: (0, format_helpers_1.pathArgDescription)() },
20
- start_line: { type: 'number', description: 'First line to read (1-based). Use the **Line** number from search_codebase results. Default: 1.' },
21
- end_line: { type: 'number', description: 'Last line to read (1-based, inclusive). Default: start_line + 99.' },
22
- },
23
- required: ['file_path'],
24
- },
25
- };
20
+ args: ARGS,
21
+ }, logger);
22
+ this.paths = paths;
23
+ this.files = files;
26
24
  }
27
- async handle(args) {
28
- const input = args.file_path == null ? '' : String(args.file_path);
29
- const startLine = Math.max(1, Number(args.start_line) || 1);
30
- const endLine = Number(args.end_line) || startLine + 99;
31
- const resolved = await this.searcher.resolveToolPath(input);
25
+ async run(args) {
26
+ const input = args.file_path;
27
+ const startLine = args.start_line;
28
+ const endLine = args.end_line ?? startLine + 99;
29
+ const resolved = await this.paths.resolveToolPath(input);
32
30
  if (!resolved.ok)
33
31
  return (0, format_helpers_1.pathErrorResponse)(this.logger, 'read_file_range', 'file_path', input, input, resolved);
34
- const range = await this.searcher.readFileRange(resolved.relPath, startLine, endLine);
32
+ const range = await this.files.readFileRange(resolved.relPath, startLine, endLine);
35
33
  if (!range.ok)
36
34
  return (0, format_helpers_1.pathErrorResponse)(this.logger, 'read_file_range', 'file_path', input, resolved.relPath, range);
37
35
  const numbered = range.lines.map((line, i) => `${startLine + i}: ${line}`).join('\n');
@@ -1,10 +1,17 @@
1
- import type { IMcpToolHandler, ToolDefinition, ToolResponse } from '../interfaces/IMcpToolHandler';
2
- import type { ISearcher } from '../interfaces/ISearcher';
1
+ import { z } from 'zod';
2
+ import type { ToolResponse } from '../interfaces/IMcpToolHandler';
3
+ import type { IToolPaths } from '../interfaces/IToolPaths';
4
+ import type { IWorkspaceFiles } from '../interfaces/IWorkspaceFiles';
3
5
  import type { ILogger } from '../interfaces/ILogger';
4
- export declare class ReadFileTool implements IMcpToolHandler {
5
- private searcher;
6
- private logger;
7
- constructor(searcher: ISearcher, logger: ILogger);
8
- definition(): ToolDefinition;
9
- handle(args: Record<string, unknown>): Promise<ToolResponse>;
6
+ import { McpTool } from './McpTool';
7
+ declare const ARGS: z.ZodObject<{
8
+ file_path: z.ZodType<string, unknown, z.core.$ZodTypeInternals<string, unknown>>;
9
+ max_lines: z.ZodType<number, unknown, z.core.$ZodTypeInternals<number, unknown>>;
10
+ }, z.core.$strip>;
11
+ export declare class ReadFileTool extends McpTool<typeof ARGS> {
12
+ private paths;
13
+ private files;
14
+ constructor(paths: IToolPaths, files: IWorkspaceFiles, logger: ILogger);
15
+ protected run({ file_path: input, max_lines: maxLines }: z.output<typeof ARGS>): Promise<ToolResponse>;
10
16
  }
17
+ export {};
@@ -1,36 +1,31 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ReadFileTool = void 0;
4
+ const zod_1 = require("zod");
4
5
  const format_helpers_1 = require("./format-helpers");
5
- class ReadFileTool {
6
- searcher;
7
- logger;
8
- constructor(searcher, logger) {
9
- this.searcher = searcher;
10
- this.logger = logger;
11
- }
12
- definition() {
13
- return {
6
+ const McpTool_1 = require("./McpTool");
7
+ const tool_args_1 = require("./tool-args");
8
+ const ARGS = zod_1.z.object({
9
+ file_path: (0, tool_args_1.pathArg)((0, format_helpers_1.pathArgDescription)()),
10
+ max_lines: (0, tool_args_1.intInRange)('Maximum lines to return (default 300, max 1000)', { min: 1, max: 1000, fallback: 300 }),
11
+ });
12
+ class ReadFileTool extends McpTool_1.McpTool {
13
+ paths;
14
+ files;
15
+ constructor(paths, files, logger) {
16
+ super({
14
17
  name: 'read_file',
15
18
  description: 'Read a complete file under the workspace, indexed or not. Returns contents with line numbers. Truncates at max_lines with a hint to continue with read_file_range.',
16
- inputSchema: {
17
- type: 'object',
18
- properties: {
19
- file_path: { type: 'string', description: (0, format_helpers_1.pathArgDescription)() },
20
- max_lines: { type: 'number', description: 'Maximum lines to return (default 300, max 1000)' },
21
- },
22
- required: ['file_path'],
23
- },
24
- };
19
+ args: ARGS,
20
+ }, logger);
21
+ this.paths = paths;
22
+ this.files = files;
25
23
  }
26
- async handle(args) {
27
- const input = args.file_path == null ? '' : String(args.file_path);
28
- const rawMax = Number(args.max_lines);
29
- const maxLines = isNaN(rawMax) || rawMax < 1 ? 300 : Math.min(1000, rawMax);
30
- const resolved = await this.searcher.resolveToolPath(input);
24
+ async run({ file_path: input, max_lines: maxLines }) {
25
+ const resolved = await this.paths.resolveToolPath(input);
31
26
  if (!resolved.ok)
32
27
  return (0, format_helpers_1.pathErrorResponse)(this.logger, 'read_file', 'file_path', input, input, resolved);
33
- const result = await this.searcher.readFile(resolved.relPath, maxLines);
28
+ const result = await this.files.readFile(resolved.relPath, maxLines);
34
29
  if (!result.ok)
35
30
  return (0, format_helpers_1.pathErrorResponse)(this.logger, 'read_file', 'file_path', input, resolved.relPath, result);
36
31
  const numbered = result.lines.map((line, i) => `${i + 1}: ${line}`).join('\n');
@@ -1,13 +1,25 @@
1
- import type { IMcpToolHandler, ToolDefinition, ToolResponse } from '../interfaces/IMcpToolHandler';
2
- import type { ISearcher } from '../interfaces/ISearcher';
1
+ import { z } from 'zod';
2
+ import type { ToolResponse } from '../interfaces/IMcpToolHandler';
3
+ import type { IChunkSearch } from '../interfaces/IChunkSearch';
4
+ import type { IDependencyGraph } from '../interfaces/IDependencyGraph';
3
5
  import type { ILogger } from '../interfaces/ILogger';
4
- export declare class SearchCodebaseTool implements IMcpToolHandler {
5
- private searcher;
6
- private defaultLimit;
7
- private maxLimit;
6
+ import { McpTool } from './McpTool';
7
+ declare function searchArgs(defaultLimit: number, maxLimit: number, defaultThreshold: number): z.ZodObject<{
8
+ query: z.ZodType<string, unknown, z.core.$ZodTypeInternals<string, unknown>>;
9
+ limit: z.ZodType<number, unknown, z.core.$ZodTypeInternals<number, unknown>>;
10
+ project: z.ZodType<string | undefined, unknown, z.core.$ZodTypeInternals<string | undefined, unknown>>;
11
+ include_neighbors: z.ZodType<boolean | undefined, unknown, z.core.$ZodTypeInternals<boolean | undefined, unknown>>;
12
+ include_graph_context: z.ZodType<boolean | undefined, unknown, z.core.$ZodTypeInternals<boolean | undefined, unknown>>;
13
+ threshold: z.ZodType<number | undefined, unknown, z.core.$ZodTypeInternals<number | undefined, unknown>>;
14
+ per_file: z.ZodType<number, unknown, z.core.$ZodTypeInternals<number, unknown>>;
15
+ rerank: z.ZodType<boolean | undefined, unknown, z.core.$ZodTypeInternals<boolean | undefined, unknown>>;
16
+ }, z.core.$strip>;
17
+ type SearchArgs = ReturnType<typeof searchArgs>;
18
+ export declare class SearchCodebaseTool extends McpTool<SearchArgs> {
19
+ private chunks;
20
+ private dependencies;
8
21
  private defaultThreshold;
9
- private logger;
10
- constructor(searcher: ISearcher, defaultLimit: number, maxLimit: number, defaultThreshold: number, logger: ILogger);
11
- definition(): ToolDefinition;
12
- handle(args: Record<string, unknown>): Promise<ToolResponse>;
22
+ constructor(chunks: IChunkSearch, dependencies: IDependencyGraph, defaultLimit: number, maxLimit: number, defaultThreshold: number, logger: ILogger);
23
+ protected run(args: z.output<SearchArgs>): Promise<ToolResponse>;
13
24
  }
25
+ export {};
@@ -1,73 +1,94 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.SearchCodebaseTool = void 0;
4
+ const zod_1 = require("zod");
4
5
  const format_helpers_1 = require("./format-helpers");
5
- class SearchCodebaseTool {
6
- searcher;
7
- defaultLimit;
8
- maxLimit;
9
- defaultThreshold;
10
- logger;
11
- constructor(searcher, defaultLimit, maxLimit, defaultThreshold, logger) {
12
- this.searcher = searcher;
13
- this.defaultLimit = defaultLimit;
14
- this.maxLimit = maxLimit;
15
- this.defaultThreshold = defaultThreshold;
16
- this.logger = logger;
6
+ const McpTool_1 = require("./McpTool");
7
+ const tool_args_1 = require("./tool-args");
8
+ const result_shaping_1 = require("../search/result-shaping");
9
+ const constants_1 = require("../constants");
10
+ function searchArgs(defaultLimit, maxLimit, defaultThreshold) {
11
+ const shown = (0, constants_1.formatThreshold)(defaultThreshold);
12
+ const stricter = defaultThreshold > 0 ? ' Use a stricter value a little below the default for precise technical queries.' : '';
13
+ const raise = defaultThreshold < 1 ? ' Raise it (up to 1.0) when a search finds nothing.' : '';
14
+ return zod_1.z.object({
15
+ query: (0, tool_args_1.requiredText)(),
16
+ limit: (0, tool_args_1.intInRange)(`Max results (default ${defaultLimit}, max ${maxLimit})`, { min: 1, max: maxLimit, fallback: defaultLimit }),
17
+ project: (0, tool_args_1.optionalText)('Filter by project name (optional). Use list_projects to see available names.'),
18
+ include_neighbors: (0, tool_args_1.flag)('Also include the chunk before and after each result from the same file (Small-to-Big retrieval). Useful when results look truncated.'),
19
+ include_graph_context: (0, tool_args_1.flag)('Append direct imports and dependents list to each result. Shows "Imports: X · Y" and "Used by: Z" without extra tool calls.'),
20
+ threshold: (0, tool_args_1.numberInRange)(`Max cosine distance (0–1). Lower = stricter. Default: ${shown}.${stricter}${raise}`, { min: 0, max: 1 }),
21
+ per_file: (0, tool_args_1.intInRange)(`Max results from one file (integer ≥ 1, default ${result_shaping_1.DEFAULT_PER_FILE}). Skipped results are backfilled from the next candidates. Raise it when one file is expected to hold several answers (e.g. several methods of one class).`, { min: 1, fallback: result_shaping_1.DEFAULT_PER_FILE }),
22
+ rerank: (0, tool_args_1.flag)('Override whether this call reranks, regardless of config. false skips reranking (use for "what does X do" / "where is X" lookups described without an exact name — reranking measurably hurts these; if you know the exact symbol name, use find_symbol instead). true forces reranking on if a reranker is configured (no-op otherwise). Omit to use config.reranker.enabled (fine for conceptual/architectural queries, where reranking is roughly neutral).'),
23
+ });
24
+ }
25
+ const DISTANCE_NOTE = '> Lower distance = closer match. Results may be reranked, so their order need not follow the distance.';
26
+ function renderNoResults(cause, project, threshold) {
27
+ const first = 'No relevant results found.';
28
+ switch (cause) {
29
+ case 'empty-scope':
30
+ return `${first}\n${project
31
+ ? `Project \`${project}\` has no indexed chunks. Check the name with \`list_projects\`.`
32
+ : 'The index holds no chunks. Run `rag-index`.'}`;
33
+ case 'no-candidates': {
34
+ const steps = ['rephrase the query', 'use `find_symbol` for a known name'];
35
+ if (project)
36
+ steps.push('drop `project`');
37
+ if (threshold < 1)
38
+ steps.push('pass a higher `threshold`');
39
+ const last = steps.pop();
40
+ return `${first}\nNo chunk ${project ? `of project \`${project}\` ` : ''}came within the distance threshold, which does not show the code is absent. Next: ${steps.join(', ')}, or ${last}.`;
41
+ }
42
+ case 'lookup-failed':
43
+ return `${first}\nThe cause could not be determined, so this does not show the code is absent.`;
17
44
  }
18
- definition() {
19
- return {
45
+ }
46
+ class SearchCodebaseTool extends McpTool_1.McpTool {
47
+ chunks;
48
+ dependencies;
49
+ defaultThreshold;
50
+ constructor(chunks, dependencies, defaultLimit, maxLimit, defaultThreshold, logger) {
51
+ super({
20
52
  name: 'search_codebase',
21
- description: 'Search local project codebase by semantic similarity. Each result shows File, Project, an optional Symbol breadcrumb (owning declaration, e.g. `IndexerService.ingestFile`), Line, the code, and Relevance.',
22
- inputSchema: {
23
- type: 'object',
24
- properties: {
25
- query: { type: 'string' },
26
- limit: { type: 'number', description: `Max results (default ${this.defaultLimit}, max ${this.maxLimit})` },
27
- project: { type: 'string', description: 'Filter by project name (optional). Use list_projects to see available names.' },
28
- include_neighbors: { type: 'boolean', description: 'Also include the chunk before and after each result from the same file (Small-to-Big retrieval). Useful when results look truncated.' },
29
- include_graph_context: { type: 'boolean', description: 'Append direct imports and dependents list to each result. Shows "Imports: X · Y" and "Used by: Z" without extra tool calls.' },
30
- threshold: { type: 'number', description: `Max cosine distance (0–1). Lower = stricter. Default: ${this.defaultThreshold}. Use 0.40–0.45 for precise technical queries, 0.55–0.60 for broad exploration.` },
31
- rerank: { type: 'boolean', description: 'Override whether this call reranks, regardless of config. false skips reranking (use for "what does X do" / "where is X" lookups described without an exact name — reranking measurably hurts these; if you know the exact symbol name, use find_symbol instead). true forces reranking on if a reranker is configured (no-op otherwise). Omit to use config.reranker.enabled (good default for conceptual/architectural queries).' },
32
- },
33
- required: ['query'],
34
- },
35
- };
53
+ description: 'Search local project codebase by semantic similarity. Each result shows File, Project, an optional Symbol breadcrumb (owning declaration, e.g. `IndexerService.ingestFile`), Line, the code, and Distance (cosine distance: lower is closer).',
54
+ args: searchArgs(defaultLimit, maxLimit, defaultThreshold),
55
+ }, logger);
56
+ this.chunks = chunks;
57
+ this.dependencies = dependencies;
58
+ this.defaultThreshold = defaultThreshold;
36
59
  }
37
- async handle(args) {
60
+ async run(args) {
38
61
  const t0 = Date.now();
39
- const raw = String(args.query);
40
- const limit = Math.min(Math.max(1, Number(args.limit) || this.defaultLimit), this.maxLimit);
41
- const project = args.project ? String(args.project) : null;
42
- const includeNeighbors = Boolean(args.include_neighbors);
43
- const includeGraphContext = Boolean(args.include_graph_context);
44
- const rawThreshold = args.threshold;
45
- const parsedThreshold = Number(rawThreshold);
46
- const threshold = rawThreshold != null && !isNaN(parsedThreshold)
47
- ? Math.min(1, Math.max(0, parsedThreshold))
48
- : undefined;
49
- const rerank = typeof args.rerank === 'boolean' ? args.rerank : undefined;
50
- const { query, translated } = await this.searcher.prepareQuery(raw);
51
- const results = await this.searcher.searchChunks(query, limit, project, threshold, rerank);
62
+ const raw = args.query;
63
+ const limit = args.limit;
64
+ const project = args.project ?? null;
65
+ const includeNeighbors = args.include_neighbors ?? false;
66
+ const includeGraphContext = args.include_graph_context ?? false;
67
+ const threshold = args.threshold;
68
+ const rerank = args.rerank;
69
+ const perFile = args.per_file;
70
+ const { query, translated } = await this.chunks.prepareQuery(raw);
71
+ const results = await this.chunks.searchChunks(query, limit, project, threshold, rerank, perFile);
52
72
  this.logger.debug('SearchCodebaseTool: handle', {
53
73
  query: raw.slice(0, 120), project, threshold: threshold ?? this.defaultThreshold,
54
- limit, translated, count: results.length, ms: Date.now() - t0,
74
+ limit, perFile, translated, count: results.length, ms: Date.now() - t0,
55
75
  });
56
76
  if (results.length === 0) {
57
- return (0, format_helpers_1.textResponse)('No relevant results found.');
77
+ const cause = await this.chunks.explainNoResults(project);
78
+ return (0, format_helpers_1.textResponse)(renderNoResults(cause, project, threshold ?? this.defaultThreshold));
58
79
  }
59
- const header = translated ? `> Query translated: "${raw}" → "${query}"\n\n` : '';
80
+ const header = `${translated ? `> Query translated: "${raw}" → "${query}"\n` : ''}${DISTANCE_NOTE}\n\n`;
60
81
  let graphCtx = null;
61
82
  if (includeGraphContext) {
62
- graphCtx = await this.searcher.fetchGraphContext(results);
83
+ graphCtx = await this.dependencies.fetchGraphContext(results);
63
84
  }
64
85
  if (includeNeighbors) {
65
- const withNeighbors = await this.searcher.fetchNeighbors(results);
86
+ const withNeighbors = await this.chunks.fetchNeighbors(results);
66
87
  const blocks = withNeighbors.map(({ result, prevChunk, nextChunk }) => {
67
88
  const parts = [];
68
89
  if (prevChunk)
69
90
  parts.push((0, format_helpers_1.formatChunk)(prevChunk, 'prev chunk'));
70
- parts.push(`${(0, format_helpers_1.formatChunk)(result)}\n**Relevance:** ${result.score}${(0, format_helpers_1.formatGraphContext)(graphCtx?.get(result.filePath))}`);
91
+ parts.push(`${(0, format_helpers_1.formatChunk)(result)}\n**Distance:** ${result.score}${(0, format_helpers_1.formatGraphContext)(graphCtx?.get(result.filePath))}`);
71
92
  if (nextChunk)
72
93
  parts.push((0, format_helpers_1.formatChunk)(nextChunk, 'next chunk'));
73
94
  return parts.join('\n\n');
@@ -75,7 +96,7 @@ class SearchCodebaseTool {
75
96
  return (0, format_helpers_1.textResponse)(header + blocks.join('\n\n---\n\n'));
76
97
  }
77
98
  const text = results
78
- .map(r => `${(0, format_helpers_1.formatChunk)(r)}\n**Relevance:** ${r.score}${(0, format_helpers_1.formatGraphContext)(graphCtx?.get(r.filePath))}`)
99
+ .map(r => `${(0, format_helpers_1.formatChunk)(r)}\n**Distance:** ${r.score}${(0, format_helpers_1.formatGraphContext)(graphCtx?.get(r.filePath))}`)
79
100
  .join('\n\n---\n\n');
80
101
  return (0, format_helpers_1.textResponse)(header + text);
81
102
  }
@@ -1,23 +1,23 @@
1
- import type { ChunkRow, DependencyRow, GraphContext, FileRangeResult, PathFailure, PathRefusal } from '../services/SearcherService';
1
+ import type { ChunkRow } from '../interfaces/IChunkSearch';
2
+ import type { DependencyRow, GraphContext } from '../interfaces/IDependencyGraph';
3
+ import type { FileRangeResult } from '../interfaces/IWorkspaceFiles';
4
+ import type { PathFailure, PathRefusal } from '../interfaces/IToolPaths';
2
5
  import type { ToolResponse } from '../interfaces/IMcpToolHandler';
3
6
  import type { ILogger } from '../interfaces/ILogger';
4
7
  export declare function textResponse(text: string): ToolResponse;
5
8
  export declare function errorResponse(text: string): ToolResponse;
6
9
  export declare function formatChunk(r: ChunkRow, label?: string): string;
7
10
  export declare function formatGraphContext(ctx: GraphContext | undefined): string;
8
- export declare function formatDependencies(filePath: string, rows: DependencyRow[], transitive: boolean): string;
9
- export declare function formatDependents(filePath: string, rows: DependencyRow[], transitive: boolean): string;
11
+ export declare function formatDependencies(filePath: string, rows: DependencyRow[], transitive: boolean, symbol?: string | null): string;
12
+ export declare function formatDependents(filePath: string, rows: DependencyRow[], transitive: boolean, symbol?: string | null): string;
13
+ export declare function formatTransitiveSection(rows: DependencyRow[], symbol: string | null, side: 'dependencies' | 'dependents'): string;
14
+ export declare function formatDependenciesFilterMiss(filePath: string, symbol: string, unfiltered: DependencyRow[]): string;
15
+ export declare function formatDependentsFilterMiss(filePath: string, symbol: string, unfiltered: DependencyRow[]): string;
10
16
  export type PathKind = 'file' | 'directory';
11
17
  export declare const PATH_EXAMPLE: Record<PathKind, string>;
12
- /** Description of a path argument; `kind` names what the path points at. */
13
18
  export declare function pathArgDescription(kind?: PathKind): string;
14
19
  export type PathError = PathRefusal | PathFailure | Extract<FileRangeResult, {
15
20
  reason: 'past_end' | 'bad_range';
16
21
  }>;
17
- /**
18
- * Text of a path error. `input` is the raw argument (echoed by refusals);
19
- * `relPath` its canonical form, printed by every other message.
20
- */
21
22
  export declare function pathErrorText(argName: string, input: string, relPath: string, err: PathError, kind?: PathKind): string;
22
- /** Error response for a path error, logged at `warn` — a caller or index-freshness problem, not a server fault. */
23
23
  export declare function pathErrorResponse(logger: ILogger, tool: string, argName: string, input: string, relPath: string, err: PathError, kind?: PathKind): ToolResponse;