codesearch-mcp 0.2.2-alpha → 0.3.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 (158) hide show
  1. package/CHANGELOG.md +65 -1
  2. package/README.md +60 -33
  3. package/dist/app.js +46 -22
  4. package/dist/src/chunking/AstChunker.d.ts +12 -0
  5. package/dist/src/chunking/AstChunker.js +30 -0
  6. package/dist/src/chunking/CharacterChunkStrategy.d.ts +8 -0
  7. package/dist/src/chunking/CharacterChunkStrategy.js +15 -0
  8. package/dist/src/chunking/DeclarationChunkStrategy.d.ts +15 -0
  9. package/dist/src/chunking/DeclarationChunkStrategy.js +87 -0
  10. package/dist/src/chunking/FragmentMerger.d.ts +11 -0
  11. package/dist/src/chunking/FragmentMerger.js +61 -0
  12. package/dist/src/chunking/ImportOnlyFilter.d.ts +5 -0
  13. package/dist/src/chunking/ImportOnlyFilter.js +14 -0
  14. package/dist/src/chunking/LangchainTextSplitter.d.ts +21 -0
  15. package/dist/src/chunking/LangchainTextSplitter.js +133 -0
  16. package/dist/src/chunking/MinSizeSplitPolicy.d.ts +9 -0
  17. package/dist/src/chunking/MinSizeSplitPolicy.js +18 -0
  18. package/dist/src/chunking/RunPacker.d.ts +12 -0
  19. package/dist/src/chunking/RunPacker.js +84 -0
  20. package/dist/src/chunking/create-chunker.d.ts +3 -0
  21. package/dist/src/chunking/create-chunker.js +15 -0
  22. package/dist/src/chunking/interfaces.d.ts +27 -0
  23. package/dist/src/chunking/interfaces.js +2 -0
  24. package/dist/src/commands/ConfigCommand.js +1 -9
  25. package/dist/src/commands/EvalCommand.d.ts +11 -0
  26. package/dist/src/commands/EvalCommand.js +264 -0
  27. package/dist/src/commands/IndexCommand.js +70 -66
  28. package/dist/src/commands/McpCommand.js +2 -8
  29. package/dist/src/commands/WebCommand.js +2 -5
  30. package/dist/src/config-error.d.ts +0 -4
  31. package/dist/src/config-error.js +0 -4
  32. package/dist/src/config-store.d.ts +1 -54
  33. package/dist/src/config-store.js +8 -69
  34. package/dist/src/config.d.ts +8 -17
  35. package/dist/src/config.js +35 -34
  36. package/dist/src/constants.d.ts +2 -28
  37. package/dist/src/constants.js +6 -28
  38. package/dist/src/container.d.ts +6 -0
  39. package/dist/src/container.js +12 -3
  40. package/dist/src/db/index.d.ts +1 -1
  41. package/dist/src/db/index.js +1 -2
  42. package/dist/src/db/schema.d.ts +22 -29
  43. package/dist/src/db/schema.js +3 -14
  44. package/dist/src/declarations/DeclarationTree.d.ts +19 -0
  45. package/dist/src/declarations/DeclarationTree.js +66 -0
  46. package/dist/src/declarations/DeclarationTreeBuilder.d.ts +22 -0
  47. package/dist/src/declarations/DeclarationTreeBuilder.js +179 -0
  48. package/dist/src/declarations/SourceLines.d.ts +37 -0
  49. package/dist/src/declarations/SourceLines.js +415 -0
  50. package/dist/src/dependency-traversal.d.ts +10 -0
  51. package/dist/src/dependency-traversal.js +39 -0
  52. package/dist/src/enriched-prompt.d.ts +0 -5
  53. package/dist/src/enriched-prompt.js +0 -5
  54. package/dist/src/error-record.d.ts +12 -0
  55. package/dist/src/error-record.js +248 -0
  56. package/dist/src/eval-corpus.d.ts +16 -0
  57. package/dist/src/eval-corpus.js +169 -0
  58. package/dist/src/eval-results.d.ts +15 -0
  59. package/dist/src/eval-results.js +397 -0
  60. package/dist/src/file-utils.d.ts +10 -0
  61. package/dist/src/file-utils.js +19 -1
  62. package/dist/src/graph.d.ts +0 -25
  63. package/dist/src/graph.js +0 -28
  64. package/dist/src/help.js +4 -1
  65. package/dist/src/hnsw-settings.d.ts +3 -0
  66. package/dist/src/hnsw-settings.js +24 -0
  67. package/dist/src/interfaces/IAstParser.d.ts +5 -30
  68. package/dist/src/interfaces/IChunker.d.ts +3 -12
  69. package/dist/src/interfaces/ICorpusInspector.d.ts +7 -0
  70. package/dist/src/interfaces/ICorpusInspector.js +2 -0
  71. package/dist/src/interfaces/IDatabase.d.ts +2 -36
  72. package/dist/src/interfaces/IEmbedder.d.ts +0 -9
  73. package/dist/src/interfaces/ILogger.d.ts +1 -11
  74. package/dist/src/interfaces/IMcpToolHandler.d.ts +0 -5
  75. package/dist/src/interfaces/IMonorepoResolver.d.ts +0 -22
  76. package/dist/src/interfaces/IProjectDiscovery.d.ts +0 -17
  77. package/dist/src/interfaces/IRetrievalEvaluator.d.ts +216 -0
  78. package/dist/src/interfaces/IRetrievalEvaluator.js +2 -0
  79. package/dist/src/interfaces/ISearcher.d.ts +26 -20
  80. package/dist/src/interfaces/index.d.ts +1 -0
  81. package/dist/src/interrupt.js +0 -2
  82. package/dist/src/owner-path.d.ts +9 -10
  83. package/dist/src/owner-path.js +11 -23
  84. package/dist/src/project-scope.d.ts +7 -0
  85. package/dist/src/project-scope.js +37 -0
  86. package/dist/src/project-selector.d.ts +1 -0
  87. package/dist/src/project-selector.js +13 -6
  88. package/dist/src/retrieval-eval.d.ts +24 -0
  89. package/dist/src/retrieval-eval.js +500 -0
  90. package/dist/src/search/result-shaping.d.ts +4 -0
  91. package/dist/src/search/result-shaping.js +19 -0
  92. package/dist/src/services/AstParserService.d.ts +28 -23
  93. package/dist/src/services/AstParserService.js +391 -98
  94. package/dist/src/services/DatabaseService.d.ts +2 -19
  95. package/dist/src/services/DatabaseService.js +44 -81
  96. package/dist/src/services/EmbedderFactory.d.ts +0 -4
  97. package/dist/src/services/EmbedderFactory.js +0 -5
  98. package/dist/src/services/IndexerService.d.ts +2 -10
  99. package/dist/src/services/IndexerService.js +29 -45
  100. package/dist/src/services/InfinityEmbedder.d.ts +0 -21
  101. package/dist/src/services/InfinityEmbedder.js +0 -15
  102. package/dist/src/services/LoggerService.d.ts +7 -5
  103. package/dist/src/services/LoggerService.js +37 -41
  104. package/dist/src/services/McpServer.d.ts +25 -10
  105. package/dist/src/services/McpServer.js +101 -64
  106. package/dist/src/services/MonorepoAwareDiscoveryService.d.ts +1 -45
  107. package/dist/src/services/MonorepoAwareDiscoveryService.js +1 -51
  108. package/dist/src/services/NxMonorepoResolver.d.ts +0 -29
  109. package/dist/src/services/NxMonorepoResolver.js +5 -56
  110. package/dist/src/services/OpenAICompatibleEmbedder.d.ts +0 -6
  111. package/dist/src/services/OpenAICompatibleEmbedder.js +1 -14
  112. package/dist/src/services/ProjectDiscoveryService.d.ts +0 -4
  113. package/dist/src/services/ProjectDiscoveryService.js +0 -4
  114. package/dist/src/services/SearcherService.d.ts +127 -70
  115. package/dist/src/services/SearcherService.js +526 -305
  116. package/dist/src/services/VoyageEmbedder.d.ts +0 -6
  117. package/dist/src/services/VoyageEmbedder.js +0 -6
  118. package/dist/src/services/WebServerService.d.ts +1 -53
  119. package/dist/src/services/WebServerService.js +11 -57
  120. package/dist/src/services/http-retry.d.ts +0 -7
  121. package/dist/src/services/http-retry.js +1 -10
  122. package/dist/src/services/infinity-provisioning.d.ts +0 -74
  123. package/dist/src/services/infinity-provisioning.js +5 -88
  124. package/dist/src/services/legacy-ollama-index.d.ts +0 -16
  125. package/dist/src/services/legacy-ollama-index.js +0 -23
  126. package/dist/src/services/reranker.d.ts +0 -9
  127. package/dist/src/services/reranker.js +46 -12
  128. package/dist/src/setup.d.ts +11 -23
  129. package/dist/src/setup.js +98 -71
  130. package/dist/src/symbol-name.d.ts +0 -12
  131. package/dist/src/symbol-name.js +0 -13
  132. package/dist/src/symbol-rows.d.ts +2 -11
  133. package/dist/src/symbol-rows.js +5 -13
  134. package/dist/src/tool-call-log.d.ts +2 -0
  135. package/dist/src/tool-call-log.js +24 -0
  136. package/dist/src/tools/FindSymbolTool.js +14 -5
  137. package/dist/src/tools/GetCallersTool.d.ts +3 -1
  138. package/dist/src/tools/GetCallersTool.js +16 -6
  139. package/dist/src/tools/GetDependenciesTool.d.ts +3 -1
  140. package/dist/src/tools/GetDependenciesTool.js +15 -8
  141. package/dist/src/tools/GetDependentsTool.d.ts +3 -1
  142. package/dist/src/tools/GetDependentsTool.js +31 -16
  143. package/dist/src/tools/ListFilesTool.d.ts +3 -1
  144. package/dist/src/tools/ListFilesTool.js +14 -12
  145. package/dist/src/tools/ListProjectsTool.js +5 -1
  146. package/dist/src/tools/ReadFileRangeTool.d.ts +3 -1
  147. package/dist/src/tools/ReadFileRangeTool.js +12 -11
  148. package/dist/src/tools/ReadFileTool.d.ts +3 -1
  149. package/dist/src/tools/ReadFileTool.js +12 -10
  150. package/dist/src/tools/SearchCodebaseTool.js +7 -2
  151. package/dist/src/tools/format-helpers.d.ts +10 -1
  152. package/dist/src/tools/format-helpers.js +145 -8
  153. package/dist/src/web/dashboard.d.ts +0 -8
  154. package/dist/src/web/dashboard.js +7 -10
  155. package/package.json +10 -9
  156. package/dist/src/services/AstChunker.d.ts +0 -42
  157. package/dist/src/services/AstChunker.js +0 -158
  158. package/docs/web-dashboard.md +0 -206
@@ -1,3 +1,4 @@
1
+ import type { DeclarationTree } from '../declarations/DeclarationTree';
1
2
  export interface DepEdge {
2
3
  project: string;
3
4
  fromFile: string;
@@ -6,7 +7,7 @@ export interface DepEdge {
6
7
  toSymbol: string | null;
7
8
  depType: string;
8
9
  }
9
- export type SymbolKind = 'function' | 'class' | 'interface' | 'type' | 'variable' | 'method' | 'get_accessor' | 'set_accessor' | 'constructor' | 'function_property' | 'method_signature';
10
+ export type SymbolKind = 'function' | 'class' | 'interface' | 'type' | 'variable' | 'method' | 'get_accessor' | 'set_accessor' | 'constructor' | 'function_property' | 'method_signature' | 'graphql_query' | 'graphql_mutation' | 'graphql_subscription' | 'graphql_field' | 'graphql_type';
10
11
  export interface SymbolEntry {
11
12
  project: string;
12
13
  filePath: string;
@@ -16,14 +17,9 @@ export interface SymbolEntry {
16
17
  line: number | null;
17
18
  endLine: number | null;
18
19
  col: number | null;
19
- /** Dotted path of enclosing named scopes, outermost first; null for top-level declarations. */
20
20
  container: string | null;
21
21
  isStatic: boolean;
22
- /**
23
- * Whether this declaration node has a body (vs. an overload signature).
24
- * Internal — used only to pick an overload set's representative row before
25
- * writing to `code_symbol`; never persisted.
26
- */
22
+ target?: string | null;
27
23
  hasBody?: boolean;
28
24
  }
29
25
  export interface CallEdge {
@@ -36,40 +32,19 @@ export interface CallEdge {
36
32
  line: number | null;
37
33
  col: number | null;
38
34
  }
39
- /**
40
- * Line range of a named scope used only to compute a chunk's owning declaration
41
- * (`ownerPath`). Method/constructor/accessor ranges carry their enclosing class
42
- * as `container`; top-level declarations use `container: null`. These are NOT
43
- * persisted to `code_symbol` — they exist only for chunk ownership.
44
- */
45
- export interface OwnerRange {
46
- name: string;
47
- container: string | null;
48
- line: number;
49
- endLine: number;
50
- }
51
35
  export interface FileAnalysis {
52
36
  edges: DepEdge[];
53
- /** Top-level declarations only — feeds the chunker and the embedding prompt. */
54
37
  symbols: SymbolEntry[];
55
- /** Members, namespace-level declarations and classes collected from the whole
56
- * file. Written to `code_symbol` alongside `symbols`; never fed to the
57
- * chunker or the prompt (see the `symbol-index-members` retrieval-invariance
58
- * requirement). */
59
38
  members: SymbolEntry[];
60
39
  calls: CallEdge[];
61
- /** Ownership ranges (decorator-inclusive) for every indexed declaration except `method_signature`. */
62
- ownerRanges?: OwnerRange[];
40
+ declarations?: DeclarationTree;
41
+ graphqlNames: SymbolEntry[];
63
42
  }
64
43
  export interface AnalyzeProjectOpts {
65
44
  skipDependencyResolution?: boolean;
66
- /** Path to root tsconfig (e.g. tsconfig.base.json) for workspace-wide path aliases */
67
45
  rootTsConfigPath?: string;
68
46
  }
69
47
  export interface IAstParser {
70
- /**
71
- * @deprecated Use analyzeProject instead for project-wide context.
72
- */
73
48
  analyzeFile(filePath: string, serviceName: string, projectRoot?: string): Promise<FileAnalysis>;
74
49
  analyzeProject(filePaths: string[], serviceName: string, projectRoot?: string, opts?: AnalyzeProjectOpts): Promise<Map<string, FileAnalysis>>;
75
50
  clearCache(projectRoot?: string): void;
@@ -1,24 +1,15 @@
1
- import type { SymbolEntry } from './IAstParser';
2
- /** One embeddable unit of source with its 1-based inclusive line range. */
1
+ import type { DeclarationTree } from '../declarations/DeclarationTree';
3
2
  export interface ChunkPiece {
4
3
  content: string;
5
4
  startLine: number;
6
5
  endLine: number;
7
6
  }
8
7
  export interface ChunkOpts {
9
- /** 'ast' = symbol-aligned boundaries; 'character' = fixed-size recursive splitter. */
10
8
  strategy: 'ast' | 'character';
11
- /** Schema files (.prisma/.graphql/.gql) always use the schema separator splitter. */
12
9
  isSchemaFile: boolean;
13
- /** Top-level symbol ranges for the file; may be empty (no analysis available). */
14
- symbols: SymbolEntry[];
10
+ declarations?: DeclarationTree;
11
+ jsx?: boolean;
15
12
  }
16
13
  export interface IChunker {
17
- /**
18
- * Split source into embeddable pieces. AST strategy aligns boundaries to
19
- * top-level declaration ranges and never emits a piece longer than the
20
- * configured chunk size; falls back to the character splitter for schema
21
- * files, empty-symbol files, or when strategy is 'character'.
22
- */
23
14
  chunk(code: string, opts: ChunkOpts): Promise<ChunkPiece[]>;
24
15
  }
@@ -0,0 +1,7 @@
1
+ export interface ICorpusInspector {
2
+ headCommit(root: string): Promise<string>;
3
+ trackedChanges(root: string): Promise<string[]>;
4
+ untrackedFiles(root: string, skipDirs: readonly string[]): Promise<string[]>;
5
+ listFiles(dir: string): Promise<string[]>;
6
+ readFile(absPath: string): Promise<Buffer | null>;
7
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -1,58 +1,24 @@
1
1
  import type { DrizzleDb, DrizzleTx } from '../services/DatabaseService';
2
- /** Single-row record of which embedding model built the current index. */
3
2
  export interface IndexMeta {
4
3
  provider: string;
5
4
  model: string;
6
5
  dimensions: number;
7
6
  }
8
- /**
9
- * Database abstraction — services depend on this interface
10
- * rather than the concrete DatabaseService.
11
- */
12
7
  export interface IDatabase {
13
8
  readonly orm: DrizzleDb;
14
9
  query<T = any>(sql: string, params?: any[]): Promise<T>;
10
+ queryWithLocalSettings<T = any>(settings: Record<string, string | number>, sql: string, params?: any[]): Promise<T>;
11
+ pgvectorVersion(): Promise<string | null>;
15
12
  transaction<T>(fn: (tx: DrizzleTx) => Promise<T>): Promise<T>;
16
13
  initDb(): Promise<void>;
17
14
  initDbWithSchema(): Promise<void>;
18
15
  destroy(): Promise<void>;
19
- /** Read the single `index_meta` row, or null when absent (table missing → null). */
20
16
  readIndexMeta(): Promise<IndexMeta | null>;
21
- /** Upsert the single `index_meta` row. */
22
17
  writeIndexMeta(meta: IndexMeta): Promise<void>;
23
- /** Create `code_chunk` (+ HNSW/service indexes) at `dimensions` if absent. */
24
18
  ensureChunkTable(dimensions: number): Promise<void>;
25
- /** Drop and recreate `code_chunk` at `dimensions` (dimension change). */
26
19
  recreateChunkTable(dimensions: number): Promise<void>;
27
- /**
28
- * Return all file paths referenced in any of the four index tables for `project`.
29
- * Union of code_chunk.filePath, code_symbol.filePath, code_call.fromFile,
30
- * code_dependency.fromFile. calleeFile and toFile are excluded (may belong to other projects).
31
- */
32
20
  listKnownFiles(project: string): Promise<string[]>;
33
- /**
34
- * Delete rows for `filePaths` from all four index tables in one transaction.
35
- * code_call rows where the file is either fromFile OR calleeFile are removed.
36
- * code_dependency rows where the file is either fromFile OR toFile are removed.
37
- * No-op when `filePaths` is empty.
38
- */
39
21
  deleteFiles(project: string, filePaths: string[]): Promise<void>;
40
- /** Return all project names referenced in any of the four index tables. */
41
22
  listIndexedProjects(): Promise<string[]>;
42
- /** Delete all rows for `name` from the four index tables in one transaction. */
43
23
  deleteProject(name: string): Promise<void>;
44
- /** Every project with at least one row in `code_chunk` or `code_symbol` — the
45
- * symbol/call-graph lookup scope (distinct from `listIndexedProjects`, which
46
- * also covers `code_call`/`code_dependency`). */
47
- listProjectsWithIndexRows(): Promise<string[]>;
48
- /**
49
- * Among `projectNames` (or every project with rows when null), those that
50
- * are outdated: at least one row in `code_chunk`/`code_symbol` and a
51
- * `symbol_index_version` below the current format version (missing row = 1).
52
- * A missing `symbol_index_version` table counts as "no marker rows" for every
53
- * project. Any other database error propagates.
54
- */
55
- listOutdatedProjects(projectNames: string[] | null): Promise<string[]>;
56
- /** Upsert a project's `symbol_index_version` marker to the current format version. */
57
- upsertSymbolIndexVersion(project: string): Promise<void>;
58
24
  }
@@ -1,16 +1,7 @@
1
1
  export type InputType = 'query' | 'document';
2
2
  export interface IEmbedder {
3
- /**
4
- * The vector width this embedder produces, when known without a probe:
5
- * `embedding.dimensions` override → model registry, else `0` for models whose
6
- * width is only knowable by embedding once (see `resolveDimension`). Read by
7
- * `SearcherService.assertIndexMatches` to catch a dimension change on the
8
- * search side (skipped when `0`). Indexing resolves the true width via
9
- * `resolveDimension` (which probes when needed), not this field.
10
- */
11
3
  readonly dimensions: number;
12
4
  embed(text: string, inputType?: InputType): Promise<number[]>;
13
- /** One vector per input, in input order. The indexing path. */
14
5
  embedBatch(texts: string[], inputType?: InputType): Promise<number[][]>;
15
6
  rerank?(query: string, documents: string[], topN: number): Promise<number[]>;
16
7
  listModels?(): Promise<string[]>;
@@ -1,17 +1,7 @@
1
- /**
2
- * Logger abstraction — allows services to depend on a contract
3
- * rather than the concrete pino-based LoggerService.
4
- */
5
1
  export interface ILogger {
6
2
  debug(msg: string, data?: Record<string, unknown>): void;
7
3
  info(msg: string, data?: Record<string, unknown>): void;
8
4
  warn(msg: string, data?: Record<string, unknown>): void;
9
5
  error(msg: string, data?: Record<string, unknown>): void;
10
- /**
11
- * Structured telemetry emitted at `info` **independent of the configured log
12
- * level** — so an operator can collect it in production without the full
13
- * `debug` firehose. No-op when file logging is disabled (never writes to
14
- * stdout, which the MCP transport owns).
15
- */
16
- metric(msg: string, data?: Record<string, unknown>): void;
6
+ withContext<T>(context: Record<string, unknown>, fn: () => Promise<T>): Promise<T>;
17
7
  }
@@ -1,8 +1,3 @@
1
- /**
2
- * MCP Tool Handler interface — each tool implements this contract.
3
- * Follows the Open/Closed Principle: new tools are added by implementing
4
- * this interface and registering them, not by modifying McpServer.
5
- */
6
1
  export interface ToolDefinition {
7
2
  name: string;
8
3
  description: string;
@@ -1,33 +1,11 @@
1
- /**
2
- * Represents a discovered project within a monorepo workspace.
3
- */
4
1
  export interface MonorepoProject {
5
- /** Project name (e.g. "my-app", "shared-utils") */
6
2
  name: string;
7
- /** Absolute path to the project root */
8
3
  path: string;
9
- /** npm scope + package name (e.g. "@scope/my-app") — null if no package.json or no name */
10
4
  packageName: string | null;
11
- /** "app" | "lib" — derived from project.json or directory convention */
12
5
  type: 'app' | 'lib';
13
6
  }
14
- /**
15
- * Monorepo resolver — detects and resolves workspace structure.
16
- * Implementations handle specific monorepo tooling (Nx, Turborepo, etc.)
17
- */
18
7
  export interface IMonorepoResolver {
19
- /**
20
- * Detect whether the given root directory is a monorepo workspace.
21
- */
22
8
  isMonorepo(rootDir: string): boolean;
23
- /**
24
- * Discover all projects (apps + libs) in the monorepo.
25
- */
26
9
  discoverProjects(rootDir: string): MonorepoProject[];
27
- /**
28
- * Get the root tsconfig path that contains workspace-wide path aliases.
29
- * For Nx this is typically tsconfig.base.json at the workspace root.
30
- * The AST parser uses this to resolve cross-project imports (@scope/*).
31
- */
32
10
  getRootTsConfigPath(rootDir: string): string | null;
33
11
  }
@@ -1,28 +1,11 @@
1
1
  export interface DiscoveredProject {
2
2
  name: string;
3
3
  path: string;
4
- /** npm scope + package name (e.g. "@scope/my-app") — only set for monorepo projects */
5
4
  packageName?: string | null;
6
- /** "app" | "lib" — only set for monorepo projects */
7
5
  type?: 'app' | 'lib';
8
- /**
9
- * Path to the workspace-wide tsconfig (e.g. tsconfig.base.json) that holds
10
- * cross-project path aliases. Set for monorepo projects; undefined for flat
11
- * workspaces (where each project uses its own local tsconfig.json).
12
- */
13
6
  rootTsConfigPath?: string | null;
14
- /**
15
- * When a top-level directory is itself a nested monorepo (e.g. an Nx repo
16
- * under a flat workspaceRoot), this holds its expanded sub-projects. The
17
- * repo stays a single selectable unit; `toLeafProjects` expands `children`
18
- * into the actual projects to index. Absent/undefined for ordinary projects.
19
- */
20
7
  children?: DiscoveredProject[];
21
8
  }
22
- /**
23
- * Project discovery abstraction — decouples project enumeration
24
- * from the indexing service (Single Responsibility Principle).
25
- */
26
9
  export interface IProjectDiscovery {
27
10
  discover(rootDir: string): DiscoveredProject[];
28
11
  }
@@ -0,0 +1,216 @@
1
+ import type { StageName } from './ISearcher';
2
+ export type { StageName };
3
+ export type EvalCategory = 'identifier' | 'behaviour' | 'concept';
4
+ export interface ExpectedAnswer {
5
+ file: string;
6
+ owner?: string;
7
+ }
8
+ export interface EvalCase {
9
+ id: string;
10
+ project: string;
11
+ category: EvalCategory;
12
+ query: string;
13
+ expect: ExpectedAnswer[];
14
+ threshold?: number;
15
+ corpus?: string | null;
16
+ }
17
+ export interface CorpusRef {
18
+ root: string;
19
+ commit: string;
20
+ }
21
+ export interface EvalSuite {
22
+ version: 1;
23
+ corpus?: CorpusRef;
24
+ cases: EvalCase[];
25
+ }
26
+ export interface SearchHit {
27
+ filePath: string;
28
+ ownerPath: string | null;
29
+ }
30
+ export interface StagedHits {
31
+ pool: SearchHit[];
32
+ stages: {
33
+ vector: SearchHit[];
34
+ } & Partial<Record<StageName, SearchHit[]>>;
35
+ rerankFailed: boolean;
36
+ fetchLimit: number;
37
+ indexParams: {
38
+ efSearch: number | null;
39
+ iterativeScan: string;
40
+ };
41
+ }
42
+ export type SearchFn = (query: string, limit: number, project: string | null, threshold?: number) => Promise<StagedHits>;
43
+ export interface IndexInspector {
44
+ isFileIndexed(project: string, file: string): Promise<boolean>;
45
+ ownerPathsOfFile(project: string, file: string): Promise<string[]>;
46
+ projectDir(project: string): Promise<string | null>;
47
+ }
48
+ export interface Metrics {
49
+ count: number;
50
+ hit1: number;
51
+ hit5: number;
52
+ mrr10: number;
53
+ }
54
+ export interface StageRank {
55
+ rank: number | null;
56
+ matched: SearchHit | null;
57
+ }
58
+ export interface CaseResult {
59
+ id: string;
60
+ project: string;
61
+ category: EvalCategory;
62
+ query: string;
63
+ stages: Partial<Record<StageName, StageRank>>;
64
+ poolRank: number | null;
65
+ poolSize: number;
66
+ rerankFailed: boolean;
67
+ corpus: string | null;
68
+ }
69
+ export interface InvalidCase {
70
+ id: string;
71
+ reason: string;
72
+ invalidExpects: ExpectedAnswer[];
73
+ }
74
+ export interface PartialWarning {
75
+ id: string;
76
+ droppedExpects: ExpectedAnswer[];
77
+ }
78
+ export interface StageMetrics {
79
+ overall: Metrics;
80
+ byCategory: Partial<Record<EvalCategory, Metrics>>;
81
+ }
82
+ export interface PoolMetrics {
83
+ count: number;
84
+ recall: number;
85
+ short: number;
86
+ }
87
+ export interface PairCounts {
88
+ improved: number;
89
+ worsened: number;
90
+ unchanged: number;
91
+ signTestP: number;
92
+ }
93
+ export interface PairedChange {
94
+ overall: PairCounts;
95
+ byCategory: Partial<Record<EvalCategory, PairCounts>>;
96
+ hit5Gained: string[];
97
+ hit5Lost: string[];
98
+ }
99
+ export interface StageChange {
100
+ from: StageName;
101
+ to: StageName;
102
+ change: PairedChange;
103
+ }
104
+ export interface EvalRunResult {
105
+ cases: CaseResult[];
106
+ invalid: InvalidCase[];
107
+ warnings: PartialWarning[];
108
+ stages: StageName[];
109
+ metrics: Partial<Record<StageName, StageMetrics>>;
110
+ pool: {
111
+ overall: PoolMetrics;
112
+ byCategory: Partial<Record<EvalCategory, PoolMetrics>>;
113
+ };
114
+ stageChanges: StageChange[];
115
+ rerankFailures: number;
116
+ byCorpus: Record<string, CorpusRunMetrics>;
117
+ }
118
+ export interface CorpusRunMetrics {
119
+ cases: number;
120
+ metrics: Partial<Record<StageName, StageMetrics>>;
121
+ pool: {
122
+ overall: PoolMetrics;
123
+ byCategory: Partial<Record<EvalCategory, PoolMetrics>>;
124
+ };
125
+ stageChanges: StageChange[];
126
+ }
127
+ export interface ObservedSearchParams {
128
+ fetchLimit: number[];
129
+ efSearch: (number | null)[];
130
+ iterativeScan: string[];
131
+ }
132
+ export interface EvalOutcome {
133
+ run: EvalRunResult;
134
+ observed: ObservedSearchParams;
135
+ }
136
+ export interface CaseProgress {
137
+ index: number;
138
+ total: number;
139
+ id: string;
140
+ result: CaseResult | null;
141
+ invalid: InvalidCase | null;
142
+ ms: number;
143
+ }
144
+ export interface IRetrievalEvaluator {
145
+ evaluate(suite: EvalSuite, search: SearchFn, inspect: IndexInspector, onCase?: (p: CaseProgress) => void): Promise<EvalOutcome>;
146
+ }
147
+ export interface SearchConditions {
148
+ similarityThreshold: number;
149
+ overfetch: number;
150
+ candidateFloor: number;
151
+ fetchLimit: number[];
152
+ efSearch: (number | null)[];
153
+ iterativeScan: string[];
154
+ }
155
+ export interface ResultMetadata {
156
+ suitePath: string;
157
+ suiteHash: string;
158
+ embeddingProvider: string;
159
+ embeddingModel: string;
160
+ rerankerModel: string | null;
161
+ indexMeta: {
162
+ provider: string;
163
+ model: string;
164
+ dimensions: number;
165
+ } | null;
166
+ gitCommit: string;
167
+ timestamp: string;
168
+ conditions: SearchConditions | null;
169
+ corpora: CorpusRecord[];
170
+ liveCases: number;
171
+ }
172
+ export interface CorpusRecord {
173
+ root: string;
174
+ commit: string;
175
+ projects: string[];
176
+ chunks: number;
177
+ fingerprint: string;
178
+ }
179
+ export interface EvalResultFile {
180
+ metadata: ResultMetadata;
181
+ run: EvalRunResult;
182
+ legacy?: true;
183
+ }
184
+ export interface MetricDelta {
185
+ baseline: number;
186
+ current: number;
187
+ delta: number;
188
+ }
189
+ export type MetricsDelta = Record<keyof Metrics, MetricDelta>;
190
+ export interface StageComparison {
191
+ stage: StageName;
192
+ overall: MetricsDelta;
193
+ byCategory: Partial<Record<EvalCategory, MetricsDelta>>;
194
+ change: PairedChange;
195
+ }
196
+ export interface PoolValueDelta {
197
+ baseline: number | null;
198
+ current: number;
199
+ delta: number | null;
200
+ }
201
+ export interface PoolDelta {
202
+ recall: PoolValueDelta;
203
+ short: PoolValueDelta;
204
+ }
205
+ export interface CompareResult {
206
+ stages: StageComparison[];
207
+ unmatchedStages: {
208
+ stage: StageName;
209
+ side: 'baseline' | 'current';
210
+ }[];
211
+ pool: {
212
+ overall: PoolDelta;
213
+ byCategory: Partial<Record<EvalCategory, PoolDelta>>;
214
+ };
215
+ conditionWarnings: string[];
216
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -1,8 +1,18 @@
1
- import type { SearchResult, NeighborResult, GraphContext, DependencyRow, ProjectRow, GrepMatch, SymbolKind, SymbolHit, CallerRow, FileRangeResult } from '../services/SearcherService';
2
- /**
3
- * Searcher abstraction — McpServer depends on this interface
4
- * rather than the concrete SearcherService.
5
- */
1
+ import type { SearchResult, NeighborResult, GraphContext, DependencyRow, ProjectRow, SymbolKind, SymbolHit, CallerRow, FileRangeResult, ListFilesResult, GrepSymbolResult, ResolvedToolPath, PathFailure } from '../services/SearcherService';
2
+ export type StageName = 'vector' | 'reranked';
3
+ export interface StagedSearchResult {
4
+ pool: SearchResult[];
5
+ stages: {
6
+ vector: SearchResult[];
7
+ reranked?: SearchResult[];
8
+ };
9
+ rerankFailed: boolean;
10
+ fetchLimit: number;
11
+ indexParams: {
12
+ efSearch: number | null;
13
+ iterativeScan: string;
14
+ };
15
+ }
6
16
  export interface ISearcher {
7
17
  prepareQuery(raw: string): Promise<{
8
18
  query: string;
@@ -14,27 +24,23 @@ export interface ISearcher {
14
24
  from: string;
15
25
  to: string;
16
26
  }[]>;
17
- searchChunks(query: string, limit: number, project: string | null, threshold?: number): Promise<SearchResult[]>;
27
+ searchChunks(query: string, limit: number, project: string | null, threshold?: number, rerankOverride?: boolean, perFile?: number): Promise<SearchResult[]>;
28
+ searchChunksWithStages(query: string, limit: number, project: string | null, threshold?: number, rerankOverride?: boolean, perFile?: number): Promise<StagedSearchResult>;
18
29
  fetchNeighbors(results: SearchResult[]): Promise<NeighborResult[]>;
19
30
  fetchGraphContext(results: SearchResult[]): Promise<Map<string, GraphContext>>;
20
- getDependencies(filePath: string, project: string, symbol?: string | null, transitive?: boolean): Promise<DependencyRow[]>;
21
- getDependents(filePath: string, project: string, symbol?: string | null, transitive?: boolean): Promise<DependencyRow[]>;
31
+ getDependencies(filePath: string, symbol?: string | null, transitive?: boolean): Promise<DependencyRow[]>;
32
+ getDependents(filePath: string, symbol?: string | null, transitive?: boolean): Promise<DependencyRow[]>;
22
33
  getCallers(symbol: string, project: string, calleeFile?: string | null): Promise<CallerRow[]>;
23
- grepSymbol(symbol: string, project: string, excludeFile: string): Promise<{
24
- matches: GrepMatch[];
25
- truncated: boolean;
26
- }>;
34
+ grepSymbol(symbol: string, rootDir: string, excludeFile: string): Promise<GrepSymbolResult>;
27
35
  findSymbol(name: string, project: string | null, kind: SymbolKind): Promise<{
28
36
  hits: SymbolHit[];
29
37
  truncated: boolean;
30
38
  grepFailed: boolean;
31
39
  }>;
32
- /** One-line warning when a project in scope is outdated (see `SearcherService.outdatedNotice`), else null. */
33
- outdatedNotice(project: string | null): Promise<string | null>;
34
- listFiles(relativePath: string, project: string, depth: number, pattern: string | null): {
35
- tree: string;
36
- error?: string;
37
- };
38
- readFileAbsolute(absPath: string, maxLines: number): Promise<FileRangeResult>;
39
- readFileRange(filePath: string, startLine: number, endLine: number): Promise<FileRangeResult>;
40
+ listFiles(relPath: string, depth: number, pattern: string | null): Promise<ListFilesResult>;
41
+ readFile(relPath: string, maxLines: number): Promise<FileRangeResult>;
42
+ readFileRange(relPath: string, startLine: number, endLine: number): Promise<FileRangeResult>;
43
+ resolveToolPath(input: string | null | undefined): Promise<ResolvedToolPath>;
44
+ checkGraphPath(relPath: string): Promise<PathFailure | null>;
45
+ fallbackRoot(relPath: string): string | null;
40
46
  }
@@ -6,3 +6,4 @@ export type { IDatabase } from './IDatabase';
6
6
  export type { ISearcher } from './ISearcher';
7
7
  export type { IProjectDiscovery, DiscoveredProject } from './IProjectDiscovery';
8
8
  export type { IMcpToolHandler, ToolDefinition, ToolResponse } from './IMcpToolHandler';
9
+ export type { EvalCategory, ExpectedAnswer, EvalCase, EvalSuite, SearchHit, SearchFn, IndexInspector, Metrics, CaseResult, InvalidCase, PartialWarning, EvalRunResult, IRetrievalEvaluator, ResultMetadata, EvalResultFile, MetricDelta, MetricsDelta, CompareResult, } from './IRetrievalEvaluator';
@@ -1,8 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.setupInterrupt = setupInterrupt;
4
- // Graceful interruption for long-running CLI operations.
5
- // Caller creates the AbortController; this function wires stdin and returns a cleanup function.
6
4
  function setupInterrupt(controller) {
7
5
  if (!process.stdin.isTTY)
8
6
  return () => { };
@@ -1,10 +1,9 @@
1
- import type { OwnerRange } from './interfaces/IAstParser';
2
- /**
3
- * Resolve the owning declaration for a chunk given its 1-based start line and a
4
- * flat list of candidate ranges (top-level symbols + method ranges). The
5
- * deepest range containing the start line wins (smallest `endLine - line` span),
6
- * so a method beats its enclosing class. Returns `Container.name` for methods
7
- * (via `container`) or `name` for top-level declarations, and `null` when the
8
- * start line lies outside every range (imports / module-scope gaps).
9
- */
10
- export declare function resolveOwnerPath(startLine: number, ranges: OwnerRange[]): string | null;
1
+ import type { DeclarationTree } from './declarations/DeclarationTree';
2
+ import type { SourceLines } from './declarations/SourceLines';
3
+ interface LineSpan {
4
+ startLine: number;
5
+ endLine: number;
6
+ }
7
+ export declare function ownedLines(piece: LineSpan, declarations: DeclarationTree, lines: SourceLines): number[];
8
+ export declare function ownerOf(piece: LineSpan, declarations: DeclarationTree, lines: SourceLines): string | null;
9
+ export {};
@@ -1,27 +1,15 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.resolveOwnerPath = resolveOwnerPath;
4
- /**
5
- * Resolve the owning declaration for a chunk given its 1-based start line and a
6
- * flat list of candidate ranges (top-level symbols + method ranges). The
7
- * deepest range containing the start line wins (smallest `endLine - line` span),
8
- * so a method beats its enclosing class. Returns `Container.name` for methods
9
- * (via `container`) or `name` for top-level declarations, and `null` when the
10
- * start line lies outside every range (imports / module-scope gaps).
11
- */
12
- function resolveOwnerPath(startLine, ranges) {
13
- let best = null;
14
- let bestSpan = Infinity;
15
- for (const r of ranges) {
16
- if (r.line <= startLine && startLine <= r.endLine) {
17
- const span = r.endLine - r.line;
18
- if (span < bestSpan) {
19
- bestSpan = span;
20
- best = r;
21
- }
22
- }
3
+ exports.ownedLines = ownedLines;
4
+ exports.ownerOf = ownerOf;
5
+ function ownedLines(piece, declarations, lines) {
6
+ const owned = [];
7
+ for (let n = piece.startLine; n <= piece.endLine; n++) {
8
+ if (lines.isSignificant(n) && declarations.contains(n))
9
+ owned.push(n);
23
10
  }
24
- if (!best)
25
- return null;
26
- return best.container ? `${best.container}.${best.name}` : best.name;
11
+ return owned;
12
+ }
13
+ function ownerOf(piece, declarations, lines) {
14
+ return declarations.smallestContaining(ownedLines(piece, declarations, lines))?.qualifiedName ?? null;
27
15
  }
@@ -0,0 +1,7 @@
1
+ import type { DiscoveredProject } from './interfaces';
2
+ export interface ResolveProjectNamesResult {
3
+ targets: DiscoveredProject[];
4
+ notFound: string[];
5
+ }
6
+ export declare function resolveProjectNames(names: string[], units: DiscoveredProject[]): ResolveProjectNamesResult;
7
+ export declare function listAvailableNames(units: DiscoveredProject[]): string[];