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.
- package/CHANGELOG.md +59 -6
- package/LICENSE +661 -21
- package/README.md +33 -17
- package/dist/app.js +13 -20
- 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/commands/EvalCommand.d.ts +7 -3
- package/dist/src/commands/EvalCommand.js +36 -158
- package/dist/src/commands/IndexCommand.d.ts +10 -4
- package/dist/src/commands/IndexCommand.js +52 -124
- package/dist/src/commands/McpCommand.d.ts +6 -3
- package/dist/src/commands/McpCommand.js +19 -14
- package/dist/src/commands/WebCommand.d.ts +9 -3
- package/dist/src/commands/WebCommand.js +17 -8
- 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-store.d.ts +0 -1
- package/dist/src/config-store.js +3 -4
- package/dist/src/config.d.ts +1 -1
- package/dist/src/config.js +1 -1
- package/dist/src/constants.d.ts +15 -0
- package/dist/src/constants.js +34 -6
- package/dist/src/container.d.ts +4 -2
- package/dist/src/container.js +7 -5
- package/dist/src/db/drizzle-types.d.ts +7 -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/declarations/DeclarationTree.d.ts +1 -1
- package/dist/src/eval-results.js +16 -2
- package/dist/src/eval-vector-index.d.ts +5 -0
- package/dist/src/eval-vector-index.js +60 -0
- package/dist/src/help.js +9 -1
- 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 +2 -1
- 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/IDatabase.d.ts +6 -2
- package/dist/src/interfaces/IDependencyGraph.d.ts +24 -0
- package/dist/src/interfaces/IDependencyGraph.js +2 -0
- 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/IMcpReadiness.d.ts +12 -0
- package/dist/src/interfaces/IMcpReadiness.js +2 -0
- package/dist/src/interfaces/IProjectCatalog.d.ts +13 -0
- package/dist/src/interfaces/IProjectCatalog.js +2 -0
- package/dist/src/interfaces/IProjectRoots.d.ts +3 -0
- package/dist/src/interfaces/IProjectRoots.js +2 -0
- package/dist/src/interfaces/IRetrievalEvaluator.d.ts +21 -2
- 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/project-scope.d.ts +1 -0
- package/dist/src/project-scope.js +5 -0
- package/dist/src/retrieval-eval.d.ts +2 -1
- package/dist/src/retrieval-eval.js +45 -2
- 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/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 +8 -44
- package/dist/src/services/AstParserService.js +19 -938
- package/dist/src/services/DatabaseService.d.ts +8 -10
- package/dist/src/services/DatabaseService.js +29 -86
- package/dist/src/services/IndexerService.d.ts +7 -10
- package/dist/src/services/IndexerService.js +36 -255
- package/dist/src/services/McpReadiness.d.ts +18 -0
- package/dist/src/services/McpReadiness.js +73 -0
- package/dist/src/services/McpServer.d.ts +32 -9
- package/dist/src/services/McpServer.js +78 -41
- package/dist/src/services/WebServerService.d.ts +4 -3
- package/dist/src/services/WebServerService.js +16 -8
- package/dist/src/setup.d.ts +16 -4
- package/dist/src/setup.js +115 -40
- package/dist/src/symbol-name.d.ts +1 -0
- package/dist/src/symbol-name.js +16 -12
- 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 +35 -28
- package/dist/src/tools/GetDependentsTool.d.ts +20 -8
- package/dist/src/tools/GetDependentsTool.js +47 -33
- 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 +69 -51
- package/dist/src/tools/format-helpers.d.ts +9 -3
- package/dist/src/tools/format-helpers.js +59 -14
- package/dist/src/tools/tool-args.d.ts +38 -0
- package/dist/src/tools/tool-args.js +95 -0
- 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 +4 -3
- package/dist/src/interfaces/ISearcher.d.ts +0 -46
- package/dist/src/services/SearcherService.d.ts +0 -235
- package/dist/src/services/SearcherService.js +0 -1118
- /package/dist/src/{interfaces/ISearcher.js → db/drizzle-types.js} +0 -0
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.ProjectRoots = void 0;
|
|
37
|
+
const path = __importStar(require("path"));
|
|
38
|
+
const MonorepoAwareDiscoveryService_1 = require("../services/MonorepoAwareDiscoveryService");
|
|
39
|
+
const path_helpers_1 = require("./path-helpers");
|
|
40
|
+
class ProjectRoots {
|
|
41
|
+
discovery;
|
|
42
|
+
config;
|
|
43
|
+
rootMap;
|
|
44
|
+
constructor(discovery, config) {
|
|
45
|
+
this.discovery = discovery;
|
|
46
|
+
this.config = config;
|
|
47
|
+
}
|
|
48
|
+
projectRootMap() {
|
|
49
|
+
if (!this.rootMap) {
|
|
50
|
+
this.rootMap = new Map((0, MonorepoAwareDiscoveryService_1.toLeafProjects)(this.discovery.discover(this.config.workspaceRoot)).map(p => [p.name, p.path]));
|
|
51
|
+
}
|
|
52
|
+
return this.rootMap;
|
|
53
|
+
}
|
|
54
|
+
entries() {
|
|
55
|
+
return this.projectRootMap().entries();
|
|
56
|
+
}
|
|
57
|
+
refresh() {
|
|
58
|
+
this.rootMap = undefined;
|
|
59
|
+
}
|
|
60
|
+
resolveProjectRoot(name) {
|
|
61
|
+
let root = this.projectRootMap().get(name);
|
|
62
|
+
if (root === undefined) {
|
|
63
|
+
this.rootMap = undefined;
|
|
64
|
+
root = this.projectRootMap().get(name);
|
|
65
|
+
}
|
|
66
|
+
return root ?? path.join(this.config.workspaceRoot, name);
|
|
67
|
+
}
|
|
68
|
+
toRel(absPath) {
|
|
69
|
+
return path.relative(this.config.workspaceRoot, absPath) || '.';
|
|
70
|
+
}
|
|
71
|
+
toAbs(relPath) {
|
|
72
|
+
return relPath === '.' ? this.workspaceRoot() : path.join(this.workspaceRoot(), relPath);
|
|
73
|
+
}
|
|
74
|
+
workspaceRoot() {
|
|
75
|
+
return (0, path_helpers_1.stripTrailingSlash)(path.posix.normalize(this.config.workspaceRoot));
|
|
76
|
+
}
|
|
77
|
+
findProjectRootByName(name) {
|
|
78
|
+
let root = this.projectRootMap().get(name);
|
|
79
|
+
if (root === undefined) {
|
|
80
|
+
this.rootMap = undefined;
|
|
81
|
+
root = this.projectRootMap().get(name);
|
|
82
|
+
}
|
|
83
|
+
return root === undefined ? null : this.toRel(root);
|
|
84
|
+
}
|
|
85
|
+
findProjectRoot(match) {
|
|
86
|
+
for (let attempt = 0; attempt < 2; attempt++) {
|
|
87
|
+
if (attempt === 1)
|
|
88
|
+
this.rootMap = undefined;
|
|
89
|
+
const best = [...this.projectRootMap().entries()]
|
|
90
|
+
.map(([name, abs]) => ({ name, rel: this.toRel(abs) }))
|
|
91
|
+
.filter(r => match(r.rel))
|
|
92
|
+
.sort((a, b) => b.rel.length - a.rel.length)[0];
|
|
93
|
+
if (best)
|
|
94
|
+
return best;
|
|
95
|
+
}
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
fallbackRoot(relPath) {
|
|
99
|
+
return this.findProjectRoot(r => (0, path_helpers_1.isWithin)(relPath, r))?.rel ?? null;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
exports.ProjectRoots = ProjectRoots;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { IDatabase, ILogger } from '../interfaces';
|
|
2
|
+
import type { IToolPaths, PathFailure, ResolvedToolPath } from '../interfaces/IToolPaths';
|
|
3
|
+
import { type WorkspaceFs } from './fs-access';
|
|
4
|
+
import type { ProjectRoots } from './ProjectRoots';
|
|
5
|
+
export declare class ToolPaths implements IToolPaths {
|
|
6
|
+
private db;
|
|
7
|
+
private roots;
|
|
8
|
+
private logger;
|
|
9
|
+
private fs;
|
|
10
|
+
private realRootCache?;
|
|
11
|
+
constructor(db: IDatabase, roots: ProjectRoots, logger: ILogger, fs: WorkspaceFs);
|
|
12
|
+
private realWorkspaceRoot;
|
|
13
|
+
resolveToolPath(input: string | null | undefined): Promise<ResolvedToolPath>;
|
|
14
|
+
private realLocation;
|
|
15
|
+
checkRealLocation(relPath: string, absPath: string, kind: 'file' | 'dir'): Promise<{
|
|
16
|
+
ok: true;
|
|
17
|
+
} | Extract<PathFailure, {
|
|
18
|
+
reason: 'outside_workspace' | 'unreadable';
|
|
19
|
+
}>>;
|
|
20
|
+
grepSearchDir(project: string): Promise<string | null>;
|
|
21
|
+
private pathExists;
|
|
22
|
+
isIndexedPath(relPath: string): Promise<boolean>;
|
|
23
|
+
isContentPath(relPath: string): Promise<boolean>;
|
|
24
|
+
private hasContentUnder;
|
|
25
|
+
findPathCandidates(relPath: string, kind: 'file' | 'dir'): Promise<string[]>;
|
|
26
|
+
candidatesOrNone(relPath: string, kind: 'file' | 'dir'): Promise<string[]>;
|
|
27
|
+
private nearNames;
|
|
28
|
+
private substituteProjectName;
|
|
29
|
+
checkGraphPath(relPath: string): Promise<PathFailure | null>;
|
|
30
|
+
private explainNotIndexed;
|
|
31
|
+
}
|
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.ToolPaths = void 0;
|
|
37
|
+
const path = __importStar(require("path"));
|
|
38
|
+
const file_utils_1 = require("../file-utils");
|
|
39
|
+
const symbol_name_1 = require("../symbol-name");
|
|
40
|
+
const index_paths_1 = require("../search/index-paths");
|
|
41
|
+
const fs_access_1 = require("./fs-access");
|
|
42
|
+
const path_helpers_1 = require("./path-helpers");
|
|
43
|
+
const PATH_MAX_BYTES = 4096;
|
|
44
|
+
const PATH_CANDIDATE_LIMIT = 3;
|
|
45
|
+
const NEAR_NAME_MAX_DISTANCE = 2;
|
|
46
|
+
const INDEX_PATH_COLUMNS = [
|
|
47
|
+
{ table: 'code_chunk', column: '"filePath"', content: true },
|
|
48
|
+
{ table: 'code_symbol', column: '"filePath"', content: true },
|
|
49
|
+
{ table: 'code_dependency', column: '"fromFile"', content: true },
|
|
50
|
+
{ table: 'code_call', column: '"fromFile"', content: true },
|
|
51
|
+
{ table: 'code_dependency', column: '"toFile"', content: false },
|
|
52
|
+
{ table: 'code_call', column: '"calleeFile"', content: false },
|
|
53
|
+
];
|
|
54
|
+
class ToolPaths {
|
|
55
|
+
db;
|
|
56
|
+
roots;
|
|
57
|
+
logger;
|
|
58
|
+
fs;
|
|
59
|
+
realRootCache;
|
|
60
|
+
constructor(db, roots, logger, fs) {
|
|
61
|
+
this.db = db;
|
|
62
|
+
this.roots = roots;
|
|
63
|
+
this.logger = logger;
|
|
64
|
+
this.fs = fs;
|
|
65
|
+
}
|
|
66
|
+
async realWorkspaceRoot() {
|
|
67
|
+
if (this.realRootCache !== undefined)
|
|
68
|
+
return this.realRootCache;
|
|
69
|
+
try {
|
|
70
|
+
this.realRootCache = await this.fs.realpath(this.roots.workspaceRoot());
|
|
71
|
+
return this.realRootCache;
|
|
72
|
+
}
|
|
73
|
+
catch (err) {
|
|
74
|
+
this.logger.warn('ToolPaths: workspaceRoot real path unavailable', { reason: (0, fs_access_1.errorCode)(err) });
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
async resolveToolPath(input) {
|
|
79
|
+
if (input == null || input === '')
|
|
80
|
+
return { ok: false, reason: 'invalid', missing: true };
|
|
81
|
+
if (input.includes('\\'))
|
|
82
|
+
return { ok: false, reason: 'invalid', missing: false };
|
|
83
|
+
if (Buffer.byteLength(input) >= PATH_MAX_BYTES)
|
|
84
|
+
return { ok: false, reason: 'unreadable', code: 'ENAMETOOLONG' };
|
|
85
|
+
if (path.posix.isAbsolute(input)) {
|
|
86
|
+
const abs = (0, path_helpers_1.stripTrailingSlash)(path.posix.normalize(input));
|
|
87
|
+
const realRoot = await this.realWorkspaceRoot();
|
|
88
|
+
for (const root of realRoot ? [this.roots.workspaceRoot(), realRoot] : [this.roots.workspaceRoot()]) {
|
|
89
|
+
if (!(0, path_helpers_1.isWithin)(abs, root))
|
|
90
|
+
continue;
|
|
91
|
+
const relative = abs === root ? '.' : abs.slice(root === '/' ? 1 : root.length + 1);
|
|
92
|
+
return { ok: false, reason: 'absolute', relative };
|
|
93
|
+
}
|
|
94
|
+
return { ok: false, reason: 'outside_workspace' };
|
|
95
|
+
}
|
|
96
|
+
const relPath = (0, path_helpers_1.stripTrailingSlash)(path.posix.normalize(input));
|
|
97
|
+
if (relPath === '..' || relPath.startsWith('../'))
|
|
98
|
+
return { ok: false, reason: 'outside_workspace' };
|
|
99
|
+
return { ok: true, relPath, absPath: this.roots.toAbs(relPath) };
|
|
100
|
+
}
|
|
101
|
+
async realLocation(absPath) {
|
|
102
|
+
if (Buffer.byteLength(absPath) >= PATH_MAX_BYTES)
|
|
103
|
+
return { ok: false, code: 'ENAMETOOLONG' };
|
|
104
|
+
const root = (await this.realWorkspaceRoot()) ?? this.roots.workspaceRoot();
|
|
105
|
+
let existing = absPath;
|
|
106
|
+
const rest = [];
|
|
107
|
+
for (;;) {
|
|
108
|
+
try {
|
|
109
|
+
const real = path.join(await this.fs.realpath(existing), ...rest);
|
|
110
|
+
return { ok: true, inside: (0, path_helpers_1.isWithin)(real, root) };
|
|
111
|
+
}
|
|
112
|
+
catch (err) {
|
|
113
|
+
if ((0, fs_access_1.errorCode)(err) !== 'ENOENT')
|
|
114
|
+
return { ok: false, code: (0, fs_access_1.errorCode)(err) };
|
|
115
|
+
const parent = path.dirname(existing);
|
|
116
|
+
if (parent === existing)
|
|
117
|
+
return { ok: true, inside: false };
|
|
118
|
+
rest.unshift(path.basename(existing));
|
|
119
|
+
existing = parent;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
async checkRealLocation(relPath, absPath, kind) {
|
|
124
|
+
const loc = await this.realLocation(absPath);
|
|
125
|
+
if (!loc.ok)
|
|
126
|
+
return { ok: false, reason: 'unreadable', code: loc.code };
|
|
127
|
+
if (loc.inside)
|
|
128
|
+
return { ok: true };
|
|
129
|
+
const exempt = kind === 'file' ? await this.isContentPath(relPath) : await this.hasContentUnder(relPath);
|
|
130
|
+
return exempt ? { ok: true } : { ok: false, reason: 'outside_workspace' };
|
|
131
|
+
}
|
|
132
|
+
async grepSearchDir(project) {
|
|
133
|
+
let discovered;
|
|
134
|
+
try {
|
|
135
|
+
discovered = this.roots.findProjectRootByName(project);
|
|
136
|
+
}
|
|
137
|
+
catch (err) {
|
|
138
|
+
this.logger.error('ToolPaths: project discovery failed', { project, err });
|
|
139
|
+
return null;
|
|
140
|
+
}
|
|
141
|
+
let absDir;
|
|
142
|
+
if (discovered !== null) {
|
|
143
|
+
absDir = this.roots.toAbs(discovered);
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
if (Buffer.byteLength(project) >= PATH_MAX_BYTES)
|
|
147
|
+
return null;
|
|
148
|
+
absDir = path.join(this.roots.workspaceRoot(), project);
|
|
149
|
+
const loc = await this.realLocation(absDir);
|
|
150
|
+
if (!loc.ok || !loc.inside)
|
|
151
|
+
return null;
|
|
152
|
+
}
|
|
153
|
+
try {
|
|
154
|
+
return (await this.fs.stat(absDir)).isDirectory() ? absDir : null;
|
|
155
|
+
}
|
|
156
|
+
catch (err) {
|
|
157
|
+
const code = (0, fs_access_1.errorCode)(err);
|
|
158
|
+
return code === 'ENOENT' || code === 'ENOTDIR' ? null : absDir;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
async pathExists(columns, predicate, param) {
|
|
162
|
+
const branches = columns.map(c => `SELECT 1 FROM ${c.table} WHERE ${predicate.replace(/\$col/g, c.column)}`);
|
|
163
|
+
const [{ exists }] = await this.db.query(`SELECT EXISTS (${branches.join(' UNION ALL ')}) AS exists`, [param]);
|
|
164
|
+
return exists;
|
|
165
|
+
}
|
|
166
|
+
isIndexedPath(relPath) {
|
|
167
|
+
return this.pathExists(INDEX_PATH_COLUMNS, '$col = $1', relPath);
|
|
168
|
+
}
|
|
169
|
+
isContentPath(relPath) {
|
|
170
|
+
return this.pathExists(INDEX_PATH_COLUMNS.filter(c => c.content), '$col = $1', relPath);
|
|
171
|
+
}
|
|
172
|
+
hasContentUnder(relPath) {
|
|
173
|
+
const prefix = relPath === '.' ? '' : (0, symbol_name_1.escapeLike)(relPath) + '/';
|
|
174
|
+
return this.pathExists(INDEX_PATH_COLUMNS.filter(c => c.content), `$col LIKE $1 ESCAPE '\\'`, prefix + '%');
|
|
175
|
+
}
|
|
176
|
+
async findPathCandidates(relPath, kind) {
|
|
177
|
+
const union = INDEX_PATH_COLUMNS.map(c => `SELECT ${c.column} AS p FROM ${c.table}`).join(' UNION ALL ');
|
|
178
|
+
const notOutside = `NOT ${(0, index_paths_1.OUTSIDE_WORKSPACE_VALUE)('p')}`;
|
|
179
|
+
if (kind === 'file') {
|
|
180
|
+
const substituted = await this.substituteProjectName(relPath);
|
|
181
|
+
const rows = await this.db.query(`SELECT p FROM (${union}) s
|
|
182
|
+
WHERE p LIKE $1 ESCAPE '\\' AND ${notOutside}
|
|
183
|
+
GROUP BY p ORDER BY p COLLATE "C" LIMIT ${PATH_CANDIDATE_LIMIT + 1}`, ['%/' + (0, symbol_name_1.escapeLike)(relPath)]);
|
|
184
|
+
const first = substituted ? [substituted] : [];
|
|
185
|
+
return [...first, ...rows.map(r => r.p).filter(p => p !== substituted)].slice(0, PATH_CANDIDATE_LIMIT);
|
|
186
|
+
}
|
|
187
|
+
const projectRoot = this.roots.findProjectRootByName(relPath);
|
|
188
|
+
const first = projectRoot && projectRoot !== relPath ? [projectRoot] : [];
|
|
189
|
+
const rows = await this.db.query(`SELECT d AS p FROM (
|
|
190
|
+
SELECT substring(p FROM 1 FOR position($2::text IN p) + length($3::text)) AS d
|
|
191
|
+
FROM (${union}) s
|
|
192
|
+
WHERE p LIKE $1 ESCAPE '\\' AND ${notOutside}
|
|
193
|
+
) dirs
|
|
194
|
+
GROUP BY d ORDER BY d COLLATE "C" LIMIT ${PATH_CANDIDATE_LIMIT + 1}`, ['%/' + (0, symbol_name_1.escapeLike)(relPath) + '/%', '/' + relPath + '/', relPath]);
|
|
195
|
+
const rest = rows.map(r => r.p).filter(p => !first.includes(p));
|
|
196
|
+
return [...first, ...rest].slice(0, PATH_CANDIDATE_LIMIT);
|
|
197
|
+
}
|
|
198
|
+
async candidatesOrNone(relPath, kind) {
|
|
199
|
+
let candidates;
|
|
200
|
+
try {
|
|
201
|
+
candidates = await this.findPathCandidates(relPath, kind);
|
|
202
|
+
}
|
|
203
|
+
catch (err) {
|
|
204
|
+
this.logger.error('ToolPaths: path candidate lookup failed', { relPath, err });
|
|
205
|
+
return [];
|
|
206
|
+
}
|
|
207
|
+
if (candidates.length >= PATH_CANDIDATE_LIMIT)
|
|
208
|
+
return candidates;
|
|
209
|
+
const near = (await this.nearNames(relPath, kind)).filter(p => !candidates.includes(p));
|
|
210
|
+
return [...candidates, ...near].slice(0, PATH_CANDIDATE_LIMIT);
|
|
211
|
+
}
|
|
212
|
+
async nearNames(relPath, kind) {
|
|
213
|
+
if (relPath === '.')
|
|
214
|
+
return [];
|
|
215
|
+
const parent = path.posix.dirname(relPath);
|
|
216
|
+
const segment = path.posix.basename(relPath);
|
|
217
|
+
const absParent = this.roots.toAbs(parent);
|
|
218
|
+
let entries;
|
|
219
|
+
try {
|
|
220
|
+
const loc = await this.realLocation(absParent);
|
|
221
|
+
if (!loc.ok)
|
|
222
|
+
throw Object.assign(new Error(`real location unavailable: ${loc.code}`), { code: loc.code });
|
|
223
|
+
if (!loc.inside)
|
|
224
|
+
return [];
|
|
225
|
+
entries = await this.fs.readdir(absParent);
|
|
226
|
+
}
|
|
227
|
+
catch (err) {
|
|
228
|
+
const code = (0, fs_access_1.errorCode)(err);
|
|
229
|
+
if (code === 'ENOENT' || code === 'ENOTDIR')
|
|
230
|
+
return [];
|
|
231
|
+
this.logger.error('ToolPaths: near-name lookup failed', { relPath, err });
|
|
232
|
+
return [];
|
|
233
|
+
}
|
|
234
|
+
const segmentLength = [...segment].length;
|
|
235
|
+
const near = [];
|
|
236
|
+
for (const entry of entries) {
|
|
237
|
+
if (kind === 'file' ? !entry.isFile() : !entry.isDirectory())
|
|
238
|
+
continue;
|
|
239
|
+
if (file_utils_1.IGNORE_DIRS.has(entry.name))
|
|
240
|
+
continue;
|
|
241
|
+
const distance = (0, path_helpers_1.editDistance)(entry.name, segment, NEAR_NAME_MAX_DISTANCE);
|
|
242
|
+
if (distance > NEAR_NAME_MAX_DISTANCE || distance >= segmentLength / 2)
|
|
243
|
+
continue;
|
|
244
|
+
near.push({ name: entry.name, distance });
|
|
245
|
+
}
|
|
246
|
+
near.sort((a, b) => a.distance - b.distance || Buffer.compare(Buffer.from(a.name, 'utf8'), Buffer.from(b.name, 'utf8')));
|
|
247
|
+
return near.slice(0, PATH_CANDIDATE_LIMIT).map(e => (parent === '.' ? e.name : `${parent}/${e.name}`));
|
|
248
|
+
}
|
|
249
|
+
async substituteProjectName(relPath) {
|
|
250
|
+
let named = [];
|
|
251
|
+
for (let attempt = 0; attempt < 2 && named.length === 0; attempt++) {
|
|
252
|
+
if (attempt === 1)
|
|
253
|
+
this.roots.refresh();
|
|
254
|
+
named = [...this.roots.entries()].filter(([name]) => relPath.startsWith(name + '/'));
|
|
255
|
+
}
|
|
256
|
+
const longest = named.sort((a, b) => b[0].length - a[0].length)[0];
|
|
257
|
+
if (!longest)
|
|
258
|
+
return null;
|
|
259
|
+
const [name, absRoot] = longest;
|
|
260
|
+
const root = this.roots.toRel(absRoot);
|
|
261
|
+
if (root === name)
|
|
262
|
+
return null;
|
|
263
|
+
const candidate = (root === '.' ? '' : root + '/') + relPath.slice(name.length + 1);
|
|
264
|
+
if (await this.isIndexedPath(candidate))
|
|
265
|
+
return candidate;
|
|
266
|
+
try {
|
|
267
|
+
return (await this.fs.stat(this.roots.toAbs(candidate))).isFile() ? candidate : null;
|
|
268
|
+
}
|
|
269
|
+
catch {
|
|
270
|
+
return null;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
async checkGraphPath(relPath) {
|
|
274
|
+
if (await this.isIndexedPath(relPath))
|
|
275
|
+
return null;
|
|
276
|
+
const absPath = this.roots.toAbs(relPath);
|
|
277
|
+
const loc = await this.realLocation(absPath);
|
|
278
|
+
if (!loc.ok)
|
|
279
|
+
return { ok: false, reason: 'unreadable', code: loc.code };
|
|
280
|
+
if (!loc.inside)
|
|
281
|
+
return { ok: false, reason: 'not_found', candidates: await this.candidatesOrNone(relPath, 'file') };
|
|
282
|
+
let stat;
|
|
283
|
+
try {
|
|
284
|
+
stat = await this.fs.stat(absPath);
|
|
285
|
+
}
|
|
286
|
+
catch (err) {
|
|
287
|
+
if ((0, fs_access_1.errorCode)(err) !== 'ENOENT')
|
|
288
|
+
return { ok: false, reason: 'unreadable', code: (0, fs_access_1.errorCode)(err) };
|
|
289
|
+
return { ok: false, reason: 'not_found', candidates: await this.candidatesOrNone(relPath, 'file') };
|
|
290
|
+
}
|
|
291
|
+
if (!stat.isFile())
|
|
292
|
+
return { ok: false, reason: 'not_a_file' };
|
|
293
|
+
return { ok: false, reason: 'not_indexed', explanation: await this.explainNotIndexed(relPath) };
|
|
294
|
+
}
|
|
295
|
+
async explainNotIndexed(relPath) {
|
|
296
|
+
const owner = this.roots.findProjectRoot(r => r !== relPath && (0, path_helpers_1.isWithin)(relPath, r));
|
|
297
|
+
if (!owner)
|
|
298
|
+
return { kind: 'no_project' };
|
|
299
|
+
const inProject = owner.rel === '.' ? relPath : relPath.slice(owner.rel.length + 1);
|
|
300
|
+
const exclusion = (0, file_utils_1.indexingExclusion)(inProject, (0, file_utils_1.loadIgnore)(this.roots.toAbs(owner.rel)));
|
|
301
|
+
if (exclusion)
|
|
302
|
+
return exclusion;
|
|
303
|
+
const [{ exists }] = await this.db.query(`SELECT EXISTS (
|
|
304
|
+
SELECT 1 FROM code_chunk WHERE "serviceName" = $1
|
|
305
|
+
UNION ALL SELECT 1 FROM code_symbol WHERE project = $1
|
|
306
|
+
UNION ALL SELECT 1 FROM code_dependency WHERE project = $1
|
|
307
|
+
UNION ALL SELECT 1 FROM code_call WHERE project = $1
|
|
308
|
+
) AS exists`, [owner.name]);
|
|
309
|
+
return exists ? { kind: 'unknown' } : { kind: 'project_not_indexed', project: owner.name };
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
exports.ToolPaths = ToolPaths;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { ILogger } from '../interfaces';
|
|
2
|
+
import type { FileRangeResult, IWorkspaceFiles, ListFilesResult } from '../interfaces/IWorkspaceFiles';
|
|
3
|
+
import { type WorkspaceFs } from './fs-access';
|
|
4
|
+
import type { ProjectRoots } from './ProjectRoots';
|
|
5
|
+
import type { ToolPaths } from './ToolPaths';
|
|
6
|
+
export declare class WorkspaceFiles implements IWorkspaceFiles {
|
|
7
|
+
private paths;
|
|
8
|
+
private roots;
|
|
9
|
+
private logger;
|
|
10
|
+
private fs;
|
|
11
|
+
constructor(paths: ToolPaths, roots: ProjectRoots, logger: ILogger, fs: WorkspaceFs);
|
|
12
|
+
listFiles(relPath: string, depth: number, pattern: string | null): Promise<ListFilesResult>;
|
|
13
|
+
private openableFile;
|
|
14
|
+
private readLines;
|
|
15
|
+
private readFailure;
|
|
16
|
+
readFile(relPath: string, maxLines: number): Promise<FileRangeResult>;
|
|
17
|
+
readFileRange(relPath: string, startLine: number, endLine: number): Promise<FileRangeResult>;
|
|
18
|
+
private walkDir;
|
|
19
|
+
}
|