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.
- package/CHANGELOG.md +88 -5
- package/LICENSE +661 -21
- package/README.md +76 -40
- package/dist/app.js +17 -38
- package/dist/src/ast/CallExtractor.d.ts +8 -0
- package/dist/src/ast/CallExtractor.js +68 -0
- package/dist/src/ast/GraphqlNameExtractor.d.ts +22 -0
- package/dist/src/ast/GraphqlNameExtractor.js +240 -0
- package/dist/src/ast/ImportEdgeExtractor.d.ts +11 -0
- package/dist/src/ast/ImportEdgeExtractor.js +129 -0
- package/dist/src/ast/IndexedNodeResolver.d.ts +14 -0
- package/dist/src/ast/IndexedNodeResolver.js +217 -0
- package/dist/src/ast/MemberExtractor.d.ts +8 -0
- package/dist/src/ast/MemberExtractor.js +129 -0
- package/dist/src/ast/TopLevelSymbolExtractor.d.ts +5 -0
- package/dist/src/ast/TopLevelSymbolExtractor.js +86 -0
- package/dist/src/ast/graphql-grammar.d.ts +24 -0
- package/dist/src/ast/graphql-grammar.js +93 -0
- package/dist/src/ast/node-helpers.d.ts +11 -0
- package/dist/src/ast/node-helpers.js +55 -0
- package/dist/src/chunking/AstChunker.d.ts +12 -0
- package/dist/src/chunking/AstChunker.js +30 -0
- package/dist/src/chunking/CharacterChunkStrategy.d.ts +8 -0
- package/dist/src/chunking/CharacterChunkStrategy.js +15 -0
- package/dist/src/chunking/DeclarationChunkStrategy.d.ts +15 -0
- package/dist/src/chunking/DeclarationChunkStrategy.js +87 -0
- package/dist/src/chunking/FragmentMerger.d.ts +11 -0
- package/dist/src/chunking/FragmentMerger.js +61 -0
- package/dist/src/chunking/ImportOnlyFilter.d.ts +5 -0
- package/dist/src/chunking/ImportOnlyFilter.js +14 -0
- package/dist/src/chunking/LangchainTextSplitter.d.ts +21 -0
- package/dist/src/chunking/LangchainTextSplitter.js +133 -0
- package/dist/src/chunking/MinSizeSplitPolicy.d.ts +9 -0
- package/dist/src/chunking/MinSizeSplitPolicy.js +18 -0
- package/dist/src/chunking/RunPacker.d.ts +12 -0
- package/dist/src/chunking/RunPacker.js +84 -0
- package/dist/src/chunking/create-chunker.d.ts +3 -0
- package/dist/src/chunking/create-chunker.js +15 -0
- package/dist/src/chunking/interfaces.d.ts +27 -0
- package/dist/src/commands/ConfigCommand.js +1 -9
- package/dist/src/commands/EvalCommand.d.ts +10 -5
- package/dist/src/commands/EvalCommand.js +60 -149
- package/dist/src/commands/IndexCommand.d.ts +10 -4
- package/dist/src/commands/IndexCommand.js +52 -146
- package/dist/src/commands/McpCommand.d.ts +6 -3
- package/dist/src/commands/McpCommand.js +19 -20
- package/dist/src/commands/WebCommand.d.ts +9 -3
- package/dist/src/commands/WebCommand.js +17 -11
- package/dist/src/commands/eval/baseline-comparison.d.ts +6 -0
- package/dist/src/commands/eval/baseline-comparison.js +54 -0
- package/dist/src/commands/eval/eval-args.d.ts +6 -0
- package/dist/src/commands/eval/eval-args.js +71 -0
- package/dist/src/commands/eval/eval-corpora.d.ts +6 -0
- package/dist/src/commands/eval/eval-corpora.js +76 -0
- package/dist/src/commands/eval/eval-metadata.d.ts +17 -0
- package/dist/src/commands/eval/eval-metadata.js +75 -0
- package/dist/src/commands/eval/index-inspector.d.ts +3 -0
- package/dist/src/commands/eval/index-inspector.js +21 -0
- package/dist/src/commands/eval/staged-search.d.ts +3 -0
- package/dist/src/commands/eval/staged-search.js +20 -0
- package/dist/src/commands/eval/suite-loader.d.ts +8 -0
- package/dist/src/commands/eval/suite-loader.js +52 -0
- package/dist/src/commands/index/backend-probe.d.ts +2 -0
- package/dist/src/commands/index/backend-probe.js +15 -0
- package/dist/src/commands/index/embedding-setup.d.ts +3 -0
- package/dist/src/commands/index/embedding-setup.js +16 -0
- package/dist/src/commands/index/index-summary.d.ts +2 -0
- package/dist/src/commands/index/index-summary.js +22 -0
- package/dist/src/commands/index/legacy-ollama-guard.d.ts +3 -0
- package/dist/src/commands/index/legacy-ollama-guard.js +23 -0
- package/dist/src/commands/index/prune-step.d.ts +3 -0
- package/dist/src/commands/index/prune-step.js +22 -0
- package/dist/src/commands/index/scan-targets.d.ts +8 -0
- package/dist/src/commands/index/scan-targets.js +107 -0
- package/dist/src/config-error.d.ts +0 -4
- package/dist/src/config-error.js +0 -4
- package/dist/src/config-store.d.ts +1 -55
- package/dist/src/config-store.js +11 -73
- package/dist/src/config.d.ts +9 -18
- package/dist/src/config.js +36 -35
- package/dist/src/constants.d.ts +17 -28
- package/dist/src/constants.js +35 -29
- package/dist/src/container.d.ts +10 -2
- package/dist/src/container.js +19 -8
- package/dist/src/db/drizzle-types.d.ts +7 -0
- package/dist/src/db/drizzle-types.js +2 -0
- package/dist/src/db/index.d.ts +1 -0
- package/dist/src/db/schema-steps.d.ts +8 -0
- package/dist/src/db/schema-steps.js +105 -0
- package/dist/src/db/schema.d.ts +17 -0
- package/dist/src/db/schema.js +1 -6
- package/dist/src/declarations/DeclarationTree.d.ts +19 -0
- package/dist/src/declarations/DeclarationTree.js +66 -0
- package/dist/src/declarations/DeclarationTreeBuilder.d.ts +22 -0
- package/dist/src/declarations/DeclarationTreeBuilder.js +179 -0
- package/dist/src/declarations/SourceLines.d.ts +37 -0
- package/dist/src/declarations/SourceLines.js +415 -0
- package/dist/src/dependency-traversal.d.ts +0 -6
- package/dist/src/dependency-traversal.js +0 -6
- package/dist/src/enriched-prompt.d.ts +0 -6
- package/dist/src/enriched-prompt.js +0 -6
- package/dist/src/error-record.d.ts +12 -0
- package/dist/src/error-record.js +248 -0
- package/dist/src/eval-corpus.d.ts +16 -0
- package/dist/src/eval-corpus.js +169 -0
- package/dist/src/eval-results.d.ts +6 -3
- package/dist/src/eval-results.js +323 -26
- package/dist/src/eval-vector-index.d.ts +5 -0
- package/dist/src/eval-vector-index.js +60 -0
- package/dist/src/file-utils.d.ts +0 -5
- package/dist/src/file-utils.js +0 -5
- package/dist/src/graph.d.ts +0 -25
- package/dist/src/graph.js +0 -28
- package/dist/src/help.js +9 -1
- package/dist/src/hnsw-settings.d.ts +3 -0
- package/dist/src/hnsw-settings.js +24 -0
- package/dist/src/index-args.d.ts +13 -0
- package/dist/src/index-args.js +48 -0
- package/dist/src/indexing/AnalysisBatcher.d.ts +12 -0
- package/dist/src/indexing/AnalysisBatcher.js +28 -0
- package/dist/src/indexing/ChunkEmbedder.d.ts +24 -0
- package/dist/src/indexing/ChunkEmbedder.js +37 -0
- package/dist/src/indexing/ConsoleScanReporter.d.ts +10 -0
- package/dist/src/indexing/ConsoleScanReporter.js +73 -0
- package/dist/src/indexing/EmbeddingSchemaPreparer.d.ts +14 -0
- package/dist/src/indexing/EmbeddingSchemaPreparer.js +66 -0
- package/dist/src/indexing/FileIngestor.d.ts +22 -0
- package/dist/src/indexing/FileIngestor.js +116 -0
- package/dist/src/indexing/IndexStore.d.ts +24 -0
- package/dist/src/indexing/IndexStore.js +69 -0
- package/dist/src/indexing/StaleFilePruner.d.ts +8 -0
- package/dist/src/indexing/StaleFilePruner.js +55 -0
- package/dist/src/indexing/analysis-rows.d.ts +4 -0
- package/dist/src/indexing/analysis-rows.js +65 -0
- package/dist/src/indexing/project-notices.d.ts +2 -0
- package/dist/src/indexing/project-notices.js +63 -0
- package/dist/src/interfaces/IAstParser.d.ts +4 -40
- package/dist/src/interfaces/ICallGraph.d.ts +28 -0
- package/dist/src/interfaces/ICallGraph.js +2 -0
- package/dist/src/interfaces/IChunkSearch.d.ts +42 -0
- package/dist/src/interfaces/IChunkSearch.js +2 -0
- package/dist/src/interfaces/IChunker.d.ts +3 -12
- package/dist/src/interfaces/ICorpusInspector.d.ts +7 -0
- package/dist/src/interfaces/ICorpusInspector.js +2 -0
- package/dist/src/interfaces/IDatabase.d.ts +8 -24
- package/dist/src/interfaces/IDependencyGraph.d.ts +24 -0
- package/dist/src/interfaces/IDependencyGraph.js +2 -0
- package/dist/src/interfaces/IEmbedder.d.ts +0 -9
- package/dist/src/interfaces/IIndexIdentityGuard.d.ts +3 -0
- package/dist/src/interfaces/IIndexIdentityGuard.js +2 -0
- package/dist/src/interfaces/IIndexedNodeResolver.d.ts +10 -0
- package/dist/src/interfaces/IIndexedNodeResolver.js +2 -0
- package/dist/src/interfaces/ILogger.d.ts +1 -11
- package/dist/src/interfaces/IMcpReadiness.d.ts +12 -0
- package/dist/src/interfaces/IMcpReadiness.js +2 -0
- package/dist/src/interfaces/IMcpToolHandler.d.ts +0 -5
- package/dist/src/interfaces/IMonorepoResolver.d.ts +0 -22
- package/dist/src/interfaces/IProjectCatalog.d.ts +13 -0
- package/dist/src/interfaces/IProjectCatalog.js +2 -0
- package/dist/src/interfaces/IProjectDiscovery.d.ts +0 -17
- package/dist/src/interfaces/IProjectRoots.d.ts +3 -0
- package/dist/src/interfaces/IProjectRoots.js +2 -0
- package/dist/src/interfaces/IRetrievalEvaluator.d.ts +153 -12
- package/dist/src/interfaces/IScanReporter.d.ts +13 -0
- package/dist/src/interfaces/IScanReporter.js +2 -0
- package/dist/src/interfaces/ISymbolLookup.d.ts +49 -0
- package/dist/src/interfaces/ISymbolLookup.js +2 -0
- package/dist/src/interfaces/IToolPaths.d.ts +62 -0
- package/dist/src/interfaces/IToolPaths.js +2 -0
- package/dist/src/interfaces/IWorkspaceFiles.d.ts +28 -0
- package/dist/src/interfaces/IWorkspaceFiles.js +2 -0
- package/dist/src/interfaces/SymbolKind.d.ts +1 -0
- package/dist/src/interfaces/SymbolKind.js +2 -0
- package/dist/src/interfaces/index.d.ts +12 -1
- package/dist/src/interrupt.js +0 -2
- package/dist/src/owner-path.d.ts +9 -10
- package/dist/src/owner-path.js +11 -23
- package/dist/src/project-scope.d.ts +1 -12
- package/dist/src/project-scope.js +5 -12
- package/dist/src/project-selector.d.ts +0 -5
- package/dist/src/project-selector.js +0 -11
- package/dist/src/retrieval-eval.d.ts +15 -6
- package/dist/src/retrieval-eval.js +388 -59
- package/dist/src/search/CallGraph.d.ts +9 -0
- package/dist/src/search/CallGraph.js +84 -0
- package/dist/src/search/ChunkSearch.d.ts +23 -0
- package/dist/src/search/ChunkSearch.js +115 -0
- package/dist/src/search/DependencyGraph.d.ts +19 -0
- package/dist/src/search/DependencyGraph.js +180 -0
- package/dist/src/search/IndexIdentityGuard.d.ts +11 -0
- package/dist/src/search/IndexIdentityGuard.js +37 -0
- package/dist/src/search/ProjectCatalog.d.ts +11 -0
- package/dist/src/search/ProjectCatalog.js +38 -0
- package/dist/src/search/SymbolLookup.d.ts +24 -0
- package/dist/src/search/SymbolLookup.js +97 -0
- package/dist/src/search/chunks/CandidateFetcher.d.ts +19 -0
- package/dist/src/search/chunks/CandidateFetcher.js +40 -0
- package/dist/src/search/chunks/IterativeScanGate.d.ts +10 -0
- package/dist/src/search/chunks/IterativeScanGate.js +42 -0
- package/dist/src/search/chunks/RerankStage.d.ts +15 -0
- package/dist/src/search/chunks/RerankStage.js +42 -0
- package/dist/src/search/chunks/search-metrics.d.ts +18 -0
- package/dist/src/search/chunks/search-metrics.js +32 -0
- package/dist/src/search/chunks/search-plan.d.ts +18 -0
- package/dist/src/search/chunks/search-plan.js +19 -0
- package/dist/src/search/create-search-services.d.ts +26 -0
- package/dist/src/search/create-search-services.js +29 -0
- package/dist/src/search/index-paths.d.ts +1 -0
- package/dist/src/search/index-paths.js +5 -0
- package/dist/src/search/result-shaping.d.ts +4 -0
- package/dist/src/search/result-shaping.js +19 -0
- package/dist/src/search/symbol-sql.d.ts +13 -0
- package/dist/src/search/symbol-sql.js +66 -0
- package/dist/src/search/symbols/SymbolGrepFallback.d.ts +19 -0
- package/dist/src/search/symbols/SymbolGrepFallback.js +106 -0
- package/dist/src/search/symbols/SymbolIndexQuery.d.ts +14 -0
- package/dist/src/search/symbols/SymbolIndexQuery.js +52 -0
- package/dist/src/search/symbols/SymbolTextSearch.d.ts +13 -0
- package/dist/src/search/symbols/SymbolTextSearch.js +84 -0
- package/dist/src/search/symbols/TargetColumnGate.d.ts +7 -0
- package/dist/src/search/symbols/TargetColumnGate.js +23 -0
- package/dist/src/search/symbols/find-symbol-constants.d.ts +4 -0
- package/dist/src/search/symbols/find-symbol-constants.js +8 -0
- package/dist/src/search/symbols/grep-args.d.ts +3 -0
- package/dist/src/search/symbols/grep-args.js +7 -0
- package/dist/src/search/symbols/grep-patterns.d.ts +4 -0
- package/dist/src/search/symbols/grep-patterns.js +60 -0
- package/dist/src/services/AstParserService.d.ts +10 -106
- package/dist/src/services/AstParserService.js +37 -1068
- package/dist/src/services/DatabaseService.d.ts +10 -17
- package/dist/src/services/DatabaseService.js +71 -115
- package/dist/src/services/EmbedderFactory.d.ts +0 -4
- package/dist/src/services/EmbedderFactory.js +0 -5
- package/dist/src/services/IndexerService.d.ts +7 -26
- package/dist/src/services/IndexerService.js +38 -286
- package/dist/src/services/InfinityEmbedder.d.ts +0 -21
- package/dist/src/services/InfinityEmbedder.js +0 -15
- package/dist/src/services/LoggerService.d.ts +7 -5
- package/dist/src/services/LoggerService.js +37 -41
- package/dist/src/services/McpReadiness.d.ts +18 -0
- package/dist/src/services/McpReadiness.js +73 -0
- package/dist/src/services/McpServer.d.ts +50 -19
- package/dist/src/services/McpServer.js +132 -62
- package/dist/src/services/MonorepoAwareDiscoveryService.d.ts +1 -45
- package/dist/src/services/MonorepoAwareDiscoveryService.js +1 -51
- package/dist/src/services/NxMonorepoResolver.d.ts +0 -29
- package/dist/src/services/NxMonorepoResolver.js +5 -56
- package/dist/src/services/OpenAICompatibleEmbedder.d.ts +0 -6
- package/dist/src/services/OpenAICompatibleEmbedder.js +0 -14
- package/dist/src/services/ProjectDiscoveryService.d.ts +0 -4
- package/dist/src/services/ProjectDiscoveryService.js +0 -4
- package/dist/src/services/VoyageEmbedder.d.ts +0 -6
- package/dist/src/services/VoyageEmbedder.js +0 -6
- package/dist/src/services/WebServerService.d.ts +5 -56
- package/dist/src/services/WebServerService.js +25 -63
- package/dist/src/services/http-retry.d.ts +0 -7
- package/dist/src/services/http-retry.js +1 -10
- package/dist/src/services/infinity-provisioning.d.ts +0 -74
- package/dist/src/services/infinity-provisioning.js +5 -88
- package/dist/src/services/legacy-ollama-index.d.ts +0 -16
- package/dist/src/services/legacy-ollama-index.js +0 -23
- package/dist/src/services/reranker.d.ts +0 -9
- package/dist/src/services/reranker.js +46 -12
- package/dist/src/setup.d.ts +24 -24
- package/dist/src/setup.js +205 -103
- package/dist/src/symbol-name.d.ts +1 -12
- package/dist/src/symbol-name.js +16 -25
- package/dist/src/symbol-rows.d.ts +0 -14
- package/dist/src/symbol-rows.js +0 -14
- package/dist/src/tool-call-log.d.ts +2 -0
- package/dist/src/tool-call-log.js +24 -0
- package/dist/src/tools/FindSymbolTool.d.ts +17 -7
- package/dist/src/tools/FindSymbolTool.js +54 -35
- package/dist/src/tools/GetCallersTool.d.ts +16 -8
- package/dist/src/tools/GetCallersTool.js +65 -35
- package/dist/src/tools/GetDependenciesTool.d.ts +16 -8
- package/dist/src/tools/GetDependenciesTool.js +36 -29
- package/dist/src/tools/GetDependentsTool.d.ts +20 -8
- package/dist/src/tools/GetDependentsTool.js +48 -34
- package/dist/src/tools/ListFilesTool.d.ts +16 -8
- package/dist/src/tools/ListFilesTool.js +20 -26
- package/dist/src/tools/ListProjectsTool.d.ts +11 -7
- package/dist/src/tools/ListProjectsTool.js +13 -11
- package/dist/src/tools/McpTool.d.ts +17 -0
- package/dist/src/tools/McpTool.js +28 -0
- package/dist/src/tools/ReadFileRangeTool.d.ts +16 -8
- package/dist/src/tools/ReadFileRangeTool.js +23 -25
- package/dist/src/tools/ReadFileTool.d.ts +15 -8
- package/dist/src/tools/ReadFileTool.js +19 -24
- package/dist/src/tools/SearchCodebaseTool.d.ts +22 -10
- package/dist/src/tools/SearchCodebaseTool.js +71 -50
- package/dist/src/tools/format-helpers.d.ts +9 -9
- package/dist/src/tools/format-helpers.js +146 -28
- package/dist/src/tools/tool-args.d.ts +38 -0
- package/dist/src/tools/tool-args.js +95 -0
- package/dist/src/web/dashboard.d.ts +0 -8
- package/dist/src/web/dashboard.js +7 -10
- package/dist/src/workspace/GrepRunner.d.ts +15 -0
- package/dist/src/workspace/GrepRunner.js +104 -0
- package/dist/src/workspace/ProjectRoots.d.ts +22 -0
- package/dist/src/workspace/ProjectRoots.js +102 -0
- package/dist/src/workspace/ToolPaths.d.ts +31 -0
- package/dist/src/workspace/ToolPaths.js +312 -0
- package/dist/src/workspace/WorkspaceFiles.d.ts +19 -0
- package/dist/src/workspace/WorkspaceFiles.js +285 -0
- package/dist/src/workspace/fs-access.d.ts +9 -0
- package/dist/src/workspace/fs-access.js +47 -0
- package/dist/src/workspace/path-helpers.d.ts +3 -0
- package/dist/src/workspace/path-helpers.js +43 -0
- package/package.json +5 -4
- package/dist/src/interfaces/ISearcher.d.ts +0 -35
- package/dist/src/services/AstChunker.d.ts +0 -42
- package/dist/src/services/AstChunker.js +0 -158
- package/dist/src/services/SearcherService.d.ts +0 -342
- package/dist/src/services/SearcherService.js +0 -1199
- package/docs/web-dashboard.md +0 -206
- /package/dist/src/{interfaces/ISearcher.js → chunking/interfaces.js} +0 -0
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ImportOnlyFilter = void 0;
|
|
4
|
+
class ImportOnlyFilter {
|
|
5
|
+
process(pieces, ctx) {
|
|
6
|
+
return pieces.filter((p) => {
|
|
7
|
+
if (!ctx.lines.isImportOnly(p.startLine, p.endLine))
|
|
8
|
+
return true;
|
|
9
|
+
ctx.removed.push({ start: p.startLine, end: p.endLine });
|
|
10
|
+
return false;
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
exports.ImportOnlyFilter = ImportOnlyFilter;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Config } from '../config';
|
|
2
|
+
import type { ChunkPiece } from '../interfaces/IChunker';
|
|
3
|
+
import type { ITextSplitter, KeepWindow } from './interfaces';
|
|
4
|
+
export interface SplitterOptions {
|
|
5
|
+
chunkSize: number;
|
|
6
|
+
chunkOverlap: number;
|
|
7
|
+
separators: string[];
|
|
8
|
+
}
|
|
9
|
+
export declare class LangchainTextSplitter implements ITextSplitter {
|
|
10
|
+
private readonly opts;
|
|
11
|
+
constructor(opts: SplitterOptions);
|
|
12
|
+
static forJs(config: Config): LangchainTextSplitter;
|
|
13
|
+
static forSchema(config: Config): LangchainTextSplitter;
|
|
14
|
+
split(text: string, firstLine: number, keep?: KeepWindow): Promise<ChunkPiece[]>;
|
|
15
|
+
private splitSpan;
|
|
16
|
+
private static splitOn;
|
|
17
|
+
private static joinKept;
|
|
18
|
+
private merge;
|
|
19
|
+
private static trim;
|
|
20
|
+
private static newlines;
|
|
21
|
+
}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.LangchainTextSplitter = void 0;
|
|
4
|
+
const textsplitters_1 = require("@langchain/textsplitters");
|
|
5
|
+
class LangchainTextSplitter {
|
|
6
|
+
opts;
|
|
7
|
+
constructor(opts) {
|
|
8
|
+
this.opts = opts;
|
|
9
|
+
if (opts.chunkOverlap >= opts.chunkSize)
|
|
10
|
+
throw new Error('Cannot have chunkOverlap >= chunkSize');
|
|
11
|
+
}
|
|
12
|
+
static forJs(config) {
|
|
13
|
+
return new LangchainTextSplitter({
|
|
14
|
+
chunkSize: config.indexer.chunkSize,
|
|
15
|
+
chunkOverlap: config.indexer.chunkOverlap,
|
|
16
|
+
separators: textsplitters_1.RecursiveCharacterTextSplitter.getSeparatorsForLanguage('js'),
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
static forSchema(config) {
|
|
20
|
+
return new LangchainTextSplitter({
|
|
21
|
+
chunkSize: config.indexer.chunkSize,
|
|
22
|
+
chunkOverlap: config.indexer.chunkOverlap,
|
|
23
|
+
separators: ['\n\n', '\n', ' '],
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
async split(text, firstLine, keep = { from: 0, to: 0 }) {
|
|
27
|
+
const pieces = [];
|
|
28
|
+
let offset = 0;
|
|
29
|
+
let line = firstLine;
|
|
30
|
+
for (const span of this.splitSpan(text, { start: 0, end: text.length }, this.opts.separators, keep)) {
|
|
31
|
+
line += LangchainTextSplitter.newlines(text, offset, span.start);
|
|
32
|
+
offset = span.start;
|
|
33
|
+
const content = text.slice(span.start, span.end);
|
|
34
|
+
pieces.push({ content, startLine: line, endLine: line + LangchainTextSplitter.newlines(content, 0, content.length) });
|
|
35
|
+
}
|
|
36
|
+
return pieces;
|
|
37
|
+
}
|
|
38
|
+
splitSpan(text, span, separators, keep) {
|
|
39
|
+
const sub = text.slice(span.start, span.end);
|
|
40
|
+
let separator = separators[separators.length - 1];
|
|
41
|
+
let next;
|
|
42
|
+
for (let i = 0; i < separators.length; i++) {
|
|
43
|
+
if (separators[i] === '') {
|
|
44
|
+
separator = '';
|
|
45
|
+
break;
|
|
46
|
+
}
|
|
47
|
+
if (sub.includes(separators[i])) {
|
|
48
|
+
separator = separators[i];
|
|
49
|
+
next = separators.slice(i + 1);
|
|
50
|
+
break;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
const out = [];
|
|
54
|
+
let good = [];
|
|
55
|
+
const splits = LangchainTextSplitter.splitOn(sub, separator, span.start);
|
|
56
|
+
for (const s of separator ? LangchainTextSplitter.joinKept(splits, keep) : splits) {
|
|
57
|
+
if (s.end - s.start < this.opts.chunkSize) {
|
|
58
|
+
good.push(s);
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
if (good.length) {
|
|
62
|
+
out.push(...this.merge(text, good));
|
|
63
|
+
good = [];
|
|
64
|
+
}
|
|
65
|
+
out.push(...(next ? this.splitSpan(text, s, next, keep) : [s]));
|
|
66
|
+
}
|
|
67
|
+
if (good.length)
|
|
68
|
+
out.push(...this.merge(text, good));
|
|
69
|
+
return out;
|
|
70
|
+
}
|
|
71
|
+
static splitOn(sub, separator, base) {
|
|
72
|
+
const parts = separator
|
|
73
|
+
? sub.split(new RegExp(`(?=${separator.replace(/[/\-\\^$*+?.()|[\]{}]/g, '\\$&')})`))
|
|
74
|
+
: sub.split('');
|
|
75
|
+
const spans = [];
|
|
76
|
+
let at = base;
|
|
77
|
+
for (const p of parts) {
|
|
78
|
+
if (p !== '')
|
|
79
|
+
spans.push({ start: at, end: at + p.length });
|
|
80
|
+
at += p.length;
|
|
81
|
+
}
|
|
82
|
+
return spans;
|
|
83
|
+
}
|
|
84
|
+
static joinKept(splits, keep) {
|
|
85
|
+
const out = [];
|
|
86
|
+
for (const s of splits) {
|
|
87
|
+
if (out.length && s.start > keep.from && s.start <= keep.to)
|
|
88
|
+
out[out.length - 1] = { start: out[out.length - 1].start, end: s.end };
|
|
89
|
+
else
|
|
90
|
+
out.push(s);
|
|
91
|
+
}
|
|
92
|
+
return out;
|
|
93
|
+
}
|
|
94
|
+
merge(text, splits) {
|
|
95
|
+
const { chunkSize, chunkOverlap } = this.opts;
|
|
96
|
+
const docs = [];
|
|
97
|
+
const current = [];
|
|
98
|
+
let total = 0;
|
|
99
|
+
const flush = () => {
|
|
100
|
+
const doc = LangchainTextSplitter.trim(text, { start: current[0].start, end: current[current.length - 1].end });
|
|
101
|
+
if (doc)
|
|
102
|
+
docs.push(doc);
|
|
103
|
+
};
|
|
104
|
+
for (const d of splits) {
|
|
105
|
+
const len = d.end - d.start;
|
|
106
|
+
if (total + len > chunkSize && current.length > 0) {
|
|
107
|
+
flush();
|
|
108
|
+
while (total > chunkOverlap || (total + len > chunkSize && total > 0)) {
|
|
109
|
+
total -= current[0].end - current[0].start;
|
|
110
|
+
current.shift();
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
current.push(d);
|
|
114
|
+
total += len;
|
|
115
|
+
}
|
|
116
|
+
if (current.length > 0)
|
|
117
|
+
flush();
|
|
118
|
+
return docs;
|
|
119
|
+
}
|
|
120
|
+
static trim(text, span) {
|
|
121
|
+
let { start, end } = span;
|
|
122
|
+
while (start < end && /\s/.test(text[start]))
|
|
123
|
+
start++;
|
|
124
|
+
while (end > start && /\s/.test(text[end - 1]))
|
|
125
|
+
end--;
|
|
126
|
+
return start < end ? { start, end } : null;
|
|
127
|
+
}
|
|
128
|
+
static newlines(text, from, to) {
|
|
129
|
+
const count = (a, b) => (text.slice(a, b).match(/\n/g) ?? []).length;
|
|
130
|
+
return to >= from ? count(from, to) : -count(to, from);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
exports.LangchainTextSplitter = LangchainTextSplitter;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { DeclarationNode } from '../declarations/DeclarationTree';
|
|
2
|
+
import type { SourceLines } from '../declarations/SourceLines';
|
|
3
|
+
import type { ISplitPolicy } from './interfaces';
|
|
4
|
+
export declare const MIN_MEMBER_CHARS = 200;
|
|
5
|
+
export declare class MinSizeSplitPolicy implements ISplitPolicy {
|
|
6
|
+
private readonly minChars;
|
|
7
|
+
constructor(minChars?: number);
|
|
8
|
+
isSplitPoint(child: DeclarationNode, siblings: DeclarationNode[], parent: DeclarationNode | null, lines: SourceLines): boolean;
|
|
9
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MinSizeSplitPolicy = exports.MIN_MEMBER_CHARS = void 0;
|
|
4
|
+
exports.MIN_MEMBER_CHARS = 200;
|
|
5
|
+
class MinSizeSplitPolicy {
|
|
6
|
+
minChars;
|
|
7
|
+
constructor(minChars = exports.MIN_MEMBER_CHARS) {
|
|
8
|
+
this.minChars = minChars;
|
|
9
|
+
}
|
|
10
|
+
isSplitPoint(child, siblings, parent, lines) {
|
|
11
|
+
if (lines.length(child.start, child.end) < this.minChars)
|
|
12
|
+
return false;
|
|
13
|
+
if (parent && (child.start <= parent.nameLine || child.end >= parent.end))
|
|
14
|
+
return false;
|
|
15
|
+
return !siblings.some(s => s !== child && s.start <= child.end && child.start <= s.end);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
exports.MinSizeSplitPolicy = MinSizeSplitPolicy;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ChunkPiece } from '../interfaces/IChunker';
|
|
2
|
+
import type { DeclarationNode } from '../declarations/DeclarationTree';
|
|
3
|
+
import type { LineRange, SourceLines } from '../declarations/SourceLines';
|
|
4
|
+
import type { ITextSplitter } from './interfaces';
|
|
5
|
+
export declare class RunPacker {
|
|
6
|
+
private readonly splitter;
|
|
7
|
+
constructor(splitter: ITextSplitter);
|
|
8
|
+
pack(run: LineRange, children: DeclarationNode[], lines: SourceLines, chunkSize: number, characterSplit?: LineRange[], owner?: DeclarationNode | null): Promise<ChunkPiece[]>;
|
|
9
|
+
private static leadWindow;
|
|
10
|
+
static units(run: LineRange, children: DeclarationNode[]): LineRange[];
|
|
11
|
+
static piece(range: LineRange, lines: SourceLines): ChunkPiece[];
|
|
12
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.RunPacker = void 0;
|
|
4
|
+
class RunPacker {
|
|
5
|
+
splitter;
|
|
6
|
+
constructor(splitter) {
|
|
7
|
+
this.splitter = splitter;
|
|
8
|
+
}
|
|
9
|
+
async pack(run, children, lines, chunkSize, characterSplit = [], owner = null) {
|
|
10
|
+
const pieces = [];
|
|
11
|
+
let current = null;
|
|
12
|
+
const flush = () => {
|
|
13
|
+
if (current)
|
|
14
|
+
pieces.push(...RunPacker.piece(current, lines));
|
|
15
|
+
current = null;
|
|
16
|
+
};
|
|
17
|
+
for (const unit of RunPacker.units(run, children)) {
|
|
18
|
+
if (lines.length(unit.start, unit.end) > chunkSize) {
|
|
19
|
+
flush();
|
|
20
|
+
characterSplit.push(unit);
|
|
21
|
+
const keep = RunPacker.leadWindow(unit, [owner, ...children], lines, chunkSize);
|
|
22
|
+
pieces.push(...await this.splitter.split(lines.slice(unit.start, unit.end), unit.start, keep));
|
|
23
|
+
continue;
|
|
24
|
+
}
|
|
25
|
+
if (current && lines.length(current.start, unit.end) <= chunkSize) {
|
|
26
|
+
current.end = unit.end;
|
|
27
|
+
continue;
|
|
28
|
+
}
|
|
29
|
+
flush();
|
|
30
|
+
current = { ...unit };
|
|
31
|
+
}
|
|
32
|
+
flush();
|
|
33
|
+
return pieces;
|
|
34
|
+
}
|
|
35
|
+
static leadWindow(unit, nodes, lines, chunkSize) {
|
|
36
|
+
const lead = nodes.find(n => n !== null && n.start === unit.start && n.nameLine > unit.start);
|
|
37
|
+
if (!lead)
|
|
38
|
+
return undefined;
|
|
39
|
+
const to = lines.length(unit.start, lead.nameLine - 1);
|
|
40
|
+
if (lines.length(unit.start, lead.nameLine) < chunkSize)
|
|
41
|
+
return { from: 0, to };
|
|
42
|
+
let first = unit.start;
|
|
43
|
+
while (first < lead.nameLine && (lines.isBlank(first) || lines.isCommentOnly(first)))
|
|
44
|
+
first++;
|
|
45
|
+
if (first === lead.nameLine || 1 + lines.length(first, lead.nameLine) >= chunkSize)
|
|
46
|
+
return undefined;
|
|
47
|
+
return { from: lines.length(unit.start, first - 1), to };
|
|
48
|
+
}
|
|
49
|
+
static units(run, children) {
|
|
50
|
+
const inside = children
|
|
51
|
+
.filter(c => c.end >= run.start && c.start <= run.end)
|
|
52
|
+
.sort((a, b) => a.start - b.start);
|
|
53
|
+
const units = [];
|
|
54
|
+
let cursor = run.start;
|
|
55
|
+
for (let i = 0; i < inside.length;) {
|
|
56
|
+
const start = Math.max(inside[i].start, run.start);
|
|
57
|
+
let end = Math.min(inside[i].end, run.end);
|
|
58
|
+
let j = i + 1;
|
|
59
|
+
while (j < inside.length && inside[j].start <= end) {
|
|
60
|
+
end = Math.min(Math.max(end, inside[j].end), run.end);
|
|
61
|
+
j++;
|
|
62
|
+
}
|
|
63
|
+
if (cursor < start)
|
|
64
|
+
units.push({ start: cursor, end: start - 1 });
|
|
65
|
+
units.push({ start, end });
|
|
66
|
+
cursor = end + 1;
|
|
67
|
+
i = j;
|
|
68
|
+
}
|
|
69
|
+
if (cursor <= run.end)
|
|
70
|
+
units.push({ start: cursor, end: run.end });
|
|
71
|
+
return units;
|
|
72
|
+
}
|
|
73
|
+
static piece(range, lines) {
|
|
74
|
+
let { start, end } = range;
|
|
75
|
+
while (start <= end && lines.isBlank(start))
|
|
76
|
+
start++;
|
|
77
|
+
while (end >= start && lines.isBlank(end))
|
|
78
|
+
end--;
|
|
79
|
+
if (start > end)
|
|
80
|
+
return [];
|
|
81
|
+
return [{ content: lines.slice(start, end), startLine: start, endLine: end }];
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
exports.RunPacker = RunPacker;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createChunker = createChunker;
|
|
4
|
+
const AstChunker_1 = require("./AstChunker");
|
|
5
|
+
const CharacterChunkStrategy_1 = require("./CharacterChunkStrategy");
|
|
6
|
+
const DeclarationChunkStrategy_1 = require("./DeclarationChunkStrategy");
|
|
7
|
+
const FragmentMerger_1 = require("./FragmentMerger");
|
|
8
|
+
const ImportOnlyFilter_1 = require("./ImportOnlyFilter");
|
|
9
|
+
const LangchainTextSplitter_1 = require("./LangchainTextSplitter");
|
|
10
|
+
const MinSizeSplitPolicy_1 = require("./MinSizeSplitPolicy");
|
|
11
|
+
const RunPacker_1 = require("./RunPacker");
|
|
12
|
+
function createChunker(config) {
|
|
13
|
+
const jsSplitter = LangchainTextSplitter_1.LangchainTextSplitter.forJs(config);
|
|
14
|
+
return new AstChunker_1.AstChunker(new DeclarationChunkStrategy_1.DeclarationChunkStrategy(new MinSizeSplitPolicy_1.MinSizeSplitPolicy(), new RunPacker_1.RunPacker(jsSplitter)), new CharacterChunkStrategy_1.CharacterChunkStrategy(jsSplitter, LangchainTextSplitter_1.LangchainTextSplitter.forSchema(config)), [new ImportOnlyFilter_1.ImportOnlyFilter()], [new FragmentMerger_1.FragmentMerger()], config);
|
|
15
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { ChunkOpts, ChunkPiece } from '../interfaces/IChunker';
|
|
2
|
+
import type { DeclarationNode, DeclarationTree } from '../declarations/DeclarationTree';
|
|
3
|
+
import type { LineRange, SourceLines } from '../declarations/SourceLines';
|
|
4
|
+
export interface ChunkContext {
|
|
5
|
+
lines: SourceLines;
|
|
6
|
+
declarations: DeclarationTree;
|
|
7
|
+
chunkSize: number;
|
|
8
|
+
removed: LineRange[];
|
|
9
|
+
splitPoints: LineRange[];
|
|
10
|
+
characterSplit: LineRange[];
|
|
11
|
+
}
|
|
12
|
+
export interface IChunkStrategy {
|
|
13
|
+
chunk(ctx: ChunkContext, opts: ChunkOpts): Promise<ChunkPiece[]>;
|
|
14
|
+
}
|
|
15
|
+
export interface ISplitPolicy {
|
|
16
|
+
isSplitPoint(child: DeclarationNode, siblings: DeclarationNode[], parent: DeclarationNode | null, lines: SourceLines): boolean;
|
|
17
|
+
}
|
|
18
|
+
export interface KeepWindow {
|
|
19
|
+
from: number;
|
|
20
|
+
to: number;
|
|
21
|
+
}
|
|
22
|
+
export interface ITextSplitter {
|
|
23
|
+
split(text: string, firstLine: number, keep?: KeepWindow): Promise<ChunkPiece[]>;
|
|
24
|
+
}
|
|
25
|
+
export interface IChunkPostProcessor {
|
|
26
|
+
process(pieces: ChunkPiece[], ctx: ChunkContext): ChunkPiece[];
|
|
27
|
+
}
|
|
@@ -72,7 +72,6 @@ class ConfigCommand {
|
|
|
72
72
|
console.log(`No config found at ${config_store_1.CONFIG_FILE}. Run rag-setup.`);
|
|
73
73
|
return;
|
|
74
74
|
}
|
|
75
|
-
// redact password for display
|
|
76
75
|
const display = JSON.parse(JSON.stringify(cfg));
|
|
77
76
|
if (display.db?.password !== undefined)
|
|
78
77
|
display.db.password = '***';
|
|
@@ -131,24 +130,18 @@ class ConfigCommand {
|
|
|
131
130
|
}
|
|
132
131
|
}
|
|
133
132
|
edit() {
|
|
134
|
-
// Ensure config + schema exist so the editor has something to open and
|
|
135
|
-
// resolve the schema against.
|
|
136
133
|
try {
|
|
137
134
|
if (!fs.existsSync(config_store_1.CONFIG_FILE)) {
|
|
138
135
|
(0, config_store_1.writeConfigJson)({});
|
|
139
136
|
}
|
|
140
137
|
else {
|
|
141
138
|
(0, config_store_1.writeSchemaFile)();
|
|
142
|
-
// Migrate existing configs: re-add the "$schema" reference if absent
|
|
143
|
-
// (rewrite through writeConfigJson) so editors bind to the schema.
|
|
144
|
-
// Skip silently if the file is currently invalid — the user will fix
|
|
145
|
-
// it in the editor and validation runs on save.
|
|
146
139
|
try {
|
|
147
140
|
const cfg = (0, config_store_1.readConfigJson)();
|
|
148
141
|
if (cfg)
|
|
149
142
|
(0, config_store_1.writeConfigJson)(cfg);
|
|
150
143
|
}
|
|
151
|
-
catch {
|
|
144
|
+
catch { }
|
|
152
145
|
}
|
|
153
146
|
}
|
|
154
147
|
catch (e) {
|
|
@@ -164,7 +157,6 @@ class ConfigCommand {
|
|
|
164
157
|
console.error('Set $EDITOR or edit the file directly: ' + config_store_1.CONFIG_FILE);
|
|
165
158
|
process.exit(1);
|
|
166
159
|
}
|
|
167
|
-
// Validate what the user saved; readConfigJson throws with a helpful message.
|
|
168
160
|
try {
|
|
169
161
|
(0, config_store_1.readConfigJson)();
|
|
170
162
|
console.log('Config OK');
|
|
@@ -1,10 +1,15 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { Config } from '../config';
|
|
2
|
+
import type { IDatabase, IChunkSearch, IProjectCatalog } from '../interfaces';
|
|
2
3
|
import type { ICommand } from './ICommand';
|
|
4
|
+
import type { ICorpusInspector } from '../interfaces/ICorpusInspector';
|
|
3
5
|
export declare class EvalCommand implements ICommand {
|
|
4
|
-
private
|
|
6
|
+
private db;
|
|
7
|
+
private chunks;
|
|
8
|
+
private catalog;
|
|
9
|
+
private config;
|
|
5
10
|
private argv1;
|
|
6
|
-
|
|
11
|
+
private corpusInspector;
|
|
12
|
+
private resultsDir;
|
|
13
|
+
constructor(db: IDatabase, chunks: IChunkSearch, catalog: IProjectCatalog, config: Config, argv1: string, corpusInspector?: ICorpusInspector, resultsDir?: string);
|
|
7
14
|
execute(): Promise<void>;
|
|
8
|
-
private printSummary;
|
|
9
|
-
private printComparison;
|
|
10
15
|
}
|
|
@@ -36,93 +36,53 @@ 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
|
-
const
|
|
41
|
+
const eval_corpus_1 = require("../eval-corpus");
|
|
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");
|
|
44
51
|
const RESULTS_DIR_NAME = path.join('benchmarks', 'results');
|
|
45
|
-
// Resolves to the repo root in both `ts-node app.ts` (one level above `src/`) and
|
|
46
|
-
// the compiled `dist/` layout (two levels above `dist/src/commands/`).
|
|
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
|
-
/** `--suite <path>` — a file or a directory of `*.json` suite files (default: `benchmarks/eval/`). */
|
|
62
|
-
function parseSuiteFlag(args) {
|
|
63
|
-
const i = args.indexOf('--suite');
|
|
64
|
-
if (i === -1)
|
|
65
|
-
return DEFAULT_SUITE_DIR;
|
|
66
|
-
const next = args[i + 1];
|
|
67
|
-
if (next === undefined || next.startsWith('-'))
|
|
68
|
-
throw new Error('--suite requires a path');
|
|
69
|
-
return next;
|
|
70
|
-
}
|
|
71
|
-
function parseBaselineFlag(args) {
|
|
72
|
-
const i = args.indexOf('--baseline');
|
|
73
|
-
if (i === -1)
|
|
74
|
-
return null;
|
|
75
|
-
const next = args[i + 1];
|
|
76
|
-
if (next === undefined || next.startsWith('-'))
|
|
77
|
-
throw new Error('--baseline requires a path');
|
|
78
|
-
return next;
|
|
79
|
-
}
|
|
80
|
-
function parseProjectFlag(args) {
|
|
81
|
-
const i = args.indexOf('--project');
|
|
82
|
-
if (i === -1)
|
|
83
|
-
return null;
|
|
84
|
-
const next = args[i + 1];
|
|
85
|
-
if (next === undefined || next.startsWith('-'))
|
|
86
|
-
throw new Error('--project requires a name');
|
|
87
|
-
return next;
|
|
88
|
-
}
|
|
89
|
-
/** Loads one suite file, or every `*.json` file directly under a directory, merged into one. */
|
|
90
|
-
function loadSuite(suitePath) {
|
|
91
|
-
const resolved = path.resolve(_projectRoot, suitePath);
|
|
92
|
-
const stat = fs.statSync(resolved);
|
|
93
|
-
if (stat.isDirectory()) {
|
|
94
|
-
const files = fs.readdirSync(resolved).filter(f => f.endsWith('.json')).sort();
|
|
95
|
-
const parts = files.map(f => fs.readFileSync(path.join(resolved, f), 'utf-8'));
|
|
96
|
-
const suites = parts.map(text => (0, retrieval_eval_1.parseSuite)(JSON.parse(text)));
|
|
97
|
-
return { suite: (0, retrieval_eval_1.mergeSuites)(suites), rawContent: parts.join('\n'), label: 'all' };
|
|
98
|
-
}
|
|
99
|
-
const text = fs.readFileSync(resolved, 'utf-8');
|
|
100
|
-
return { suite: (0, retrieval_eval_1.parseSuite)(JSON.parse(text)), rawContent: text, label: path.basename(resolved, '.json') };
|
|
101
|
-
}
|
|
102
55
|
class EvalCommand {
|
|
103
|
-
|
|
56
|
+
db;
|
|
57
|
+
chunks;
|
|
58
|
+
catalog;
|
|
59
|
+
config;
|
|
104
60
|
argv1;
|
|
105
|
-
|
|
106
|
-
|
|
61
|
+
corpusInspector;
|
|
62
|
+
resultsDir;
|
|
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;
|
|
107
68
|
this.argv1 = argv1;
|
|
69
|
+
this.corpusInspector = corpusInspector;
|
|
70
|
+
this.resultsDir = resultsDir;
|
|
108
71
|
}
|
|
109
72
|
async execute() {
|
|
110
|
-
const
|
|
111
|
-
const args = process.argv.slice(this.argv1 === 'rag-index' ? 3 : 4); // after `rag-index eval` / `index eval`
|
|
73
|
+
const args = process.argv.slice(this.argv1 === 'rag-index' ? 3 : 4);
|
|
112
74
|
let suitePath, baselinePath, projectFilter;
|
|
113
75
|
try {
|
|
114
|
-
suitePath =
|
|
115
|
-
baselinePath = parseBaselineFlag(args);
|
|
116
|
-
projectFilter = parseProjectFlag(args);
|
|
76
|
+
({ suitePath, baselinePath, projectFilter } = (0, eval_args_1.parseEvalArgs)(args));
|
|
117
77
|
}
|
|
118
78
|
catch (err) {
|
|
119
79
|
console.error(`\n${err.message}`);
|
|
120
80
|
process.exitCode = 1;
|
|
121
81
|
return;
|
|
122
82
|
}
|
|
123
|
-
let suite, rawContent, label;
|
|
83
|
+
let suite, corpora, rawContent, label;
|
|
124
84
|
try {
|
|
125
|
-
({ suite, rawContent, label } = loadSuite(suitePath));
|
|
85
|
+
({ suite, corpora, rawContent, label } = (0, suite_loader_1.loadSuite)(_projectRoot, suitePath));
|
|
126
86
|
}
|
|
127
87
|
catch (err) {
|
|
128
88
|
if (err instanceof retrieval_eval_1.EvalSuiteError) {
|
|
@@ -142,90 +102,41 @@ class EvalCommand {
|
|
|
142
102
|
process.exitCode = 1;
|
|
143
103
|
return;
|
|
144
104
|
}
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
const search = async (query, limit, project, threshold) => {
|
|
160
|
-
const prepared = await searcher.prepareQuery(query);
|
|
161
|
-
const results = await searcher.searchChunks(prepared.query, limit, project, threshold);
|
|
162
|
-
return results.map(r => ({ filePath: r.filePath, ownerPath: r.ownerPath ?? null }));
|
|
163
|
-
};
|
|
164
|
-
const run = await new retrieval_eval_1.RetrievalEvaluator().evaluate(suite, search, inspect);
|
|
165
|
-
const indexMeta = await db.readIndexMeta();
|
|
166
|
-
const metadata = {
|
|
167
|
-
suitePath,
|
|
168
|
-
suiteHash: hashContent(rawContent),
|
|
169
|
-
embeddingProvider: config.embedding.provider,
|
|
170
|
-
embeddingModel: config.embedding.model,
|
|
171
|
-
rerankerModel: config.reranker.enabled ? config.reranker.model : null,
|
|
172
|
-
indexMeta: indexMeta ? { provider: indexMeta.provider, model: indexMeta.model, dimensions: indexMeta.dimensions } : null,
|
|
173
|
-
gitCommit: gitCommit(),
|
|
174
|
-
timestamp: new Date().toISOString(),
|
|
175
|
-
};
|
|
176
|
-
const resultFile = { metadata, run };
|
|
177
|
-
this.printSummary(resultFile);
|
|
178
|
-
let comparison;
|
|
179
|
-
if (baselinePath) {
|
|
180
|
-
try {
|
|
181
|
-
const baseline = (0, eval_results_1.readResultFile)(path.resolve(_projectRoot, baselinePath));
|
|
182
|
-
const cmp = (0, retrieval_eval_1.compare)(baseline, resultFile);
|
|
183
|
-
comparison = { baselinePath, result: cmp };
|
|
184
|
-
this.printComparison(baselinePath, cmp);
|
|
185
|
-
}
|
|
186
|
-
catch (err) {
|
|
187
|
-
console.error(`\nFailed to read baseline '${baselinePath}': ${err.message}`);
|
|
188
|
-
process.exitCode = 1;
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
const resultsDir = path.join(_projectRoot, RESULTS_DIR_NAME);
|
|
192
|
-
const { jsonPath, mdPath } = (0, eval_results_1.writeResultFiles)(resultsDir, label, resultFile, new Date(), comparison);
|
|
193
|
-
console.log(`\nResults written to:\n ${path.relative(_projectRoot, jsonPath)}\n ${path.relative(_projectRoot, mdPath)}`);
|
|
194
|
-
}
|
|
195
|
-
printSummary(result) {
|
|
196
|
-
const { run, metadata } = result;
|
|
197
|
-
console.log(`\nEvaluated ${run.cases.length} case(s) (${run.invalid.length} invalid) against ${metadata.embeddingProvider}/${metadata.embeddingModel}`);
|
|
198
|
-
const o = run.metrics.overall;
|
|
199
|
-
console.log(` Overall — hit@1: ${(o.hit1 * 100).toFixed(1)}% hit@5: ${(o.hit5 * 100).toFixed(1)}% MRR@10: ${o.mrr10.toFixed(4)}`);
|
|
200
|
-
for (const category of ['identifier', 'behaviour', 'concept']) {
|
|
201
|
-
const m = run.metrics.byCategory[category];
|
|
202
|
-
if (m)
|
|
203
|
-
console.log(` ${category.padEnd(10)} — hit@1: ${(m.hit1 * 100).toFixed(1)}% hit@5: ${(m.hit5 * 100).toFixed(1)}% MRR@10: ${m.mrr10.toFixed(4)} (${m.count})`);
|
|
204
|
-
}
|
|
205
|
-
if (run.invalid.length > 0) {
|
|
206
|
-
console.log(`\nInvalid cases:`);
|
|
207
|
-
for (const c of run.invalid)
|
|
208
|
-
console.log(` ${c.id}: ${c.reason} — ${c.invalidExpects.map(e => e.file).join(', ')}`);
|
|
209
|
-
}
|
|
210
|
-
if (run.warnings.length > 0) {
|
|
211
|
-
console.log(`\nWarnings (scored on remaining valid answers):`);
|
|
212
|
-
for (const w of run.warnings)
|
|
213
|
-
console.log(` ${w.id}: dropped ${w.droppedExpects.map(e => e.file).join(', ')}`);
|
|
105
|
+
const runCorpora = corpora.filter(c => suite.cases.some(k => k.corpus === c.root));
|
|
106
|
+
if (await (0, eval_corpora_1.refusesMovedCorpus)(runCorpora, this.config, _projectRoot, this.corpusInspector))
|
|
107
|
+
return;
|
|
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);
|
|
116
|
+
let outcome;
|
|
117
|
+
try {
|
|
118
|
+
outcome = await new retrieval_eval_1.RetrievalEvaluator().evaluate(suite, search, inspect, p => console.error((0, eval_results_1.renderProgress)(p)));
|
|
214
119
|
}
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
120
|
+
catch (err) {
|
|
121
|
+
if (!(err instanceof retrieval_eval_1.EvalSuiteError))
|
|
122
|
+
throw err;
|
|
123
|
+
console.error(`\nInvalid suite: ${err.message}`);
|
|
124
|
+
process.exitCode = 1;
|
|
125
|
+
return;
|
|
221
126
|
}
|
|
222
|
-
const
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
127
|
+
const { run, observed } = outcome;
|
|
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
|
+
});
|
|
134
|
+
const resultFile = { metadata, run };
|
|
135
|
+
for (const line of (0, eval_results_1.renderSummary)(resultFile))
|
|
136
|
+
console.log(line);
|
|
137
|
+
const comparison = baselinePath ? (0, baseline_comparison_1.compareWithBaseline)(_projectRoot, baselinePath, resultFile) : undefined;
|
|
138
|
+
const { jsonPath, mdPath } = (0, eval_results_1.writeResultFiles)(this.resultsDir, label, resultFile, new Date(), comparison);
|
|
139
|
+
console.log(`\nResults written to:\n ${path.relative(_projectRoot, jsonPath)}\n ${path.relative(_projectRoot, mdPath)}`);
|
|
229
140
|
}
|
|
230
141
|
}
|
|
231
142
|
exports.EvalCommand = EvalCommand;
|