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,93 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.GRAPHQL_NAME_RE = exports.GRAPHQL_OPERATION_KIND = exports.GRAPHQL_TYPE_DECORATORS = exports.GRAPHQL_MODULE = void 0;
4
+ exports.decoratorIdentifier = decoratorIdentifier;
5
+ exports.literalStringValue = literalStringValue;
6
+ exports.checkGraphqlGrammar = checkGraphqlGrammar;
7
+ exports.isAbstractGraphqlType = isAbstractGraphqlType;
8
+ exports.findNameProperty = findNameProperty;
9
+ exports.peekThroughWrapper = peekThroughWrapper;
10
+ exports.extractResolverIdentifier = extractResolverIdentifier;
11
+ const ts_morph_1 = require("ts-morph");
12
+ exports.GRAPHQL_MODULE = '@nestjs/graphql';
13
+ exports.GRAPHQL_TYPE_DECORATORS = new Set(['ObjectType', 'InputType', 'InterfaceType']);
14
+ exports.GRAPHQL_OPERATION_KIND = {
15
+ Query: 'graphql_query', Mutation: 'graphql_mutation', Subscription: 'graphql_subscription',
16
+ };
17
+ exports.GRAPHQL_NAME_RE = /^[_A-Za-z][_0-9A-Za-z]*$/;
18
+ function decoratorIdentifier(dec) {
19
+ const expr = dec.getExpression();
20
+ if (ts_morph_1.Node.isCallExpression(expr)) {
21
+ const callee = expr.getExpression();
22
+ return ts_morph_1.Node.isIdentifier(callee) ? callee : undefined;
23
+ }
24
+ return ts_morph_1.Node.isIdentifier(expr) ? expr : undefined;
25
+ }
26
+ function literalStringValue(node) {
27
+ if (ts_morph_1.Node.isStringLiteral(node) || ts_morph_1.Node.isNoSubstitutionTemplateLiteral(node))
28
+ return node.getLiteralValue();
29
+ return null;
30
+ }
31
+ function checkGraphqlGrammar(name) {
32
+ return exports.GRAPHQL_NAME_RE.test(name) ? { ok: true, name } : { ok: false, reason: 'invalid-name', value: name };
33
+ }
34
+ function isAbstractGraphqlType(args) {
35
+ return args.some((arg) => {
36
+ if (!ts_morph_1.Node.isObjectLiteralExpression(arg))
37
+ return false;
38
+ const prop = arg.getProperties().find((p) => {
39
+ if (!ts_morph_1.Node.isPropertyAssignment(p))
40
+ return false;
41
+ const nameNode = p.getNameNode();
42
+ if (ts_morph_1.Node.isIdentifier(nameNode))
43
+ return nameNode.getText() === 'isAbstract';
44
+ if (ts_morph_1.Node.isStringLiteral(nameNode))
45
+ return nameNode.getLiteralValue() === 'isAbstract';
46
+ return false;
47
+ });
48
+ const init = prop?.getInitializer();
49
+ return init !== undefined && ts_morph_1.Node.isTrueLiteral(init);
50
+ });
51
+ }
52
+ function findNameProperty(obj) {
53
+ return obj.getProperties().find((p) => {
54
+ if (!ts_morph_1.Node.isPropertyAssignment(p) && !ts_morph_1.Node.isShorthandPropertyAssignment(p))
55
+ return false;
56
+ const nameNode = p.getNameNode();
57
+ if (ts_morph_1.Node.isIdentifier(nameNode))
58
+ return nameNode.getText() === 'name';
59
+ if (ts_morph_1.Node.isStringLiteral(nameNode))
60
+ return nameNode.getLiteralValue() === 'name';
61
+ return false;
62
+ });
63
+ }
64
+ function peekThroughWrapper(node) {
65
+ let current = node;
66
+ let wrapped = false;
67
+ while (true) {
68
+ if (ts_morph_1.Node.isParenthesizedExpression(current) || ts_morph_1.Node.isAsExpression(current) || ts_morph_1.Node.isSatisfiesExpression(current) || ts_morph_1.Node.isNonNullExpression(current)) {
69
+ current = current.getExpression();
70
+ wrapped = true;
71
+ continue;
72
+ }
73
+ break;
74
+ }
75
+ return { inner: current, wrapped };
76
+ }
77
+ function extractResolverIdentifier(argNode) {
78
+ let target = argNode;
79
+ if (ts_morph_1.Node.isArrowFunction(target)) {
80
+ const body = target.getBody();
81
+ if (ts_morph_1.Node.isBlock(body))
82
+ return null;
83
+ target = body;
84
+ }
85
+ if (ts_morph_1.Node.isIdentifier(target))
86
+ return target;
87
+ if (ts_morph_1.Node.isArrayLiteralExpression(target)) {
88
+ const elements = target.getElements();
89
+ if (elements.length === 1 && ts_morph_1.Node.isIdentifier(elements[0]))
90
+ return elements[0];
91
+ }
92
+ return null;
93
+ }
@@ -0,0 +1,11 @@
1
+ import { Node, type SourceFile } from 'ts-morph';
2
+ export type ResolveDeclaration = (identifier: Node) => Node | undefined;
3
+ export declare function getPos(sourceFile: SourceFile, node: Node): {
4
+ line: number;
5
+ col: number;
6
+ };
7
+ export declare function lineTextAt(sourceLines: string[], sourceFile: SourceFile, node: Node): string;
8
+ export declare function memberName(nameNode: Node | undefined): string | null;
9
+ export declare function unwrapExpr(node: Node): Node;
10
+ export declare function unwrapParent(node: Node): Node | undefined;
11
+ export declare function defaultResolveDeclaration(identifier: Node): Node | undefined;
@@ -0,0 +1,55 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getPos = getPos;
4
+ exports.lineTextAt = lineTextAt;
5
+ exports.memberName = memberName;
6
+ exports.unwrapExpr = unwrapExpr;
7
+ exports.unwrapParent = unwrapParent;
8
+ exports.defaultResolveDeclaration = defaultResolveDeclaration;
9
+ const ts_morph_1 = require("ts-morph");
10
+ function getPos(sourceFile, node) {
11
+ const { line, character } = sourceFile.compilerNode
12
+ .getLineAndCharacterOfPosition(node.getStart());
13
+ return { line: line + 1, col: character + 1 };
14
+ }
15
+ function lineTextAt(sourceLines, sourceFile, node) {
16
+ const { line } = getPos(sourceFile, node);
17
+ return (sourceLines[line - 1] ?? node.getText().split('\n')[0]).trim();
18
+ }
19
+ function memberName(nameNode) {
20
+ if (!nameNode)
21
+ return null;
22
+ if (ts_morph_1.Node.isPrivateIdentifier(nameNode))
23
+ return nameNode.getText();
24
+ if (ts_morph_1.Node.isIdentifier(nameNode))
25
+ return nameNode.getText();
26
+ if (ts_morph_1.Node.isStringLiteral(nameNode))
27
+ return nameNode.getLiteralValue();
28
+ if (ts_morph_1.Node.isNumericLiteral(nameNode))
29
+ return nameNode.getText();
30
+ if (ts_morph_1.Node.isComputedPropertyName(nameNode))
31
+ return nameNode.getText().replace(/\s+/g, '');
32
+ return null;
33
+ }
34
+ function unwrapExpr(node) {
35
+ let current = node;
36
+ while (ts_morph_1.Node.isParenthesizedExpression(current) || ts_morph_1.Node.isAsExpression(current) || ts_morph_1.Node.isSatisfiesExpression(current)) {
37
+ current = current.getExpression();
38
+ }
39
+ return current;
40
+ }
41
+ function unwrapParent(node) {
42
+ let current = node.getParent();
43
+ while (current && (ts_morph_1.Node.isParenthesizedExpression(current) || ts_morph_1.Node.isAsExpression(current) || ts_morph_1.Node.isSatisfiesExpression(current))) {
44
+ current = current.getParent();
45
+ }
46
+ return current;
47
+ }
48
+ function defaultResolveDeclaration(identifier) {
49
+ const sym = identifier.getSymbol();
50
+ if (!sym)
51
+ return undefined;
52
+ const firstDecl = sym.getDeclarations()?.[0];
53
+ const resolved = firstDecl && ts_morph_1.Node.isImportSpecifier(firstDecl) ? (sym.getAliasedSymbol() ?? sym) : sym;
54
+ return resolved.getDeclarations()?.[0];
55
+ }
@@ -1,11 +1,15 @@
1
- import type { Container } from '../container';
1
+ import type { Config } from '../config';
2
+ import type { IDatabase, IChunkSearch, IProjectCatalog } from '../interfaces';
2
3
  import type { ICommand } from './ICommand';
3
4
  import type { ICorpusInspector } from '../interfaces/ICorpusInspector';
4
5
  export declare class EvalCommand implements ICommand {
5
- private container;
6
+ private db;
7
+ private chunks;
8
+ private catalog;
9
+ private config;
6
10
  private argv1;
7
11
  private corpusInspector;
8
12
  private resultsDir;
9
- constructor(container: Container, argv1: string, corpusInspector?: ICorpusInspector, resultsDir?: string);
13
+ constructor(db: IDatabase, chunks: IChunkSearch, catalog: IProjectCatalog, config: Config, argv1: string, corpusInspector?: ICorpusInspector, resultsDir?: string);
10
14
  execute(): Promise<void>;
11
15
  }
@@ -36,87 +36,44 @@ Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.EvalCommand = void 0;
37
37
  const fs = __importStar(require("fs"));
38
38
  const path = __importStar(require("path"));
39
- const crypto = __importStar(require("crypto"));
40
- const child_process_1 = require("child_process");
41
39
  const retrieval_eval_1 = require("../retrieval-eval");
42
40
  const eval_results_1 = require("../eval-results");
43
41
  const eval_corpus_1 = require("../eval-corpus");
44
- const DEFAULT_SUITE_DIR = path.join('benchmarks', 'eval');
42
+ const eval_vector_index_1 = require("../eval-vector-index");
43
+ const constants_1 = require("../constants");
44
+ const eval_args_1 = require("./eval/eval-args");
45
+ const suite_loader_1 = require("./eval/suite-loader");
46
+ const eval_corpora_1 = require("./eval/eval-corpora");
47
+ const index_inspector_1 = require("./eval/index-inspector");
48
+ const staged_search_1 = require("./eval/staged-search");
49
+ const eval_metadata_1 = require("./eval/eval-metadata");
50
+ const baseline_comparison_1 = require("./eval/baseline-comparison");
45
51
  const RESULTS_DIR_NAME = path.join('benchmarks', 'results');
46
- const KEPT_CORPUS_DIR = path.join('benchmarks', 'corpus');
47
52
  const _projectRoot = fs.existsSync(path.join(__dirname, '..', '..', 'package.json'))
48
53
  ? path.join(__dirname, '..', '..')
49
54
  : path.join(__dirname, '..', '..', '..');
50
- function gitCommit() {
51
- try {
52
- return (0, child_process_1.execFileSync)('git', ['rev-parse', 'HEAD'], { cwd: _projectRoot, encoding: 'utf-8' }).trim();
53
- }
54
- catch {
55
- return 'unknown';
56
- }
57
- }
58
- function hashContent(text) {
59
- return crypto.createHash('sha256').update(text).digest('hex').slice(0, 16);
60
- }
61
- function parseSuiteFlag(args) {
62
- const i = args.indexOf('--suite');
63
- if (i === -1)
64
- return DEFAULT_SUITE_DIR;
65
- const next = args[i + 1];
66
- if (next === undefined || next.startsWith('-'))
67
- throw new Error('--suite requires a path');
68
- return next;
69
- }
70
- function parseBaselineFlag(args) {
71
- const i = args.indexOf('--baseline');
72
- if (i === -1)
73
- return null;
74
- const next = args[i + 1];
75
- if (next === undefined || next.startsWith('-'))
76
- throw new Error('--baseline requires a path');
77
- return next;
78
- }
79
- function parseProjectFlag(args) {
80
- const i = args.indexOf('--project');
81
- if (i === -1)
82
- return null;
83
- const next = args[i + 1];
84
- if (next === undefined || next.startsWith('-'))
85
- throw new Error('--project requires a name');
86
- return next;
87
- }
88
- function loadSuite(suitePath) {
89
- const resolved = path.resolve(_projectRoot, suitePath);
90
- const stat = fs.statSync(resolved);
91
- if (stat.isDirectory()) {
92
- const files = fs.readdirSync(resolved).filter(f => f.endsWith('.json')).sort();
93
- const parts = files.map(f => fs.readFileSync(path.join(resolved, f), 'utf-8'));
94
- const suites = parts.map(text => (0, retrieval_eval_1.parseSuite)(JSON.parse(text)));
95
- return { suite: (0, retrieval_eval_1.mergeSuites)(suites), corpora: (0, retrieval_eval_1.corporaOf)(suites), rawContent: parts.join('\n'), label: 'all' };
96
- }
97
- const text = fs.readFileSync(resolved, 'utf-8');
98
- const suite = (0, retrieval_eval_1.parseSuite)(JSON.parse(text));
99
- return { suite, corpora: (0, retrieval_eval_1.corporaOf)([suite]), rawContent: text, label: path.basename(resolved, '.json') };
100
- }
101
55
  class EvalCommand {
102
- container;
56
+ db;
57
+ chunks;
58
+ catalog;
59
+ config;
103
60
  argv1;
104
61
  corpusInspector;
105
62
  resultsDir;
106
- constructor(container, argv1, corpusInspector = new eval_corpus_1.GitCorpusInspector(), resultsDir = path.join(_projectRoot, RESULTS_DIR_NAME)) {
107
- this.container = container;
63
+ constructor(db, chunks, catalog, config, argv1, corpusInspector = new eval_corpus_1.GitCorpusInspector(), resultsDir = path.join(_projectRoot, RESULTS_DIR_NAME)) {
64
+ this.db = db;
65
+ this.chunks = chunks;
66
+ this.catalog = catalog;
67
+ this.config = config;
108
68
  this.argv1 = argv1;
109
69
  this.corpusInspector = corpusInspector;
110
70
  this.resultsDir = resultsDir;
111
71
  }
112
72
  async execute() {
113
- const { db, searcher, config } = this.container;
114
73
  const args = process.argv.slice(this.argv1 === 'rag-index' ? 3 : 4);
115
74
  let suitePath, baselinePath, projectFilter;
116
75
  try {
117
- suitePath = parseSuiteFlag(args);
118
- baselinePath = parseBaselineFlag(args);
119
- projectFilter = parseProjectFlag(args);
76
+ ({ suitePath, baselinePath, projectFilter } = (0, eval_args_1.parseEvalArgs)(args));
120
77
  }
121
78
  catch (err) {
122
79
  console.error(`\n${err.message}`);
@@ -125,7 +82,7 @@ class EvalCommand {
125
82
  }
126
83
  let suite, corpora, rawContent, label;
127
84
  try {
128
- ({ suite, corpora, rawContent, label } = loadSuite(suitePath));
85
+ ({ suite, corpora, rawContent, label } = (0, suite_loader_1.loadSuite)(_projectRoot, suitePath));
129
86
  }
130
87
  catch (err) {
131
88
  if (err instanceof retrieval_eval_1.EvalSuiteError) {
@@ -146,59 +103,16 @@ class EvalCommand {
146
103
  return;
147
104
  }
148
105
  const runCorpora = corpora.filter(c => suite.cases.some(k => k.corpus === c.root));
149
- let refused = false;
150
- for (const corpus of runCorpora) {
151
- let failures;
152
- try {
153
- failures = await (0, eval_corpus_1.checkCorpus)(corpus, path.join(config.workspaceRoot, corpus.root), path.join(_projectRoot, KEPT_CORPUS_DIR, corpus.root), this.corpusInspector);
154
- }
155
- catch (err) {
156
- failures = [`cannot inspect the checkout: ${err.message}`];
157
- }
158
- if (failures.length === 0)
159
- continue;
160
- refused = true;
161
- console.error(`\nCorpus ${corpus.root} does not match ${corpus.commit}:`);
162
- for (const f of failures)
163
- console.error(` - ${f}`);
164
- }
165
- if (refused) {
166
- console.error('\nNo search was run and no result file was written.');
167
- process.exitCode = 1;
106
+ if (await (0, eval_corpora_1.refusesMovedCorpus)(runCorpora, this.config, _projectRoot, this.corpusInspector))
168
107
  return;
169
- }
170
- await db.initDbWithSchema();
171
- const projectDirs = new Map((await searcher.listProjects()).map(p => [p.serviceName, p.relPath ?? null]));
172
- const knownFilesCache = new Map();
173
- const inspect = {
174
- async isFileIndexed(project, file) {
175
- if (!knownFilesCache.has(project))
176
- knownFilesCache.set(project, db.listKnownFiles(project));
177
- const files = await knownFilesCache.get(project);
178
- return files.includes(file);
179
- },
180
- async ownerPathsOfFile(project, file) {
181
- const rows = await db.query(`SELECT DISTINCT "ownerPath" FROM code_chunk WHERE "serviceName" = $1 AND "filePath" = $2 AND "ownerPath" IS NOT NULL`, [project, file]);
182
- return rows.map(r => r.ownerPath);
183
- },
184
- async projectDir(project) {
185
- return projectDirs.get(project) ?? null;
186
- },
187
- };
188
- const toHits = (rows) => rows.map(r => ({ filePath: r.filePath, ownerPath: r.ownerPath ?? null }));
189
- const search = async (query, limit, project, threshold) => {
190
- const prepared = await searcher.prepareQuery(query);
191
- const r = await searcher.searchChunksWithStages(prepared.query, limit, project, threshold, undefined, limit);
192
- return {
193
- pool: toHits(r.pool),
194
- stages: r.stages.reranked
195
- ? { vector: toHits(r.stages.vector), reranked: toHits(r.stages.reranked) }
196
- : { vector: toHits(r.stages.vector) },
197
- rerankFailed: r.rerankFailed,
198
- fetchLimit: r.fetchLimit,
199
- indexParams: r.indexParams,
200
- };
201
- };
108
+ await this.db.initDbWithSchema();
109
+ const projectDirs = new Map((await this.catalog.listProjects()).map(p => [p.serviceName, p.relPath ?? null]));
110
+ const inspect = (0, index_inspector_1.createIndexInspector)(this.db, projectDirs);
111
+ const search = (0, staged_search_1.createStagedSearch)(this.chunks);
112
+ const thresholdWarning = (0, constants_1.thresholdMismatchWarning)(this.config.search.similarityThreshold, this.config.embedding.model);
113
+ if (thresholdWarning)
114
+ console.warn(`\n⚠ ${thresholdWarning}\n`);
115
+ const vectorIndex = await (0, eval_vector_index_1.describeVectorIndex)(this.db);
202
116
  let outcome;
203
117
  try {
204
118
  outcome = await new retrieval_eval_1.RetrievalEvaluator().evaluate(suite, search, inspect, p => console.error((0, eval_results_1.renderProgress)(p)));
@@ -211,52 +125,16 @@ class EvalCommand {
211
125
  return;
212
126
  }
213
127
  const { run, observed } = outcome;
214
- const corpusRecords = [];
215
- for (const corpus of runCorpora) {
216
- const projects = [...projectDirs].filter(([, dir]) => dir !== null && (0, retrieval_eval_1.isUnderRoot)(dir, corpus.root)).map(([name]) => name).sort();
217
- const started = Date.now();
218
- const record = { ...corpus, projects, ...(await (0, eval_corpus_1.fingerprintCorpus)(db, projects)) };
219
- console.log(`Corpus ${corpus.root}: ${record.chunks} chunks in ${projects.length} project(s), fingerprint ${record.fingerprint} (${((Date.now() - started) / 1000).toFixed(1)}s)`);
220
- corpusRecords.push(record);
221
- }
222
- const indexMeta = await db.readIndexMeta();
223
- const metadata = {
224
- suitePath,
225
- suiteHash: hashContent(rawContent),
226
- embeddingProvider: config.embedding.provider,
227
- embeddingModel: config.embedding.model,
228
- rerankerModel: config.reranker.enabled ? config.reranker.model : null,
229
- indexMeta: indexMeta ? { provider: indexMeta.provider, model: indexMeta.model, dimensions: indexMeta.dimensions } : null,
230
- gitCommit: gitCommit(),
231
- timestamp: new Date().toISOString(),
232
- conditions: {
233
- similarityThreshold: config.search.similarityThreshold,
234
- overfetch: config.reranker.overfetch,
235
- candidateFloor: config.reranker.candidateFloor,
236
- fetchLimit: observed.fetchLimit,
237
- efSearch: observed.efSearch,
238
- iterativeScan: observed.iterativeScan,
239
- },
240
- corpora: corpusRecords,
241
- liveCases: suite.cases.filter(c => !c.corpus).length,
242
- };
128
+ const corpusRecords = await (0, eval_corpora_1.recordCorpora)(this.db, runCorpora, projectDirs);
129
+ const indexMeta = await this.db.readIndexMeta();
130
+ const metadata = (0, eval_metadata_1.buildResultMetadata)({
131
+ suitePath, rawContent, config: this.config, indexMeta, observed, vectorIndex, corpusRecords,
132
+ liveCases: suite.cases.filter(c => !c.corpus).length, projectRoot: _projectRoot,
133
+ });
243
134
  const resultFile = { metadata, run };
244
135
  for (const line of (0, eval_results_1.renderSummary)(resultFile))
245
136
  console.log(line);
246
- let comparison;
247
- if (baselinePath) {
248
- try {
249
- const baseline = (0, eval_results_1.readResultFile)(path.resolve(_projectRoot, baselinePath));
250
- const cmp = (0, retrieval_eval_1.compare)(baseline, resultFile);
251
- comparison = { baselinePath, result: cmp };
252
- for (const line of (0, eval_results_1.renderComparison)(baselinePath, cmp))
253
- console.log(line);
254
- }
255
- catch (err) {
256
- console.error(`\nFailed to read baseline '${baselinePath}': ${err.message}`);
257
- process.exitCode = 1;
258
- }
259
- }
137
+ const comparison = baselinePath ? (0, baseline_comparison_1.compareWithBaseline)(_projectRoot, baselinePath, resultFile) : undefined;
260
138
  const { jsonPath, mdPath } = (0, eval_results_1.writeResultFiles)(this.resultsDir, label, resultFile, new Date(), comparison);
261
139
  console.log(`\nResults written to:\n ${path.relative(_projectRoot, jsonPath)}\n ${path.relative(_projectRoot, mdPath)}`);
262
140
  }
@@ -1,9 +1,15 @@
1
- import type { Container } from '../container';
1
+ import type { IndexerService } from '../services/IndexerService';
2
+ import type { Config } from '../config';
3
+ import type { IDatabase, IDependencyGraph, IEmbedder, IProjectDiscovery } from '../interfaces';
2
4
  import type { ICommand } from './ICommand';
3
5
  export declare class IndexCommand implements ICommand {
4
- private container;
6
+ private db;
7
+ private embedder;
8
+ private indexer;
9
+ private dependencies;
10
+ private discovery;
11
+ private config;
5
12
  private argv1;
6
- constructor(container: Container, argv1: string);
13
+ constructor(db: IDatabase, embedder: IEmbedder, indexer: IndexerService, dependencies: IDependencyGraph, discovery: IProjectDiscovery, config: Config, argv1: string);
7
14
  execute(): Promise<void>;
8
- private printSummary;
9
15
  }
@@ -5,164 +5,92 @@ const interrupt_1 = require("../interrupt");
5
5
  const project_selector_1 = require("../project-selector");
6
6
  const graph_1 = require("../graph");
7
7
  const MonorepoAwareDiscoveryService_1 = require("../services/MonorepoAwareDiscoveryService");
8
- const project_scope_1 = require("../project-scope");
9
8
  const file_utils_1 = require("../file-utils");
10
- const legacy_ollama_index_1 = require("../services/legacy-ollama-index");
11
- function parseProjectFlag(args) {
12
- const i = args.indexOf('--project');
13
- if (i === -1)
14
- return { present: false };
15
- const next = args[i + 1];
16
- return next !== undefined && !next.startsWith('-') ? { present: true, name: next } : { present: true };
17
- }
9
+ const index_args_1 = require("../index-args");
10
+ const scan_targets_1 = require("./index/scan-targets");
11
+ const legacy_ollama_guard_1 = require("./index/legacy-ollama-guard");
12
+ const embedding_setup_1 = require("./index/embedding-setup");
13
+ const prune_step_1 = require("./index/prune-step");
14
+ const backend_probe_1 = require("./index/backend-probe");
15
+ const index_summary_1 = require("./index/index-summary");
18
16
  class IndexCommand {
19
- container;
17
+ db;
18
+ embedder;
19
+ indexer;
20
+ dependencies;
21
+ discovery;
22
+ config;
20
23
  argv1;
21
- constructor(container, argv1) {
22
- this.container = container;
24
+ constructor(db, embedder, indexer, dependencies, discovery, config, argv1) {
25
+ this.db = db;
26
+ this.embedder = embedder;
27
+ this.indexer = indexer;
28
+ this.dependencies = dependencies;
29
+ this.discovery = discovery;
30
+ this.config = config;
23
31
  this.argv1 = argv1;
24
32
  }
25
33
  async execute() {
26
- const { db, indexer, searcher, config, discovery, embedder } = this.container;
27
- const args = process.argv.slice(this.argv1 === 'rag-index' ? 2 : 3);
28
- const force = args.includes('--reindex');
29
- const forceSelect = args.includes('--select');
30
- const projectFlag = parseProjectFlag(args);
31
- let discovered;
32
- try {
33
- discovered = discovery.discover(config.workspaceRoot);
34
- }
35
- catch (err) {
36
- console.error(`\n${err.message}`);
37
- process.exitCode = 1;
34
+ const args = (0, index_args_1.parseIndexArgs)(process.argv.slice(this.argv1 === 'rag-index' ? 2 : 3));
35
+ const { force, forceSelect } = args;
36
+ const targets = await (0, scan_targets_1.resolveScanTargets)(this.discovery, this.config, args);
37
+ if (!targets)
38
+ return;
39
+ await this.db.initDbWithSchema();
40
+ if (!force && await (0, legacy_ollama_guard_1.refusesLegacyOllamaIndex)(this.db, this.config))
38
41
  return;
39
- }
40
- let scanTargets;
41
- if (projectFlag.present) {
42
- let name = projectFlag.name;
43
- if (name === undefined) {
44
- if (discovered.length === 0) {
45
- console.error('\nNo projects available to select.');
46
- process.exitCode = 1;
47
- return;
48
- }
49
- name = await (0, project_selector_1.selectSingleProject)(discovered);
50
- if (name === undefined) {
51
- process.exitCode = 1;
52
- return;
53
- }
54
- }
55
- const { targets, notFound } = (0, project_scope_1.resolveProjectNames)([name], discovered);
56
- if (notFound.length > 0) {
57
- const available = (0, project_scope_1.listAvailableNames)(discovered).join(', ');
58
- console.error(`\nProject '${notFound[0]}' not found. Available projects: ${available}`);
59
- process.exitCode = 1;
60
- return;
61
- }
62
- scanTargets = targets;
63
- }
64
- await db.initDbWithSchema();
65
- if (!force) {
66
- let identity;
67
- try {
68
- identity = await (0, legacy_ollama_index_1.resolveIndexedIdentity)(db);
69
- }
70
- catch (err) {
71
- console.error(`\n${err.message}`);
72
- process.exitCode = 1;
73
- return;
74
- }
75
- if (identity?.provider === 'ollama') {
76
- console.error(`\nThe existing index was built with ${identity.provider}/${identity.model}, but "ollama" is no ` +
77
- `longer a supported embedding provider (configured: ${config.embedding.provider}/${config.embedding.model}). ` +
78
- `Run \`rag-index --reindex\` to confirm rebuilding the index under the configured provider.`);
79
- process.exitCode = 1;
80
- return;
81
- }
82
- }
83
42
  let projects;
84
- if (scanTargets) {
85
- projects = scanTargets;
43
+ if (targets.scanTargets) {
44
+ projects = targets.scanTargets;
86
45
  }
87
46
  else {
88
- const selected = await new project_selector_1.ProjectSelector(config.workspaceRoot).select(discovered, forceSelect);
47
+ const selected = await new project_selector_1.ProjectSelector(this.config.workspaceRoot).select(targets.discovered, forceSelect);
89
48
  if (selected.length === 0)
90
49
  return;
91
50
  projects = (0, MonorepoAwareDiscoveryService_1.toLeafProjects)(selected);
92
51
  }
93
- const fullLeafProjects = (0, MonorepoAwareDiscoveryService_1.toLeafProjects)(discovered);
94
- try {
95
- await embedder.ensureModelAvailable?.();
96
- const meta = await indexer.prepareEmbeddingSchema();
97
- console.log(`Embedding: ${meta.provider} / ${meta.model} (${meta.dimensions} dims)`);
98
- }
99
- catch (err) {
100
- console.error(`\nEmbedding setup failed: ${err.message}`);
101
- process.exitCode = 1;
52
+ const fullLeafProjects = (0, MonorepoAwareDiscoveryService_1.toLeafProjects)(targets.discovered);
53
+ if (!await (0, embedding_setup_1.prepareEmbedding)(this.embedder, this.indexer))
102
54
  return;
103
- }
104
55
  const controller = new AbortController();
105
56
  const teardown = (0, interrupt_1.setupInterrupt)(controller);
106
57
  try {
107
- if (!scanTargets) {
108
- let pruneResult;
109
- try {
110
- pruneResult = await indexer.pruneProjects(projects.map(p => p.name));
111
- }
112
- catch (err) {
113
- console.error(`\nPruning failed: ${err.message}`);
114
- process.exitCode = 1;
115
- return;
116
- }
117
- const { removed, failed } = pruneResult;
118
- for (const name of removed) {
119
- console.log(`Removed project ${name} (not selected)`);
120
- }
121
- if (failed.length > 0) {
122
- process.exitCode = 1;
123
- }
124
- }
58
+ if (!targets.scanTargets && !await (0, prune_step_1.pruneUnselected)(this.indexer, projects))
59
+ return;
125
60
  const filesPerProject = projects.map(p => (0, file_utils_1.collectFiles)(p.path, (0, file_utils_1.loadIgnore)(p.path), p.path));
126
61
  const totalFiles = filesPerProject.reduce((sum, f) => sum + f.length, 0);
127
62
  console.log(`\n${projects.length} projects — ${totalFiles} files total`);
128
63
  if (force)
129
64
  console.log('Reindex mode: all files will be re-indexed.');
130
- const allStats = await indexer.scanProjects(projects, force, controller.signal, filesPerProject);
131
- if (controller.signal.aborted)
65
+ const allStats = await this.indexer.scanProjects(projects, force, controller.signal, filesPerProject);
66
+ const interrupted = controller.signal.aborted;
67
+ if (interrupted)
132
68
  console.log('\nIndexing interrupted.');
133
- this.printSummary(allStats);
134
- if (!controller.signal.aborted) {
69
+ (0, index_summary_1.printIndexSummary)(allStats);
70
+ const sum = (field) => allStats.reduce((total, s) => total + s[field], 0);
71
+ const failed = sum('failed');
72
+ const total = failed + sum('indexed') + sum('skipped');
73
+ if (failed > 0) {
74
+ console.error(`Indexing finished with ${failed} of ${total} file(s) failed.`);
75
+ }
76
+ if (!interrupted) {
135
77
  try {
136
- const projectEdges = await searcher.getProjectEdges();
137
- (0, graph_1.generateProjectGraph)(fullLeafProjects, projectEdges, config.workspaceRoot);
78
+ const projectEdges = await this.dependencies.getProjectEdges();
79
+ (0, graph_1.generateProjectGraph)(fullLeafProjects, projectEdges, this.config.workspaceRoot);
138
80
  }
139
81
  catch (err) {
140
82
  console.error(` ⚠ Could not build project graph: ${err.message}`);
141
83
  }
142
84
  }
85
+ if (failed > 0) {
86
+ const nothingUsable = sum('skipped') === 0 && sum('chunks') === 0;
87
+ const alreadyFailed = interrupted || !!process.exitCode || nothingUsable;
88
+ process.exitCode = alreadyFailed || !(await (0, backend_probe_1.isBackendAvailable)(this.db, this.embedder)) ? 1 : 2;
89
+ }
143
90
  }
144
91
  finally {
145
92
  teardown();
146
93
  }
147
94
  }
148
- printSummary(allStats) {
149
- const cols = { name: 30, num: 8 };
150
- const line = '─'.repeat(cols.name + cols.num * 5 + 5);
151
- console.log('\n=== Indexing Summary ===');
152
- console.log('Service'.padEnd(cols.name), 'Indexed'.padStart(cols.num), 'Skipped'.padStart(cols.num), 'Failed'.padStart(cols.num), 'Chunks'.padStart(cols.num), 'Time(s)'.padStart(cols.num));
153
- console.log(line);
154
- for (const s of allStats) {
155
- console.log(s.serviceName.padEnd(cols.name), String(s.indexed).padStart(cols.num), String(s.skipped).padStart(cols.num), String(s.failed).padStart(cols.num), String(s.chunks).padStart(cols.num), String(s.elapsedSec).padStart(cols.num));
156
- }
157
- console.log(line);
158
- const total = allStats.reduce((acc, s) => ({
159
- indexed: acc.indexed + s.indexed,
160
- skipped: acc.skipped + s.skipped,
161
- failed: acc.failed + s.failed,
162
- chunks: acc.chunks + s.chunks,
163
- elapsedSec: acc.elapsedSec + s.elapsedSec,
164
- }), { indexed: 0, skipped: 0, failed: 0, chunks: 0, elapsedSec: 0 });
165
- console.log('TOTAL'.padEnd(cols.name), String(total.indexed).padStart(cols.num), String(total.skipped).padStart(cols.num), String(total.failed).padStart(cols.num), String(total.chunks).padStart(cols.num), String(total.elapsedSec.toFixed(1)).padStart(cols.num));
166
- }
167
95
  }
168
96
  exports.IndexCommand = IndexCommand;