codesearch-mcp 0.3.0-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 (224) hide show
  1. package/CHANGELOG.md +59 -6
  2. package/LICENSE +661 -21
  3. package/README.md +33 -17
  4. package/dist/app.js +13 -20
  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/commands/EvalCommand.d.ts +7 -3
  22. package/dist/src/commands/EvalCommand.js +36 -158
  23. package/dist/src/commands/IndexCommand.d.ts +10 -4
  24. package/dist/src/commands/IndexCommand.js +52 -124
  25. package/dist/src/commands/McpCommand.d.ts +6 -3
  26. package/dist/src/commands/McpCommand.js +19 -14
  27. package/dist/src/commands/WebCommand.d.ts +9 -3
  28. package/dist/src/commands/WebCommand.js +17 -8
  29. package/dist/src/commands/eval/baseline-comparison.d.ts +6 -0
  30. package/dist/src/commands/eval/baseline-comparison.js +54 -0
  31. package/dist/src/commands/eval/eval-args.d.ts +6 -0
  32. package/dist/src/commands/eval/eval-args.js +71 -0
  33. package/dist/src/commands/eval/eval-corpora.d.ts +6 -0
  34. package/dist/src/commands/eval/eval-corpora.js +76 -0
  35. package/dist/src/commands/eval/eval-metadata.d.ts +17 -0
  36. package/dist/src/commands/eval/eval-metadata.js +75 -0
  37. package/dist/src/commands/eval/index-inspector.d.ts +3 -0
  38. package/dist/src/commands/eval/index-inspector.js +21 -0
  39. package/dist/src/commands/eval/staged-search.d.ts +3 -0
  40. package/dist/src/commands/eval/staged-search.js +20 -0
  41. package/dist/src/commands/eval/suite-loader.d.ts +8 -0
  42. package/dist/src/commands/eval/suite-loader.js +52 -0
  43. package/dist/src/commands/index/backend-probe.d.ts +2 -0
  44. package/dist/src/commands/index/backend-probe.js +15 -0
  45. package/dist/src/commands/index/embedding-setup.d.ts +3 -0
  46. package/dist/src/commands/index/embedding-setup.js +16 -0
  47. package/dist/src/commands/index/index-summary.d.ts +2 -0
  48. package/dist/src/commands/index/index-summary.js +22 -0
  49. package/dist/src/commands/index/legacy-ollama-guard.d.ts +3 -0
  50. package/dist/src/commands/index/legacy-ollama-guard.js +23 -0
  51. package/dist/src/commands/index/prune-step.d.ts +3 -0
  52. package/dist/src/commands/index/prune-step.js +22 -0
  53. package/dist/src/commands/index/scan-targets.d.ts +8 -0
  54. package/dist/src/commands/index/scan-targets.js +107 -0
  55. package/dist/src/config-store.d.ts +0 -1
  56. package/dist/src/config-store.js +3 -4
  57. package/dist/src/config.d.ts +1 -1
  58. package/dist/src/config.js +1 -1
  59. package/dist/src/constants.d.ts +15 -0
  60. package/dist/src/constants.js +34 -6
  61. package/dist/src/container.d.ts +4 -2
  62. package/dist/src/container.js +7 -5
  63. package/dist/src/db/drizzle-types.d.ts +7 -0
  64. package/dist/src/db/index.d.ts +1 -0
  65. package/dist/src/db/schema-steps.d.ts +8 -0
  66. package/dist/src/db/schema-steps.js +105 -0
  67. package/dist/src/declarations/DeclarationTree.d.ts +1 -1
  68. package/dist/src/eval-results.js +16 -2
  69. package/dist/src/eval-vector-index.d.ts +5 -0
  70. package/dist/src/eval-vector-index.js +60 -0
  71. package/dist/src/help.js +9 -1
  72. package/dist/src/index-args.d.ts +13 -0
  73. package/dist/src/index-args.js +48 -0
  74. package/dist/src/indexing/AnalysisBatcher.d.ts +12 -0
  75. package/dist/src/indexing/AnalysisBatcher.js +28 -0
  76. package/dist/src/indexing/ChunkEmbedder.d.ts +24 -0
  77. package/dist/src/indexing/ChunkEmbedder.js +37 -0
  78. package/dist/src/indexing/ConsoleScanReporter.d.ts +10 -0
  79. package/dist/src/indexing/ConsoleScanReporter.js +73 -0
  80. package/dist/src/indexing/EmbeddingSchemaPreparer.d.ts +14 -0
  81. package/dist/src/indexing/EmbeddingSchemaPreparer.js +66 -0
  82. package/dist/src/indexing/FileIngestor.d.ts +22 -0
  83. package/dist/src/indexing/FileIngestor.js +116 -0
  84. package/dist/src/indexing/IndexStore.d.ts +24 -0
  85. package/dist/src/indexing/IndexStore.js +69 -0
  86. package/dist/src/indexing/StaleFilePruner.d.ts +8 -0
  87. package/dist/src/indexing/StaleFilePruner.js +55 -0
  88. package/dist/src/indexing/analysis-rows.d.ts +4 -0
  89. package/dist/src/indexing/analysis-rows.js +65 -0
  90. package/dist/src/indexing/project-notices.d.ts +2 -0
  91. package/dist/src/indexing/project-notices.js +63 -0
  92. package/dist/src/interfaces/IAstParser.d.ts +2 -1
  93. package/dist/src/interfaces/ICallGraph.d.ts +28 -0
  94. package/dist/src/interfaces/ICallGraph.js +2 -0
  95. package/dist/src/interfaces/IChunkSearch.d.ts +42 -0
  96. package/dist/src/interfaces/IChunkSearch.js +2 -0
  97. package/dist/src/interfaces/IDatabase.d.ts +6 -2
  98. package/dist/src/interfaces/IDependencyGraph.d.ts +24 -0
  99. package/dist/src/interfaces/IDependencyGraph.js +2 -0
  100. package/dist/src/interfaces/IIndexIdentityGuard.d.ts +3 -0
  101. package/dist/src/interfaces/IIndexIdentityGuard.js +2 -0
  102. package/dist/src/interfaces/IIndexedNodeResolver.d.ts +10 -0
  103. package/dist/src/interfaces/IIndexedNodeResolver.js +2 -0
  104. package/dist/src/interfaces/IMcpReadiness.d.ts +12 -0
  105. package/dist/src/interfaces/IMcpReadiness.js +2 -0
  106. package/dist/src/interfaces/IProjectCatalog.d.ts +13 -0
  107. package/dist/src/interfaces/IProjectCatalog.js +2 -0
  108. package/dist/src/interfaces/IProjectRoots.d.ts +3 -0
  109. package/dist/src/interfaces/IProjectRoots.js +2 -0
  110. package/dist/src/interfaces/IRetrievalEvaluator.d.ts +21 -2
  111. package/dist/src/interfaces/IScanReporter.d.ts +13 -0
  112. package/dist/src/interfaces/IScanReporter.js +2 -0
  113. package/dist/src/interfaces/ISymbolLookup.d.ts +49 -0
  114. package/dist/src/interfaces/ISymbolLookup.js +2 -0
  115. package/dist/src/interfaces/IToolPaths.d.ts +62 -0
  116. package/dist/src/interfaces/IToolPaths.js +2 -0
  117. package/dist/src/interfaces/IWorkspaceFiles.d.ts +28 -0
  118. package/dist/src/interfaces/IWorkspaceFiles.js +2 -0
  119. package/dist/src/interfaces/SymbolKind.d.ts +1 -0
  120. package/dist/src/interfaces/SymbolKind.js +2 -0
  121. package/dist/src/interfaces/index.d.ts +12 -1
  122. package/dist/src/project-scope.d.ts +1 -0
  123. package/dist/src/project-scope.js +5 -0
  124. package/dist/src/retrieval-eval.d.ts +2 -1
  125. package/dist/src/retrieval-eval.js +45 -2
  126. package/dist/src/search/CallGraph.d.ts +9 -0
  127. package/dist/src/search/CallGraph.js +84 -0
  128. package/dist/src/search/ChunkSearch.d.ts +23 -0
  129. package/dist/src/search/ChunkSearch.js +115 -0
  130. package/dist/src/search/DependencyGraph.d.ts +19 -0
  131. package/dist/src/search/DependencyGraph.js +180 -0
  132. package/dist/src/search/IndexIdentityGuard.d.ts +11 -0
  133. package/dist/src/search/IndexIdentityGuard.js +37 -0
  134. package/dist/src/search/ProjectCatalog.d.ts +11 -0
  135. package/dist/src/search/ProjectCatalog.js +38 -0
  136. package/dist/src/search/SymbolLookup.d.ts +24 -0
  137. package/dist/src/search/SymbolLookup.js +97 -0
  138. package/dist/src/search/chunks/CandidateFetcher.d.ts +19 -0
  139. package/dist/src/search/chunks/CandidateFetcher.js +40 -0
  140. package/dist/src/search/chunks/IterativeScanGate.d.ts +10 -0
  141. package/dist/src/search/chunks/IterativeScanGate.js +42 -0
  142. package/dist/src/search/chunks/RerankStage.d.ts +15 -0
  143. package/dist/src/search/chunks/RerankStage.js +42 -0
  144. package/dist/src/search/chunks/search-metrics.d.ts +18 -0
  145. package/dist/src/search/chunks/search-metrics.js +32 -0
  146. package/dist/src/search/chunks/search-plan.d.ts +18 -0
  147. package/dist/src/search/chunks/search-plan.js +19 -0
  148. package/dist/src/search/create-search-services.d.ts +26 -0
  149. package/dist/src/search/create-search-services.js +29 -0
  150. package/dist/src/search/index-paths.d.ts +1 -0
  151. package/dist/src/search/index-paths.js +5 -0
  152. package/dist/src/search/symbol-sql.d.ts +13 -0
  153. package/dist/src/search/symbol-sql.js +66 -0
  154. package/dist/src/search/symbols/SymbolGrepFallback.d.ts +19 -0
  155. package/dist/src/search/symbols/SymbolGrepFallback.js +106 -0
  156. package/dist/src/search/symbols/SymbolIndexQuery.d.ts +14 -0
  157. package/dist/src/search/symbols/SymbolIndexQuery.js +52 -0
  158. package/dist/src/search/symbols/SymbolTextSearch.d.ts +13 -0
  159. package/dist/src/search/symbols/SymbolTextSearch.js +84 -0
  160. package/dist/src/search/symbols/TargetColumnGate.d.ts +7 -0
  161. package/dist/src/search/symbols/TargetColumnGate.js +23 -0
  162. package/dist/src/search/symbols/find-symbol-constants.d.ts +4 -0
  163. package/dist/src/search/symbols/find-symbol-constants.js +8 -0
  164. package/dist/src/search/symbols/grep-args.d.ts +3 -0
  165. package/dist/src/search/symbols/grep-args.js +7 -0
  166. package/dist/src/search/symbols/grep-patterns.d.ts +4 -0
  167. package/dist/src/search/symbols/grep-patterns.js +60 -0
  168. package/dist/src/services/AstParserService.d.ts +8 -44
  169. package/dist/src/services/AstParserService.js +19 -938
  170. package/dist/src/services/DatabaseService.d.ts +8 -10
  171. package/dist/src/services/DatabaseService.js +29 -86
  172. package/dist/src/services/IndexerService.d.ts +7 -10
  173. package/dist/src/services/IndexerService.js +36 -255
  174. package/dist/src/services/McpReadiness.d.ts +18 -0
  175. package/dist/src/services/McpReadiness.js +73 -0
  176. package/dist/src/services/McpServer.d.ts +32 -9
  177. package/dist/src/services/McpServer.js +78 -41
  178. package/dist/src/services/WebServerService.d.ts +4 -3
  179. package/dist/src/services/WebServerService.js +16 -8
  180. package/dist/src/setup.d.ts +16 -4
  181. package/dist/src/setup.js +115 -40
  182. package/dist/src/symbol-name.d.ts +1 -0
  183. package/dist/src/symbol-name.js +16 -12
  184. package/dist/src/tools/FindSymbolTool.d.ts +17 -7
  185. package/dist/src/tools/FindSymbolTool.js +54 -35
  186. package/dist/src/tools/GetCallersTool.d.ts +16 -8
  187. package/dist/src/tools/GetCallersTool.js +65 -35
  188. package/dist/src/tools/GetDependenciesTool.d.ts +16 -8
  189. package/dist/src/tools/GetDependenciesTool.js +35 -28
  190. package/dist/src/tools/GetDependentsTool.d.ts +20 -8
  191. package/dist/src/tools/GetDependentsTool.js +47 -33
  192. package/dist/src/tools/ListFilesTool.d.ts +16 -8
  193. package/dist/src/tools/ListFilesTool.js +20 -26
  194. package/dist/src/tools/ListProjectsTool.d.ts +11 -7
  195. package/dist/src/tools/ListProjectsTool.js +13 -11
  196. package/dist/src/tools/McpTool.d.ts +17 -0
  197. package/dist/src/tools/McpTool.js +28 -0
  198. package/dist/src/tools/ReadFileRangeTool.d.ts +16 -8
  199. package/dist/src/tools/ReadFileRangeTool.js +23 -25
  200. package/dist/src/tools/ReadFileTool.d.ts +15 -8
  201. package/dist/src/tools/ReadFileTool.js +19 -24
  202. package/dist/src/tools/SearchCodebaseTool.d.ts +22 -10
  203. package/dist/src/tools/SearchCodebaseTool.js +69 -51
  204. package/dist/src/tools/format-helpers.d.ts +9 -3
  205. package/dist/src/tools/format-helpers.js +59 -14
  206. package/dist/src/tools/tool-args.d.ts +38 -0
  207. package/dist/src/tools/tool-args.js +95 -0
  208. package/dist/src/workspace/GrepRunner.d.ts +15 -0
  209. package/dist/src/workspace/GrepRunner.js +104 -0
  210. package/dist/src/workspace/ProjectRoots.d.ts +22 -0
  211. package/dist/src/workspace/ProjectRoots.js +102 -0
  212. package/dist/src/workspace/ToolPaths.d.ts +31 -0
  213. package/dist/src/workspace/ToolPaths.js +312 -0
  214. package/dist/src/workspace/WorkspaceFiles.d.ts +19 -0
  215. package/dist/src/workspace/WorkspaceFiles.js +285 -0
  216. package/dist/src/workspace/fs-access.d.ts +9 -0
  217. package/dist/src/workspace/fs-access.js +47 -0
  218. package/dist/src/workspace/path-helpers.d.ts +3 -0
  219. package/dist/src/workspace/path-helpers.js +43 -0
  220. package/package.json +4 -3
  221. package/dist/src/interfaces/ISearcher.d.ts +0 -46
  222. package/dist/src/services/SearcherService.d.ts +0 -235
  223. package/dist/src/services/SearcherService.js +0 -1118
  224. /package/dist/src/{interfaces/ISearcher.js → db/drizzle-types.js} +0 -0
@@ -0,0 +1,24 @@
1
+ import type { Config } from '../config';
2
+ import type { IDatabase, ILogger } from '../interfaces';
3
+ import type { FindSymbolResult, GrepSymbolResult, ISymbolLookup, SymbolKind } from '../interfaces/ISymbolLookup';
4
+ import type { GrepRunner } from '../workspace/GrepRunner';
5
+ import type { ProjectRoots } from '../workspace/ProjectRoots';
6
+ import type { ToolPaths } from '../workspace/ToolPaths';
7
+ export declare class SymbolLookup implements ISymbolLookup {
8
+ private db;
9
+ private grep;
10
+ private roots;
11
+ private paths;
12
+ private config;
13
+ private logger;
14
+ private readonly textSearch;
15
+ private readonly gate;
16
+ private readonly indexQuery;
17
+ private readonly grepFallback;
18
+ constructor(db: IDatabase, grep: GrepRunner, roots: ProjectRoots, paths: ToolPaths, config: Config, logger: ILogger);
19
+ grepSymbol(symbol: string, rootDir: string, excludeFile: string): Promise<GrepSymbolResult>;
20
+ findSymbol(name: string, project: string | null, kind: SymbolKind): Promise<FindSymbolResult>;
21
+ private findSymbolFromIndex;
22
+ private indexedElsewhere;
23
+ private similarOrNone;
24
+ }
@@ -0,0 +1,97 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SymbolLookup = void 0;
4
+ const symbol_name_1 = require("../symbol-name");
5
+ const symbol_sql_1 = require("./symbol-sql");
6
+ const find_symbol_constants_1 = require("./symbols/find-symbol-constants");
7
+ const SymbolGrepFallback_1 = require("./symbols/SymbolGrepFallback");
8
+ const SymbolIndexQuery_1 = require("./symbols/SymbolIndexQuery");
9
+ const SymbolTextSearch_1 = require("./symbols/SymbolTextSearch");
10
+ const TargetColumnGate_1 = require("./symbols/TargetColumnGate");
11
+ const NO_SIMILAR = { names: [], truncated: false };
12
+ class SymbolLookup {
13
+ db;
14
+ grep;
15
+ roots;
16
+ paths;
17
+ config;
18
+ logger;
19
+ textSearch;
20
+ gate;
21
+ indexQuery;
22
+ grepFallback;
23
+ constructor(db, grep, roots, paths, config, logger) {
24
+ this.db = db;
25
+ this.grep = grep;
26
+ this.roots = roots;
27
+ this.paths = paths;
28
+ this.config = config;
29
+ this.logger = logger;
30
+ this.textSearch = new SymbolTextSearch_1.SymbolTextSearch(grep, roots, config, logger);
31
+ this.gate = new TargetColumnGate_1.TargetColumnGate(db);
32
+ this.indexQuery = new SymbolIndexQuery_1.SymbolIndexQuery(db, this.gate);
33
+ this.grepFallback = new SymbolGrepFallback_1.SymbolGrepFallback(grep, paths, config, logger);
34
+ }
35
+ grepSymbol(symbol, rootDir, excludeFile) {
36
+ return this.textSearch.search(symbol, rootDir, excludeFile);
37
+ }
38
+ findSymbol(name, project, kind) {
39
+ const parsed = (0, symbol_name_1.parseFindSymbolName)(name);
40
+ if (!parsed)
41
+ throw new Error('Invalid symbol name');
42
+ return this.findSymbolFromIndex(parsed, project, kind);
43
+ }
44
+ async findSymbolFromIndex(parsed, project, kind) {
45
+ const t0 = Date.now();
46
+ this.logger.debug('SymbolLookup: findSymbol', { parsed, project, kind, source: 'index' });
47
+ const isGraphqlKind = find_symbol_constants_1.GRAPHQL_KINDS.has(kind);
48
+ const grepped = parsed.form === 'bare' || parsed.form === 'qualified';
49
+ let indexed;
50
+ try {
51
+ indexed = await this.indexQuery.query(parsed, project, kind);
52
+ this.logger.debug('SymbolLookup: findSymbol result', { source: 'index', hits: indexed.hits.length, truncated: indexed.truncated, ms: Date.now() - t0 });
53
+ }
54
+ catch (err) {
55
+ this.logger.warn('SymbolLookup: symbol index unavailable', { err, ms: Date.now() - t0 });
56
+ if (isGraphqlKind)
57
+ throw err;
58
+ if (!grepped)
59
+ return { hits: [], truncated: false, grep: find_symbol_constants_1.COMPLETE, similar: NO_SIMILAR };
60
+ return { ...(await this.grepFallback.run(parsed, project, kind)), similar: NO_SIMILAR };
61
+ }
62
+ if (indexed.hits.length > 0)
63
+ return { ...indexed, grep: find_symbol_constants_1.COMPLETE, similar: NO_SIMILAR };
64
+ if (isGraphqlKind || !grepped)
65
+ return { hits: [], truncated: false, grep: find_symbol_constants_1.COMPLETE, similar: NO_SIMILAR };
66
+ let found;
67
+ if (parsed.form === 'qualified' && await this.indexedElsewhere(parsed.name, project, kind)) {
68
+ found = { hits: [], truncated: false, grep: { outcome: 'other-container' } };
69
+ }
70
+ else {
71
+ found = await this.grepFallback.run(parsed, project, kind);
72
+ }
73
+ if (found.hits.length > 0)
74
+ return { ...found, similar: NO_SIMILAR };
75
+ const exactFirst = found.grep.outcome === 'other-container' || kind !== 'all';
76
+ return { ...found, similar: await this.similarOrNone(parsed.name, project, exactFirst) };
77
+ }
78
+ async indexedElsewhere(name, project, kind) {
79
+ try {
80
+ return await (0, symbol_sql_1.symbolIndexedElsewhere)(this.db, name, project, kind);
81
+ }
82
+ catch (err) {
83
+ this.logger.warn('SymbolLookup: findSymbol other-container check failed', { err, name, project });
84
+ return false;
85
+ }
86
+ }
87
+ async similarOrNone(name, project, exactFirst) {
88
+ try {
89
+ return await (0, symbol_sql_1.similarSymbolNames)(this.db, name, project, exactFirst);
90
+ }
91
+ catch (err) {
92
+ this.logger.warn('SymbolLookup: findSymbol similar-name lookup failed', { err, name, project });
93
+ return NO_SIMILAR;
94
+ }
95
+ }
96
+ }
97
+ exports.SymbolLookup = SymbolLookup;
@@ -0,0 +1,19 @@
1
+ import type { IDatabase } from '../../interfaces';
2
+ import type { SearchResult } from '../../interfaces/IChunkSearch';
3
+ import type { IterativeScanGate } from './IterativeScanGate';
4
+ import type { SearchPlan } from './search-plan';
5
+ export interface CandidatePool {
6
+ candidates: SearchResult[];
7
+ poolSaturated: boolean;
8
+ indexParams: {
9
+ efSearch: number;
10
+ iterativeScan: string;
11
+ };
12
+ dbMs: number;
13
+ }
14
+ export declare class CandidateFetcher {
15
+ private db;
16
+ private gate;
17
+ constructor(db: IDatabase, gate: IterativeScanGate);
18
+ fetch(embedding: number[], plan: SearchPlan, project: string | null): Promise<CandidatePool>;
19
+ }
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CandidateFetcher = void 0;
4
+ const hnsw_settings_1 = require("../../hnsw-settings");
5
+ class CandidateFetcher {
6
+ db;
7
+ gate;
8
+ constructor(db, gate) {
9
+ this.db = db;
10
+ this.gate = gate;
11
+ }
12
+ async fetch(embedding, plan, project) {
13
+ const params = [`[${embedding}]`, plan.threshold.value, plan.dbLimit];
14
+ let projectFilter = '';
15
+ if (project) {
16
+ params.push(project);
17
+ projectFilter = `AND "serviceName" = $${params.length}`;
18
+ }
19
+ const iterative = await this.gate.enabled();
20
+ const settings = (0, hnsw_settings_1.hnswSettings)(plan.dbLimit, iterative);
21
+ const indexParams = {
22
+ efSearch: settings['hnsw.ef_search'],
23
+ iterativeScan: iterative ? hnsw_settings_1.ITERATIVE_SCAN_MODE : 'off',
24
+ };
25
+ const tDb0 = Date.now();
26
+ const fetched = await this.db.queryWithLocalSettings(settings, `SELECT "serviceName", "filePath", "startLine", content, "ownerPath",
27
+ ROUND((embedding <=> $1)::numeric, 4)::float8 AS score
28
+ FROM code_chunk
29
+ WHERE embedding <=> $1 < $2
30
+ ${projectFilter}
31
+ ORDER BY embedding <=> $1
32
+ LIMIT $3`, params);
33
+ const dbMs = Date.now() - tDb0;
34
+ fetched.sort((a, b) => a.score - b.score);
35
+ const poolSaturated = fetched.length > plan.fetchLimit;
36
+ const candidates = fetched.slice(0, plan.fetchLimit);
37
+ return { candidates, poolSaturated, indexParams, dbMs };
38
+ }
39
+ }
40
+ exports.CandidateFetcher = CandidateFetcher;
@@ -0,0 +1,10 @@
1
+ import type { IDatabase, ILogger } from '../../interfaces';
2
+ export declare class IterativeScanGate {
3
+ private db;
4
+ private logger;
5
+ private pgvectorVersionRead?;
6
+ private degradedScanWarned;
7
+ constructor(db: IDatabase, logger: ILogger);
8
+ enabled(): Promise<boolean>;
9
+ private warnDegraded;
10
+ }
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.IterativeScanGate = void 0;
4
+ const hnsw_settings_1 = require("../../hnsw-settings");
5
+ class IterativeScanGate {
6
+ db;
7
+ logger;
8
+ pgvectorVersionRead;
9
+ degradedScanWarned = false;
10
+ constructor(db, logger) {
11
+ this.db = db;
12
+ this.logger = logger;
13
+ }
14
+ async enabled() {
15
+ const read = this.pgvectorVersionRead ??= this.db.pgvectorVersion().then(v => {
16
+ if (v === null)
17
+ throw new Error('vector extension not found in pg_extension');
18
+ return v;
19
+ });
20
+ let version;
21
+ try {
22
+ version = await read;
23
+ }
24
+ catch (err) {
25
+ if (this.pgvectorVersionRead === read)
26
+ this.pgvectorVersionRead = undefined;
27
+ this.warnDegraded('unknown', err);
28
+ return false;
29
+ }
30
+ if ((0, hnsw_settings_1.supportsIterativeScan)(version))
31
+ return true;
32
+ this.warnDegraded(version);
33
+ return false;
34
+ }
35
+ warnDegraded(version, err) {
36
+ if (this.degradedScanWarned)
37
+ return;
38
+ this.degradedScanWarned = true;
39
+ this.logger.warn(`IterativeScanGate: pgvector ${version} lacks hnsw.iterative_scan — filtered searches on large projects may return fewer candidates than requested; upgrade to pgvector ≥ 0.8`, err ? { err } : undefined);
40
+ }
41
+ }
42
+ exports.IterativeScanGate = IterativeScanGate;
@@ -0,0 +1,15 @@
1
+ import type { IEmbedder, ILogger } from '../../interfaces';
2
+ import type { ChunkRow, SearchResult } from '../../interfaces/IChunkSearch';
3
+ import type { SearchPlan } from './search-plan';
4
+ export declare function rerankDocument(row: ChunkRow): string;
5
+ export interface RerankOutcome {
6
+ reranked: SearchResult[];
7
+ rerankFailed: boolean;
8
+ rerankMs: number;
9
+ }
10
+ export declare class RerankStage {
11
+ private embedder;
12
+ private logger;
13
+ constructor(embedder: IEmbedder, logger: ILogger);
14
+ run(query: string, candidates: SearchResult[], vector: SearchResult[], plan: SearchPlan, startedAt: number): Promise<RerankOutcome>;
15
+ }
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RerankStage = void 0;
4
+ exports.rerankDocument = rerankDocument;
5
+ const result_shaping_1 = require("../result-shaping");
6
+ function rerankDocument(row) {
7
+ const symbol = row.ownerPath ? ` | Symbol: ${oneLine(row.ownerPath)}` : '';
8
+ return `File: ${oneLine(row.filePath)}${symbol}\n${row.content}`;
9
+ }
10
+ function oneLine(text) {
11
+ return text.replace(/\s+/g, ' ').trim();
12
+ }
13
+ class RerankStage {
14
+ embedder;
15
+ logger;
16
+ constructor(embedder, logger) {
17
+ this.embedder = embedder;
18
+ this.logger = logger;
19
+ }
20
+ async run(query, candidates, vector, plan, startedAt) {
21
+ if (candidates.length === 0)
22
+ return { reranked: [], rerankFailed: false, rerankMs: 0 };
23
+ const tRerank0 = Date.now();
24
+ try {
25
+ const topN = plan.perFileActive ? candidates.length : plan.limit;
26
+ const indices = await this.embedder.rerank(query, candidates.map(rerankDocument), topN);
27
+ const rerankMs = Date.now() - tRerank0;
28
+ this.logger.debug('RerankStage: searchChunks rerank done', { indices, ms: Date.now() - startedAt });
29
+ const order = indices.filter(i => i >= 0 && i < candidates.length).map(i => candidates[i]);
30
+ return { reranked: (0, result_shaping_1.limitPerFile)(order, plan.limit, plan.perFile), rerankFailed: false, rerankMs };
31
+ }
32
+ catch (err) {
33
+ const rerankMs = Date.now() - tRerank0;
34
+ this.logger.warn('RerankStage: rerank failed, falling back to vector order', {
35
+ err,
36
+ ms: Date.now() - startedAt,
37
+ });
38
+ return { reranked: vector, rerankFailed: true, rerankMs };
39
+ }
40
+ }
41
+ }
42
+ exports.RerankStage = RerankStage;
@@ -0,0 +1,18 @@
1
+ import type { ResolvedThreshold } from '../../constants';
2
+ import type { SearchResult } from '../../interfaces/IChunkSearch';
3
+ export interface SearchMetricsInput {
4
+ fetchLimit: number;
5
+ candidates: SearchResult[];
6
+ results: SearchResult[];
7
+ poolSaturated: boolean;
8
+ indexParams: {
9
+ efSearch: number;
10
+ iterativeScan: string;
11
+ };
12
+ threshold: ResolvedThreshold;
13
+ embedMs: number;
14
+ dbMs: number;
15
+ rerankMs: number;
16
+ totalMs: number;
17
+ }
18
+ export declare function searchMetrics(query: string, m: SearchMetricsInput): Record<string, unknown>;
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.searchMetrics = searchMetrics;
4
+ function searchMetrics(query, m) {
5
+ const { candidates, results } = m;
6
+ const contentIndex = new Map(candidates.map((c, i) => [c, i]));
7
+ const maxCosineRankSurvived = results.reduce((max, r) => Math.max(max, contentIndex.get(r) ?? -1), -1);
8
+ const fileCounts = new Map();
9
+ for (const r of results)
10
+ fileCounts.set(r.filePath, (fileCounts.get(r.filePath) ?? 0) + 1);
11
+ const topFileCount = results.length ? Math.max(...fileCounts.values()) : 0;
12
+ return {
13
+ query: query.slice(0, 120),
14
+ fetchLimit: m.fetchLimit,
15
+ candidatesReturned: candidates.length,
16
+ poolSaturated: m.poolSaturated,
17
+ maxCosineRankSurvived,
18
+ resultCount: results.length,
19
+ distinctFilesInResult: fileCounts.size,
20
+ topFileShare: results.length ? +(topFileCount / results.length).toFixed(3) : 0,
21
+ bestResultScore: results.length ? Math.min(...results.map(r => r.score)) : null,
22
+ worstResultScore: results.length ? Math.max(...results.map(r => r.score)) : null,
23
+ efSearch: m.indexParams.efSearch,
24
+ iterativeScan: m.indexParams.iterativeScan,
25
+ threshold: m.threshold.value,
26
+ thresholdSource: m.threshold.source,
27
+ embedMs: m.embedMs,
28
+ rerankMs: m.rerankMs,
29
+ dbMs: m.dbMs,
30
+ totalMs: m.totalMs,
31
+ };
32
+ }
@@ -0,0 +1,18 @@
1
+ import type { Config } from '../../config';
2
+ import { type ResolvedThreshold } from '../../constants';
3
+ export interface SearchPlan {
4
+ limit: number;
5
+ perFile: number;
6
+ threshold: ResolvedThreshold;
7
+ reranking: boolean;
8
+ perFileActive: boolean;
9
+ fetchLimit: number;
10
+ dbLimit: number;
11
+ }
12
+ export declare function planSearch(call: {
13
+ limit: number;
14
+ perFile: number;
15
+ threshold?: number;
16
+ rerankOverride?: boolean;
17
+ rerankAvailable: boolean;
18
+ }, config: Config): SearchPlan;
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.planSearch = planSearch;
4
+ const constants_1 = require("../../constants");
5
+ function planSearch(call, config) {
6
+ const { limit, perFile, threshold, rerankOverride } = call;
7
+ const resolvedThreshold = (0, constants_1.resolveThreshold)({
8
+ callValue: threshold,
9
+ configValue: config.search.similarityThreshold,
10
+ model: config.embedding.model,
11
+ });
12
+ const reranking = rerankOverride === false ? false : call.rerankAvailable;
13
+ const perFileActive = perFile < limit;
14
+ const fetchLimit = reranking || perFileActive
15
+ ? Math.min(Math.max(limit * config.reranker.overfetch, config.reranker.candidateFloor), 200)
16
+ : limit;
17
+ const dbLimit = fetchLimit + 1;
18
+ return { limit, perFile, threshold: resolvedThreshold, reranking, perFileActive, fetchLimit, dbLimit };
19
+ }
@@ -0,0 +1,26 @@
1
+ import type { Config } from '../config';
2
+ import type { IDatabase, IEmbedder, ILogger, IProjectDiscovery } from '../interfaces';
3
+ import { type WorkspaceFs } from '../workspace/fs-access';
4
+ import { ProjectRoots } from '../workspace/ProjectRoots';
5
+ import { ToolPaths } from '../workspace/ToolPaths';
6
+ import { WorkspaceFiles } from '../workspace/WorkspaceFiles';
7
+ import { GrepRunner } from '../workspace/GrepRunner';
8
+ import { SymbolLookup } from './SymbolLookup';
9
+ import { CallGraph } from './CallGraph';
10
+ import { DependencyGraph } from './DependencyGraph';
11
+ import { IndexIdentityGuard } from './IndexIdentityGuard';
12
+ import { ChunkSearch } from './ChunkSearch';
13
+ import { ProjectCatalog } from './ProjectCatalog';
14
+ export interface SearchServices {
15
+ readonly roots: ProjectRoots;
16
+ readonly paths: ToolPaths;
17
+ readonly files: WorkspaceFiles;
18
+ readonly grep: GrepRunner;
19
+ readonly symbols: SymbolLookup;
20
+ readonly calls: CallGraph;
21
+ readonly dependencies: DependencyGraph;
22
+ readonly identity: IndexIdentityGuard;
23
+ readonly chunks: ChunkSearch;
24
+ readonly catalog: ProjectCatalog;
25
+ }
26
+ export declare function createSearchServices(db: IDatabase, embedder: IEmbedder, discovery: IProjectDiscovery, config: Config, logger?: ILogger, fsDeps?: Partial<WorkspaceFs>): SearchServices;
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createSearchServices = createSearchServices;
4
+ const LoggerService_1 = require("../services/LoggerService");
5
+ const fs_access_1 = require("../workspace/fs-access");
6
+ const ProjectRoots_1 = require("../workspace/ProjectRoots");
7
+ const ToolPaths_1 = require("../workspace/ToolPaths");
8
+ const WorkspaceFiles_1 = require("../workspace/WorkspaceFiles");
9
+ const GrepRunner_1 = require("../workspace/GrepRunner");
10
+ const SymbolLookup_1 = require("./SymbolLookup");
11
+ const CallGraph_1 = require("./CallGraph");
12
+ const DependencyGraph_1 = require("./DependencyGraph");
13
+ const IndexIdentityGuard_1 = require("./IndexIdentityGuard");
14
+ const ChunkSearch_1 = require("./ChunkSearch");
15
+ const ProjectCatalog_1 = require("./ProjectCatalog");
16
+ function createSearchServices(db, embedder, discovery, config, logger = LoggerService_1.LoggerService.silent(), fsDeps = {}) {
17
+ const fs = { ...fs_access_1.NODE_FS, ...fsDeps };
18
+ const roots = new ProjectRoots_1.ProjectRoots(discovery, config);
19
+ const paths = new ToolPaths_1.ToolPaths(db, roots, logger, fs);
20
+ const files = new WorkspaceFiles_1.WorkspaceFiles(paths, roots, logger, fs);
21
+ const grep = new GrepRunner_1.GrepRunner(logger);
22
+ const symbols = new SymbolLookup_1.SymbolLookup(db, grep, roots, paths, config, logger);
23
+ const calls = new CallGraph_1.CallGraph(db, logger);
24
+ const dependencies = new DependencyGraph_1.DependencyGraph(db, roots, config, logger);
25
+ const identity = new IndexIdentityGuard_1.IndexIdentityGuard(db, embedder, config);
26
+ const chunks = new ChunkSearch_1.ChunkSearch(db, embedder, identity, config, logger);
27
+ const catalog = new ProjectCatalog_1.ProjectCatalog(db, roots, fs);
28
+ return { roots, paths, files, grep, symbols, calls, dependencies, identity, chunks, catalog };
29
+ }
@@ -0,0 +1 @@
1
+ export declare const OUTSIDE_WORKSPACE_VALUE: (col: string) => string;
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.OUTSIDE_WORKSPACE_VALUE = void 0;
4
+ const OUTSIDE_WORKSPACE_VALUE = (col) => `(${col} = '..' OR ${col} LIKE '../%')`;
5
+ exports.OUTSIDE_WORKSPACE_VALUE = OUTSIDE_WORKSPACE_VALUE;
@@ -0,0 +1,13 @@
1
+ import type { IDatabase } from '../interfaces';
2
+ import type { SymbolKind } from '../interfaces/ISymbolLookup';
3
+ export declare function symbolMatch(name: string, container: string | null, params: unknown[]): {
4
+ filter: string;
5
+ exactRank: string | null;
6
+ };
7
+ export declare const QUALIFIED_SQL = "COALESCE(container || '.', '') || name";
8
+ export declare const SIMILAR_NAMES_LIMIT = 5;
9
+ export declare function similarSymbolNames(db: IDatabase, name: string, project: string | null, exactFirst: boolean): Promise<{
10
+ names: string[];
11
+ truncated: boolean;
12
+ }>;
13
+ export declare function symbolIndexedElsewhere(db: IDatabase, name: string, project: string | null, kind: SymbolKind): Promise<boolean>;
@@ -0,0 +1,66 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SIMILAR_NAMES_LIMIT = exports.QUALIFIED_SQL = void 0;
4
+ exports.symbolMatch = symbolMatch;
5
+ exports.similarSymbolNames = similarSymbolNames;
6
+ exports.symbolIndexedElsewhere = symbolIndexedElsewhere;
7
+ const symbol_name_1 = require("../symbol-name");
8
+ function symbolMatch(name, container, params) {
9
+ params.push(name);
10
+ const nameFilter = `name = $${params.length}`;
11
+ if (container === null)
12
+ return { filter: nameFilter, exactRank: null };
13
+ params.push(container);
14
+ const exactParam = params.length;
15
+ params.push(`%.${(0, symbol_name_1.escapeLike)(container)}`);
16
+ const suffixParam = params.length;
17
+ return {
18
+ filter: `${nameFilter} AND (container = $${exactParam} OR container LIKE $${suffixParam} ESCAPE '\\')`,
19
+ exactRank: `(CASE WHEN container = $${exactParam} THEN 0 ELSE 1 END)`,
20
+ };
21
+ }
22
+ exports.QUALIFIED_SQL = `COALESCE(container || '.', '') || name`;
23
+ exports.SIMILAR_NAMES_LIMIT = 5;
24
+ async function similarSymbolNames(db, name, project, exactFirst) {
25
+ const params = [];
26
+ let projectFilter = '';
27
+ if (project !== null) {
28
+ params.push(project);
29
+ projectFilter = `project = $${params.length} AND `;
30
+ }
31
+ params.push(`${(0, symbol_name_1.escapeLike)(name)}%`);
32
+ const likeParam = params.length;
33
+ let exactRank = '';
34
+ if (exactFirst) {
35
+ params.push(name);
36
+ exactRank = `(CASE WHEN name = $${params.length} THEN 0 ELSE 1 END), `;
37
+ }
38
+ params.push(exports.SIMILAR_NAMES_LIMIT + 1);
39
+ const rows = await db.query(`SELECT qualified
40
+ FROM (
41
+ SELECT DISTINCT name, ${exports.QUALIFIED_SQL} AS qualified
42
+ FROM code_symbol
43
+ WHERE ${projectFilter}name ILIKE $${likeParam} ESCAPE '\\'
44
+ ) AS suggestions
45
+ ORDER BY ${exactRank}name COLLATE "C", qualified COLLATE "C"
46
+ LIMIT $${params.length}`, params);
47
+ return {
48
+ names: rows.slice(0, exports.SIMILAR_NAMES_LIMIT).map(r => r.qualified),
49
+ truncated: rows.length > exports.SIMILAR_NAMES_LIMIT,
50
+ };
51
+ }
52
+ async function symbolIndexedElsewhere(db, name, project, kind) {
53
+ const params = [name];
54
+ let projectFilter = '';
55
+ if (project) {
56
+ params.push(project);
57
+ projectFilter = `AND project = $${params.length}`;
58
+ }
59
+ let kindFilter = '';
60
+ if (kind !== 'all') {
61
+ params.push(kind);
62
+ kindFilter = `AND kind = $${params.length}`;
63
+ }
64
+ const rows = await db.query(`SELECT EXISTS (SELECT 1 FROM code_symbol WHERE name = $1 ${projectFilter} ${kindFilter}) AS present`, params);
65
+ return !!rows[0]?.present;
66
+ }
@@ -0,0 +1,19 @@
1
+ import type { Config } from '../../config';
2
+ import type { ILogger } from '../../interfaces';
3
+ import type { FindSymbolGrep, SymbolHit, SymbolKind } from '../../interfaces/ISymbolLookup';
4
+ import type { FindSymbolQuery } from '../../symbol-name';
5
+ import type { GrepRunner } from '../../workspace/GrepRunner';
6
+ import type { ToolPaths } from '../../workspace/ToolPaths';
7
+ export type GrepFindResult = {
8
+ hits: SymbolHit[];
9
+ truncated: boolean;
10
+ grep: FindSymbolGrep;
11
+ };
12
+ export declare class SymbolGrepFallback {
13
+ private grep;
14
+ private paths;
15
+ private config;
16
+ private logger;
17
+ constructor(grep: GrepRunner, paths: ToolPaths, config: Config, logger: ILogger);
18
+ run(parsed: FindSymbolQuery, project: string | null, kind: SymbolKind): Promise<GrepFindResult>;
19
+ }
@@ -0,0 +1,106 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.SymbolGrepFallback = void 0;
37
+ const path = __importStar(require("path"));
38
+ const find_symbol_constants_1 = require("./find-symbol-constants");
39
+ const grep_args_1 = require("./grep-args");
40
+ const grep_patterns_1 = require("./grep-patterns");
41
+ const FIND_SYMBOL_RAW_LIMIT = find_symbol_constants_1.FIND_SYMBOL_LIMIT * 10;
42
+ class SymbolGrepFallback {
43
+ grep;
44
+ paths;
45
+ config;
46
+ logger;
47
+ constructor(grep, paths, config, logger) {
48
+ this.grep = grep;
49
+ this.paths = paths;
50
+ this.config = config;
51
+ this.logger = logger;
52
+ }
53
+ async run(parsed, project, kind) {
54
+ const t0 = Date.now();
55
+ const grepName = parsed.name;
56
+ this.logger.debug('SymbolGrepFallback: findSymbol', { grepName, project, kind, source: 'grep' });
57
+ const pattern = (0, grep_patterns_1.buildFindSymbolPattern)(grepName, kind);
58
+ if (pattern === null)
59
+ return { hits: [], truncated: false, grep: find_symbol_constants_1.COMPLETE };
60
+ const searchDir = project ? await this.paths.grepSearchDir(project) : this.config.workspaceRoot;
61
+ if (searchDir === null)
62
+ return { hits: [], truncated: false, grep: { outcome: 'no-project-directory' } };
63
+ const result = await this.grep.run([
64
+ '-rn', '-E',
65
+ grep_args_1.GREP_BINARY_AS_TEXT,
66
+ '-m', String(FIND_SYMBOL_RAW_LIMIT),
67
+ ...grep_args_1.SOURCE_INCLUDES,
68
+ ...grep_args_1.GREP_EXCLUDE_DIRS,
69
+ pattern,
70
+ searchDir,
71
+ ]);
72
+ if (!result.ok)
73
+ this.logger.warn('SymbolGrepFallback: findSymbol grep failed', { grepName, project, failure: result.failure });
74
+ const parsedHits = [];
75
+ for (const raw of (result.output ?? '').split('\n').slice(0, -1)) {
76
+ const m = raw.match(/^(.+?):(\d+):(.*)$/s);
77
+ if (!m)
78
+ continue;
79
+ const [, absFile, lineNumStr, matchedLine] = m;
80
+ const lineNum = parseInt(lineNumStr, 10);
81
+ if (isNaN(lineNum))
82
+ continue;
83
+ const col = (0, grep_patterns_1.wholeWordIndex)(matchedLine, grepName);
84
+ if (col === -1)
85
+ continue;
86
+ parsedHits.push({
87
+ filePath: path.relative(this.config.workspaceRoot, absFile),
88
+ line: lineNum,
89
+ column: col + 1,
90
+ kind: (0, grep_patterns_1.inferKind)(matchedLine, grepName),
91
+ signature: matchedLine.trim(),
92
+ qualified: grepName,
93
+ isStatic: false,
94
+ source: 'grep',
95
+ target: null,
96
+ });
97
+ }
98
+ const truncated = parsedHits.length > find_symbol_constants_1.FIND_SYMBOL_LIMIT;
99
+ this.logger.debug('SymbolGrepFallback: findSymbol result', { source: 'grep', hits: Math.min(parsedHits.length, find_symbol_constants_1.FIND_SYMBOL_LIMIT), truncated, partial: !result.ok, ms: Date.now() - t0 });
100
+ let grep = find_symbol_constants_1.COMPLETE;
101
+ if (!result.ok)
102
+ grep = parsedHits.length > 0 ? { outcome: 'partial' } : { outcome: 'failed', cause: result.failure ?? 'unknown' };
103
+ return { hits: parsedHits.slice(0, find_symbol_constants_1.FIND_SYMBOL_LIMIT), truncated, grep };
104
+ }
105
+ }
106
+ exports.SymbolGrepFallback = SymbolGrepFallback;