@ai-agent-context/core 0.1.0
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/LICENSE +21 -0
- package/README.md +285 -0
- package/dist/.tsbuildinfo +1 -0
- package/dist/adapters/filesystem/fs-adapter.d.ts +50 -0
- package/dist/adapters/filesystem/fs-adapter.d.ts.map +1 -0
- package/dist/adapters/filesystem/fs-adapter.js +168 -0
- package/dist/adapters/filesystem/fs-adapter.js.map +1 -0
- package/dist/adapters/filesystem/sensitive.d.ts +26 -0
- package/dist/adapters/filesystem/sensitive.d.ts.map +1 -0
- package/dist/adapters/filesystem/sensitive.js +67 -0
- package/dist/adapters/filesystem/sensitive.js.map +1 -0
- package/dist/adapters/git/git-adapter.d.ts +47 -0
- package/dist/adapters/git/git-adapter.d.ts.map +1 -0
- package/dist/adapters/git/git-adapter.js +109 -0
- package/dist/adapters/git/git-adapter.js.map +1 -0
- package/dist/adapters/language/json/adapter.d.ts +24 -0
- package/dist/adapters/language/json/adapter.d.ts.map +1 -0
- package/dist/adapters/language/json/adapter.js +54 -0
- package/dist/adapters/language/json/adapter.js.map +1 -0
- package/dist/adapters/language/markdown/adapter.d.ts +41 -0
- package/dist/adapters/language/markdown/adapter.d.ts.map +1 -0
- package/dist/adapters/language/markdown/adapter.js +124 -0
- package/dist/adapters/language/markdown/adapter.js.map +1 -0
- package/dist/adapters/language/package-json/adapter.d.ts +47 -0
- package/dist/adapters/language/package-json/adapter.d.ts.map +1 -0
- package/dist/adapters/language/package-json/adapter.js +153 -0
- package/dist/adapters/language/package-json/adapter.js.map +1 -0
- package/dist/adapters/language/registry.d.ts +35 -0
- package/dist/adapters/language/registry.d.ts.map +1 -0
- package/dist/adapters/language/registry.js +79 -0
- package/dist/adapters/language/registry.js.map +1 -0
- package/dist/adapters/language/ts-js/adapter.d.ts +14 -0
- package/dist/adapters/language/ts-js/adapter.d.ts.map +1 -0
- package/dist/adapters/language/ts-js/adapter.js +59 -0
- package/dist/adapters/language/ts-js/adapter.js.map +1 -0
- package/dist/adapters/language/ts-js/extractor.d.ts +21 -0
- package/dist/adapters/language/ts-js/extractor.d.ts.map +1 -0
- package/dist/adapters/language/ts-js/extractor.js +779 -0
- package/dist/adapters/language/ts-js/extractor.js.map +1 -0
- package/dist/adapters/language/ts-js/lexer.d.ts +30 -0
- package/dist/adapters/language/ts-js/lexer.d.ts.map +1 -0
- package/dist/adapters/language/ts-js/lexer.js +446 -0
- package/dist/adapters/language/ts-js/lexer.js.map +1 -0
- package/dist/adapters/language/ts-js/package-signals.d.ts +5 -0
- package/dist/adapters/language/ts-js/package-signals.d.ts.map +1 -0
- package/dist/adapters/language/ts-js/package-signals.js +113 -0
- package/dist/adapters/language/ts-js/package-signals.js.map +1 -0
- package/dist/adapters/language/tsconfig/adapter.d.ts +38 -0
- package/dist/adapters/language/tsconfig/adapter.d.ts.map +1 -0
- package/dist/adapters/language/tsconfig/adapter.js +130 -0
- package/dist/adapters/language/tsconfig/adapter.js.map +1 -0
- package/dist/adapters/language/types.d.ts +152 -0
- package/dist/adapters/language/types.d.ts.map +1 -0
- package/dist/adapters/language/types.js +51 -0
- package/dist/adapters/language/types.js.map +1 -0
- package/dist/agent-context.d.ts +122 -0
- package/dist/agent-context.d.ts.map +1 -0
- package/dist/agent-context.js +243 -0
- package/dist/agent-context.js.map +1 -0
- package/dist/config/defaults.d.ts +13 -0
- package/dist/config/defaults.d.ts.map +1 -0
- package/dist/config/defaults.js +98 -0
- package/dist/config/defaults.js.map +1 -0
- package/dist/config/load.d.ts +25 -0
- package/dist/config/load.d.ts.map +1 -0
- package/dist/config/load.js +106 -0
- package/dist/config/load.js.map +1 -0
- package/dist/config/types.d.ts +95 -0
- package/dist/config/types.d.ts.map +1 -0
- package/dist/config/types.js +8 -0
- package/dist/config/types.js.map +1 -0
- package/dist/config/validate.d.ts +15 -0
- package/dist/config/validate.d.ts.map +1 -0
- package/dist/config/validate.js +202 -0
- package/dist/config/validate.js.map +1 -0
- package/dist/core/architecture/detector.d.ts +10 -0
- package/dist/core/architecture/detector.d.ts.map +1 -0
- package/dist/core/architecture/detector.js +37 -0
- package/dist/core/architecture/detector.js.map +1 -0
- package/dist/core/architecture/entry-points.d.ts +20 -0
- package/dist/core/architecture/entry-points.d.ts.map +1 -0
- package/dist/core/architecture/entry-points.js +190 -0
- package/dist/core/architecture/entry-points.js.map +1 -0
- package/dist/core/architecture/role-detector.d.ts +32 -0
- package/dist/core/architecture/role-detector.d.ts.map +1 -0
- package/dist/core/architecture/role-detector.js +240 -0
- package/dist/core/architecture/role-detector.js.map +1 -0
- package/dist/core/context/explain.d.ts +36 -0
- package/dist/core/context/explain.d.ts.map +1 -0
- package/dist/core/context/explain.js +199 -0
- package/dist/core/context/explain.js.map +1 -0
- package/dist/core/context/repository-context.d.ts +16 -0
- package/dist/core/context/repository-context.d.ts.map +1 -0
- package/dist/core/context/repository-context.js +134 -0
- package/dist/core/context/repository-context.js.map +1 -0
- package/dist/core/context/types.d.ts +94 -0
- package/dist/core/context/types.d.ts.map +1 -0
- package/dist/core/context/types.js +2 -0
- package/dist/core/context/types.js.map +1 -0
- package/dist/core/conventions/detector.d.ts +55 -0
- package/dist/core/conventions/detector.d.ts.map +1 -0
- package/dist/core/conventions/detector.js +438 -0
- package/dist/core/conventions/detector.js.map +1 -0
- package/dist/core/conventions/renderer.d.ts +16 -0
- package/dist/core/conventions/renderer.d.ts.map +1 -0
- package/dist/core/conventions/renderer.js +42 -0
- package/dist/core/conventions/renderer.js.map +1 -0
- package/dist/core/decisions/detector.d.ts +45 -0
- package/dist/core/decisions/detector.d.ts.map +1 -0
- package/dist/core/decisions/detector.js +256 -0
- package/dist/core/decisions/detector.js.map +1 -0
- package/dist/core/diff/differ.d.ts +26 -0
- package/dist/core/diff/differ.d.ts.map +1 -0
- package/dist/core/diff/differ.js +159 -0
- package/dist/core/diff/differ.js.map +1 -0
- package/dist/core/git-analysis/activity.d.ts +35 -0
- package/dist/core/git-analysis/activity.d.ts.map +1 -0
- package/dist/core/git-analysis/activity.js +123 -0
- package/dist/core/git-analysis/activity.js.map +1 -0
- package/dist/core/graph/aliases.d.ts +20 -0
- package/dist/core/graph/aliases.d.ts.map +1 -0
- package/dist/core/graph/aliases.js +99 -0
- package/dist/core/graph/aliases.js.map +1 -0
- package/dist/core/graph/knowledge-graph.d.ts +91 -0
- package/dist/core/graph/knowledge-graph.d.ts.map +1 -0
- package/dist/core/graph/knowledge-graph.js +572 -0
- package/dist/core/graph/knowledge-graph.js.map +1 -0
- package/dist/core/graph/modules.d.ts +28 -0
- package/dist/core/graph/modules.d.ts.map +1 -0
- package/dist/core/graph/modules.js +139 -0
- package/dist/core/graph/modules.js.map +1 -0
- package/dist/core/graph/resolver.d.ts +50 -0
- package/dist/core/graph/resolver.d.ts.map +1 -0
- package/dist/core/graph/resolver.js +180 -0
- package/dist/core/graph/resolver.js.map +1 -0
- package/dist/core/scanner/cache.d.ts +49 -0
- package/dist/core/scanner/cache.d.ts.map +1 -0
- package/dist/core/scanner/cache.js +101 -0
- package/dist/core/scanner/cache.js.map +1 -0
- package/dist/core/scanner/scanner.d.ts +60 -0
- package/dist/core/scanner/scanner.d.ts.map +1 -0
- package/dist/core/scanner/scanner.js +304 -0
- package/dist/core/scanner/scanner.js.map +1 -0
- package/dist/core/scanner/types.d.ts +47 -0
- package/dist/core/scanner/types.d.ts.map +1 -0
- package/dist/core/scanner/types.js +18 -0
- package/dist/core/scanner/types.js.map +1 -0
- package/dist/core/search/analyzer.d.ts +16 -0
- package/dist/core/search/analyzer.d.ts.map +1 -0
- package/dist/core/search/analyzer.js +165 -0
- package/dist/core/search/analyzer.js.map +1 -0
- package/dist/core/search/bm25.d.ts +21 -0
- package/dist/core/search/bm25.d.ts.map +1 -0
- package/dist/core/search/bm25.js +108 -0
- package/dist/core/search/bm25.js.map +1 -0
- package/dist/core/search/documents.d.ts +20 -0
- package/dist/core/search/documents.d.ts.map +1 -0
- package/dist/core/search/documents.js +106 -0
- package/dist/core/search/documents.js.map +1 -0
- package/dist/core/search/service.d.ts +30 -0
- package/dist/core/search/service.d.ts.map +1 -0
- package/dist/core/search/service.js +54 -0
- package/dist/core/search/service.js.map +1 -0
- package/dist/core/search/types.d.ts +44 -0
- package/dist/core/search/types.d.ts.map +1 -0
- package/dist/core/search/types.js +2 -0
- package/dist/core/search/types.js.map +1 -0
- package/dist/core/serialization/documents.d.ts +26 -0
- package/dist/core/serialization/documents.d.ts.map +1 -0
- package/dist/core/serialization/documents.js +224 -0
- package/dist/core/serialization/documents.js.map +1 -0
- package/dist/core/serialization/reader.d.ts +22 -0
- package/dist/core/serialization/reader.d.ts.map +1 -0
- package/dist/core/serialization/reader.js +65 -0
- package/dist/core/serialization/reader.js.map +1 -0
- package/dist/core/serialization/types.d.ts +184 -0
- package/dist/core/serialization/types.d.ts.map +1 -0
- package/dist/core/serialization/types.js +2 -0
- package/dist/core/serialization/types.js.map +1 -0
- package/dist/core/serialization/writer.d.ts +17 -0
- package/dist/core/serialization/writer.d.ts.map +1 -0
- package/dist/core/serialization/writer.js +64 -0
- package/dist/core/serialization/writer.js.map +1 -0
- package/dist/core/workspace/package-facts.d.ts +12 -0
- package/dist/core/workspace/package-facts.d.ts.map +1 -0
- package/dist/core/workspace/package-facts.js +50 -0
- package/dist/core/workspace/package-facts.js.map +1 -0
- package/dist/core/workspace/workspace.d.ts +32 -0
- package/dist/core/workspace/workspace.d.ts.map +1 -0
- package/dist/core/workspace/workspace.js +167 -0
- package/dist/core/workspace/workspace.js.map +1 -0
- package/dist/errors.d.ts +50 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +64 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +80 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +66 -0
- package/dist/index.js.map +1 -0
- package/dist/logging/diagnostics.d.ts +64 -0
- package/dist/logging/diagnostics.d.ts.map +1 -0
- package/dist/logging/diagnostics.js +92 -0
- package/dist/logging/diagnostics.js.map +1 -0
- package/dist/model/canonical.d.ts +24 -0
- package/dist/model/canonical.d.ts.map +1 -0
- package/dist/model/canonical.js +69 -0
- package/dist/model/canonical.js.map +1 -0
- package/dist/model/schema.d.ts +37 -0
- package/dist/model/schema.d.ts.map +1 -0
- package/dist/model/schema.js +42 -0
- package/dist/model/schema.js.map +1 -0
- package/dist/model/types.d.ts +402 -0
- package/dist/model/types.d.ts.map +1 -0
- package/dist/model/types.js +10 -0
- package/dist/model/types.js.map +1 -0
- package/dist/pipeline/scan-pipeline.d.ts +69 -0
- package/dist/pipeline/scan-pipeline.d.ts.map +1 -0
- package/dist/pipeline/scan-pipeline.js +270 -0
- package/dist/pipeline/scan-pipeline.js.map +1 -0
- package/dist/util/concurrency.d.ts +17 -0
- package/dist/util/concurrency.d.ts.map +1 -0
- package/dist/util/concurrency.js +46 -0
- package/dist/util/concurrency.js.map +1 -0
- package/dist/util/glob.d.ts +26 -0
- package/dist/util/glob.d.ts.map +1 -0
- package/dist/util/glob.js +198 -0
- package/dist/util/glob.js.map +1 -0
- package/dist/util/paths.d.ts +23 -0
- package/dist/util/paths.d.ts.map +1 -0
- package/dist/util/paths.js +115 -0
- package/dist/util/paths.js.map +1 -0
- package/dist/util/text.d.ts +22 -0
- package/dist/util/text.d.ts.map +1 -0
- package/dist/util/text.js +66 -0
- package/dist/util/text.js.map +1 -0
- package/package.json +52 -0
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { basename, depth, dirname, isInside, normalizeRelative, relativeTo, stem } from "../../util/paths.js";
|
|
2
|
+
import { compareStrings } from "../../model/canonical.js";
|
|
3
|
+
const ENTRY_NAME_PATTERN = /^(index|mod)\.[cm]?[jt]sx?$/;
|
|
4
|
+
function isModuleFile(file) {
|
|
5
|
+
return file.kind === 'source' || file.kind === 'test';
|
|
6
|
+
}
|
|
7
|
+
/** Directory of the nearest workspace package, or `null` when none contains the path. */
|
|
8
|
+
function owningPackageDirectory(workspace, filePath) {
|
|
9
|
+
const candidates = [...workspace.packages].sort((a, b) => b.path.length - a.path.length);
|
|
10
|
+
for (const entry of candidates) {
|
|
11
|
+
if (entry.path.length === 0 || isInside(entry.path, filePath)) {
|
|
12
|
+
return { directory: normalizeRelative(entry.path), name: entry.name };
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
export function buildModules(input) {
|
|
18
|
+
const moduleFiles = input.files.filter(isModuleFile);
|
|
19
|
+
const candidates = [];
|
|
20
|
+
const takenIds = new Set();
|
|
21
|
+
const addCandidate = (candidate) => {
|
|
22
|
+
if (candidates.some((entry) => entry.directory === candidate.directory))
|
|
23
|
+
return;
|
|
24
|
+
let id = candidate.id;
|
|
25
|
+
if (takenIds.has(id))
|
|
26
|
+
id = candidate.directory;
|
|
27
|
+
takenIds.add(id);
|
|
28
|
+
candidates.push({ ...candidate, id });
|
|
29
|
+
};
|
|
30
|
+
// 1. workspace packages are always modules
|
|
31
|
+
for (const entry of input.workspace.packages) {
|
|
32
|
+
addCandidate({
|
|
33
|
+
directory: normalizeRelative(entry.path),
|
|
34
|
+
basis: 'workspace-package',
|
|
35
|
+
id: entry.name,
|
|
36
|
+
packageName: entry.name,
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
const fileCountByDirectory = new Map();
|
|
40
|
+
const directoriesWithEntry = new Set();
|
|
41
|
+
for (const file of moduleFiles) {
|
|
42
|
+
const directory = normalizeRelative(dirname(file.path));
|
|
43
|
+
fileCountByDirectory.set(directory, (fileCountByDirectory.get(directory) ?? 0) + 1);
|
|
44
|
+
if (ENTRY_NAME_PATTERN.test(basename(file.path)))
|
|
45
|
+
directoriesWithEntry.add(directory);
|
|
46
|
+
}
|
|
47
|
+
// 2. directories exposing an index/mod entry file
|
|
48
|
+
for (const directory of [...directoriesWithEntry].sort(compareStrings)) {
|
|
49
|
+
const ownership = owningPackageDirectory(input.workspace, directory);
|
|
50
|
+
const packageDirectory = ownership?.directory ?? '';
|
|
51
|
+
if (directory === packageDirectory)
|
|
52
|
+
continue;
|
|
53
|
+
addCandidate({ directory, basis: 'index-file', id: directory, packageName: ownership?.name ?? null });
|
|
54
|
+
}
|
|
55
|
+
// 3. directories up to `moduleDepth` below their package root with >= 2 files
|
|
56
|
+
const sortedDirectories = [...fileCountByDirectory].sort((a, b) => compareStrings(a[0], b[0]));
|
|
57
|
+
for (const [directory, count] of sortedDirectories) {
|
|
58
|
+
if (count < 2)
|
|
59
|
+
continue;
|
|
60
|
+
const ownership = owningPackageDirectory(input.workspace, directory);
|
|
61
|
+
const packageDirectory = ownership?.directory ?? '';
|
|
62
|
+
const relative = directory.length === 0 ? '' : (relativeTo(packageDirectory, directory) ?? directory);
|
|
63
|
+
const relativeDepth = relative.length === 0 ? 0 : depth(relative);
|
|
64
|
+
if (relativeDepth < 1 || relativeDepth > input.moduleDepth)
|
|
65
|
+
continue;
|
|
66
|
+
addCandidate({ directory, basis: 'directory', id: directory, packageName: ownership?.name ?? null });
|
|
67
|
+
}
|
|
68
|
+
candidates.sort((a, b) => a.directory.length === b.directory.length
|
|
69
|
+
? compareStrings(a.directory, b.directory)
|
|
70
|
+
: b.directory.length - a.directory.length);
|
|
71
|
+
const fileToModule = new Map();
|
|
72
|
+
const modulesById = new Map();
|
|
73
|
+
const moduleForFile = (file) => {
|
|
74
|
+
for (const candidate of candidates) {
|
|
75
|
+
if (candidate.directory.length === 0 || isInside(candidate.directory, file.path)) {
|
|
76
|
+
return {
|
|
77
|
+
id: candidate.id,
|
|
78
|
+
basis: candidate.basis,
|
|
79
|
+
directory: candidate.directory,
|
|
80
|
+
packageName: candidate.packageName,
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return { id: file.path, basis: 'single-file', directory: normalizeRelative(dirname(file.path)), packageName: null };
|
|
85
|
+
};
|
|
86
|
+
for (const file of moduleFiles) {
|
|
87
|
+
const assignment = moduleForFile(file);
|
|
88
|
+
fileToModule.set(file.path, assignment.id);
|
|
89
|
+
let moduleNode = modulesById.get(assignment.id);
|
|
90
|
+
if (moduleNode === undefined) {
|
|
91
|
+
moduleNode = {
|
|
92
|
+
id: assignment.id,
|
|
93
|
+
path: assignment.directory,
|
|
94
|
+
name: assignment.basis === 'workspace-package'
|
|
95
|
+
? assignment.id
|
|
96
|
+
: assignment.basis === 'single-file'
|
|
97
|
+
? stem(file.path)
|
|
98
|
+
: basename(assignment.directory) || assignment.directory,
|
|
99
|
+
basis: assignment.basis,
|
|
100
|
+
roles: [],
|
|
101
|
+
packageName: assignment.packageName,
|
|
102
|
+
isWorkspacePackage: assignment.basis === 'workspace-package',
|
|
103
|
+
files: [],
|
|
104
|
+
entryPoints: [],
|
|
105
|
+
dependsOn: [],
|
|
106
|
+
usedBy: [],
|
|
107
|
+
publicExports: [],
|
|
108
|
+
boundaries: [],
|
|
109
|
+
signals: [],
|
|
110
|
+
responsibilities: [],
|
|
111
|
+
git: null,
|
|
112
|
+
testFiles: [],
|
|
113
|
+
};
|
|
114
|
+
modulesById.set(assignment.id, moduleNode);
|
|
115
|
+
}
|
|
116
|
+
moduleNode.files.push(file.path);
|
|
117
|
+
if (file.kind === 'test')
|
|
118
|
+
moduleNode.testFiles.push(file.path);
|
|
119
|
+
const parsed = input.parsed.get(file.path);
|
|
120
|
+
if (parsed !== undefined) {
|
|
121
|
+
for (const signal of parsed.signals) {
|
|
122
|
+
if (!moduleNode.signals.includes(signal))
|
|
123
|
+
moduleNode.signals.push(signal);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
file.moduleId = assignment.id;
|
|
127
|
+
file.packageName = assignment.packageName;
|
|
128
|
+
}
|
|
129
|
+
for (const moduleNode of modulesById.values()) {
|
|
130
|
+
if (moduleNode.basis === 'single-file')
|
|
131
|
+
moduleNode.path = normalizeRelative(dirname(moduleNode.files[0] ?? ''));
|
|
132
|
+
moduleNode.files.sort(compareStrings);
|
|
133
|
+
moduleNode.testFiles.sort(compareStrings);
|
|
134
|
+
moduleNode.signals.sort(compareStrings);
|
|
135
|
+
}
|
|
136
|
+
const modules = [...modulesById.values()].sort((a, b) => compareStrings(a.id, b.id));
|
|
137
|
+
return { modules, fileToModule };
|
|
138
|
+
}
|
|
139
|
+
//# sourceMappingURL=modules.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"modules.js","sourceRoot":"","sources":["../../../src/core/graph/modules.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { DependencyKind } from '../../model/types.ts';
|
|
2
|
+
/** Extensions tried when a specifier has no extension, in deterministic order. */
|
|
3
|
+
export declare const RESOLUTION_EXTENSIONS: string[];
|
|
4
|
+
export interface AliasEntry {
|
|
5
|
+
/** Pattern such as `@app/*` or `@app/domain`. */
|
|
6
|
+
pattern: string;
|
|
7
|
+
/** Replacement targets, e.g. `src/*`. */
|
|
8
|
+
targets: string[];
|
|
9
|
+
/** Directory that relative targets are resolved against. */
|
|
10
|
+
base: string;
|
|
11
|
+
/** tsconfig that declared the alias. */
|
|
12
|
+
source: string;
|
|
13
|
+
}
|
|
14
|
+
export interface ResolverInput {
|
|
15
|
+
/** All analyzed file paths (repository-relative POSIX). */
|
|
16
|
+
filePaths: ReadonlySet<string>;
|
|
17
|
+
/** Path aliases collected from tsconfig files. */
|
|
18
|
+
aliases: AliasEntry[];
|
|
19
|
+
/** Workspace package name → package directory and entry candidates. */
|
|
20
|
+
workspacePackages: Map<string, {
|
|
21
|
+
directory: string;
|
|
22
|
+
entries: string[];
|
|
23
|
+
}>;
|
|
24
|
+
}
|
|
25
|
+
export interface ResolvedImport {
|
|
26
|
+
kind: DependencyKind;
|
|
27
|
+
/** Resolved file path, package name or builtin name. */
|
|
28
|
+
target: string;
|
|
29
|
+
/** Entry file of a workspace package, when known. */
|
|
30
|
+
entry: string | null;
|
|
31
|
+
confidence: number;
|
|
32
|
+
evidence: string;
|
|
33
|
+
/** Candidates that were tried and rejected (only for unresolved imports). */
|
|
34
|
+
attempts: string[];
|
|
35
|
+
}
|
|
36
|
+
/** Tries the extension and index-file candidates of a specifier base path. */
|
|
37
|
+
export declare function withExtensions(base: string, filePaths: ReadonlySet<string>): string | null;
|
|
38
|
+
export declare class ImportResolver {
|
|
39
|
+
private readonly filePaths;
|
|
40
|
+
private readonly aliases;
|
|
41
|
+
private readonly workspacePackages;
|
|
42
|
+
constructor(input: ResolverInput);
|
|
43
|
+
/** Resolves a specifier written in `fromFile`. */
|
|
44
|
+
resolve(specifier: string, fromFile: string): ResolvedImport;
|
|
45
|
+
private resolveWorkspaceEntry;
|
|
46
|
+
private matchAlias;
|
|
47
|
+
}
|
|
48
|
+
/** Relative specifier target without extension resolution; used by tests. */
|
|
49
|
+
export declare function relativeSpecifierTarget(specifier: string, fromFile: string): string;
|
|
50
|
+
//# sourceMappingURL=resolver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolver.d.ts","sourceRoot":"","sources":["../../../src/core/graph/resolver.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAO3D,kFAAkF;AAClF,eAAO,MAAM,qBAAqB,UAAmF,CAAC;AAWtH,MAAM,WAAW,UAAU;IACzB,iDAAiD;IACjD,OAAO,EAAE,MAAM,CAAC;IAChB,yCAAyC;IACzC,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,4DAA4D;IAC5D,IAAI,EAAE,MAAM,CAAC;IACb,wCAAwC;IACxC,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,aAAa;IAC5B,2DAA2D;IAC3D,SAAS,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAC/B,kDAAkD;IAClD,OAAO,EAAE,UAAU,EAAE,CAAC;IACtB,uEAAuE;IACvE,iBAAiB,EAAE,GAAG,CAAC,MAAM,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,CAAC;CAC1E;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,cAAc,CAAC;IACrB,wDAAwD;IACxD,MAAM,EAAE,MAAM,CAAC;IACf,qDAAqD;IACrD,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,6EAA6E;IAC7E,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,8EAA8E;AAC9E,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,WAAW,CAAC,MAAM,CAAC,GAAG,MAAM,GAAG,IAAI,CAoB1F;AAaD,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAsB;IAChD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAe;IACvC,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAqC;gBAE3D,KAAK,EAAE,aAAa;IAShC,kDAAkD;IAClD,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,cAAc;IA8D5D,OAAO,CAAC,qBAAqB;IAU7B,OAAO,CAAC,UAAU;CA4BnB;AAED,6EAA6E;AAC7E,wBAAgB,uBAAuB,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAEnF"}
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Import resolution.
|
|
3
|
+
*
|
|
4
|
+
* Resolution is deterministic and purely in-memory: it looks only at the set of
|
|
5
|
+
* analyzed files plus alias/workspace metadata, which is why a single file change
|
|
6
|
+
* never triggers a full repository re-read.
|
|
7
|
+
*
|
|
8
|
+
* Classification distinguishes the dependency kinds the task requires: internal
|
|
9
|
+
* file, workspace package, external package and Node built-in modules (plus an
|
|
10
|
+
* honest `unresolved` result with the candidates that were tried).
|
|
11
|
+
*/
|
|
12
|
+
import { builtinModules } from 'node:module';
|
|
13
|
+
import { extname, dirname, join, normalizeRelative } from "../../util/paths.js";
|
|
14
|
+
import { compareStrings } from "../../model/canonical.js";
|
|
15
|
+
import { packageNameFromSpecifier } from "../../adapters/language/ts-js/package-signals.js";
|
|
16
|
+
const BUILTINS = new Set([...builtinModules, ...builtinModules.map((name) => `node:${name}`)]);
|
|
17
|
+
/** Extensions tried when a specifier has no extension, in deterministic order. */
|
|
18
|
+
export const RESOLUTION_EXTENSIONS = ['.ts', '.tsx', '.mts', '.cts', '.d.ts', '.js', '.jsx', '.mjs', '.cjs', '.json'];
|
|
19
|
+
/** TypeScript ESM rewrite: `./x.js` may be emitted from `./x.ts`. */
|
|
20
|
+
const ESM_TO_TS = {
|
|
21
|
+
'.js': ['.ts', '.tsx', '.d.ts', '.js'],
|
|
22
|
+
'.jsx': ['.tsx', '.jsx'],
|
|
23
|
+
'.mjs': ['.mts', '.mjs'],
|
|
24
|
+
'.cjs': ['.cts', '.cjs'],
|
|
25
|
+
'.d.ts': ['.d.ts'],
|
|
26
|
+
};
|
|
27
|
+
/** Tries the extension and index-file candidates of a specifier base path. */
|
|
28
|
+
export function withExtensions(base, filePaths) {
|
|
29
|
+
const normalized = normalizeRelative(base);
|
|
30
|
+
if (filePaths.has(normalized))
|
|
31
|
+
return normalized;
|
|
32
|
+
const extension = extname(normalized);
|
|
33
|
+
if (extension.length > 0) {
|
|
34
|
+
const rewrites = ESM_TO_TS[extension];
|
|
35
|
+
if (rewrites === undefined)
|
|
36
|
+
return null;
|
|
37
|
+
const stem = normalized.slice(0, -extension.length);
|
|
38
|
+
for (const candidate of rewrites) {
|
|
39
|
+
if (filePaths.has(`${stem}${candidate}`))
|
|
40
|
+
return `${stem}${candidate}`;
|
|
41
|
+
}
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
for (const candidate of RESOLUTION_EXTENSIONS) {
|
|
45
|
+
if (filePaths.has(`${normalized}${candidate}`))
|
|
46
|
+
return `${normalized}${candidate}`;
|
|
47
|
+
}
|
|
48
|
+
for (const candidate of RESOLUTION_EXTENSIONS) {
|
|
49
|
+
if (filePaths.has(`${normalized}/index${candidate}`))
|
|
50
|
+
return `${normalized}/index${candidate}`;
|
|
51
|
+
}
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
function unresolved(specifier, attempts) {
|
|
55
|
+
return {
|
|
56
|
+
kind: 'unresolved',
|
|
57
|
+
target: specifier,
|
|
58
|
+
entry: null,
|
|
59
|
+
confidence: 0.3,
|
|
60
|
+
evidence: `could not resolve "${specifier}" to an analyzed file`,
|
|
61
|
+
attempts,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
export class ImportResolver {
|
|
65
|
+
filePaths;
|
|
66
|
+
aliases;
|
|
67
|
+
workspacePackages;
|
|
68
|
+
constructor(input) {
|
|
69
|
+
this.filePaths = input.filePaths;
|
|
70
|
+
// Deeper `base` first: the tsconfig closest to the importing file wins.
|
|
71
|
+
this.aliases = [...input.aliases].sort((a, b) => a.base.length === b.base.length ? compareStrings(a.pattern, b.pattern) : b.base.length - a.base.length);
|
|
72
|
+
this.workspacePackages = input.workspacePackages;
|
|
73
|
+
}
|
|
74
|
+
/** Resolves a specifier written in `fromFile`. */
|
|
75
|
+
resolve(specifier, fromFile) {
|
|
76
|
+
const normalizedSpecifier = specifier.replace(/\\/g, '/');
|
|
77
|
+
if (normalizedSpecifier.length === 0)
|
|
78
|
+
return unresolved(specifier, ['empty specifier']);
|
|
79
|
+
if (normalizedSpecifier.startsWith('.') || normalizedSpecifier.startsWith('/')) {
|
|
80
|
+
const base = join(dirname(fromFile), normalizedSpecifier);
|
|
81
|
+
const resolved = withExtensions(base, this.filePaths);
|
|
82
|
+
if (resolved !== null) {
|
|
83
|
+
const sameDirectory = dirname(fromFile) === dirname(resolved);
|
|
84
|
+
return {
|
|
85
|
+
kind: 'internal-file',
|
|
86
|
+
target: resolved,
|
|
87
|
+
entry: null,
|
|
88
|
+
confidence: 0.99,
|
|
89
|
+
evidence: sameDirectory
|
|
90
|
+
? `relative import inside ${dirname(fromFile) === '' ? '<repository root>' : dirname(fromFile)}`
|
|
91
|
+
: `relative import resolved to ${resolved}`,
|
|
92
|
+
attempts: [],
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
return unresolved(specifier, [`no analyzed file matched "${base}" with a known extension or index file`]);
|
|
96
|
+
}
|
|
97
|
+
const aliasMatch = this.matchAlias(normalizedSpecifier);
|
|
98
|
+
if (aliasMatch !== null)
|
|
99
|
+
return aliasMatch;
|
|
100
|
+
const packageName = packageNameFromSpecifier(normalizedSpecifier);
|
|
101
|
+
if (packageName !== null) {
|
|
102
|
+
const workspacePackage = this.workspacePackages.get(packageName);
|
|
103
|
+
if (workspacePackage !== undefined) {
|
|
104
|
+
return {
|
|
105
|
+
kind: 'workspace-package',
|
|
106
|
+
target: packageName,
|
|
107
|
+
entry: this.resolveWorkspaceEntry(packageName),
|
|
108
|
+
confidence: 0.97,
|
|
109
|
+
evidence: `specifier resolves to workspace package "${packageName}" (${workspacePackage.directory})`,
|
|
110
|
+
attempts: [],
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
if (BUILTINS.has(normalizedSpecifier)) {
|
|
114
|
+
return {
|
|
115
|
+
kind: 'node-builtin',
|
|
116
|
+
target: normalizedSpecifier,
|
|
117
|
+
entry: null,
|
|
118
|
+
confidence: 0.99,
|
|
119
|
+
evidence: 'specifier is a Node.js built-in module',
|
|
120
|
+
attempts: [],
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
return {
|
|
124
|
+
kind: 'external-package',
|
|
125
|
+
target: packageName,
|
|
126
|
+
entry: null,
|
|
127
|
+
confidence: 0.96,
|
|
128
|
+
evidence: 'specifier is an external package dependency',
|
|
129
|
+
attempts: [],
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
return unresolved(specifier, ['specifier is neither relative, aliased, nor a package name']);
|
|
133
|
+
}
|
|
134
|
+
resolveWorkspaceEntry(packageName) {
|
|
135
|
+
const workspacePackage = this.workspacePackages.get(packageName);
|
|
136
|
+
if (workspacePackage === undefined)
|
|
137
|
+
return null;
|
|
138
|
+
for (const candidate of workspacePackage.entries) {
|
|
139
|
+
const resolved = withExtensions(candidate, this.filePaths);
|
|
140
|
+
if (resolved !== null)
|
|
141
|
+
return resolved;
|
|
142
|
+
}
|
|
143
|
+
return null;
|
|
144
|
+
}
|
|
145
|
+
matchAlias(specifier) {
|
|
146
|
+
for (const alias of this.aliases) {
|
|
147
|
+
const wildcard = alias.pattern.includes('*');
|
|
148
|
+
if (!wildcard && alias.pattern !== specifier)
|
|
149
|
+
continue;
|
|
150
|
+
const prefix = wildcard ? alias.pattern.slice(0, alias.pattern.indexOf('*')) : alias.pattern;
|
|
151
|
+
if (!specifier.startsWith(prefix))
|
|
152
|
+
continue;
|
|
153
|
+
const rest = wildcard ? specifier.slice(prefix.length) : '';
|
|
154
|
+
for (const target of alias.targets) {
|
|
155
|
+
const substituted = wildcard ? target.replace('*', rest) : target;
|
|
156
|
+
const base = normalizeRelative(join(alias.base, substituted));
|
|
157
|
+
const resolved = withExtensions(base, this.filePaths);
|
|
158
|
+
if (resolved !== null) {
|
|
159
|
+
return {
|
|
160
|
+
kind: 'internal-file',
|
|
161
|
+
target: resolved,
|
|
162
|
+
entry: null,
|
|
163
|
+
confidence: 0.95,
|
|
164
|
+
evidence: `alias "${alias.pattern}" declared in ${alias.source} resolved to ${resolved}`,
|
|
165
|
+
attempts: [],
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
return unresolved(specifier, [
|
|
170
|
+
`alias "${alias.pattern}" declared in ${alias.source} did not resolve to an analyzed file`,
|
|
171
|
+
]);
|
|
172
|
+
}
|
|
173
|
+
return null;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
/** Relative specifier target without extension resolution; used by tests. */
|
|
177
|
+
export function relativeSpecifierTarget(specifier, fromFile) {
|
|
178
|
+
return normalizeRelative(join(dirname(fromFile), specifier));
|
|
179
|
+
}
|
|
180
|
+
//# sourceMappingURL=resolver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolver.js","sourceRoot":"","sources":["../../../src/core/graph/resolver.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { FileKind, ParsedFileSnapshot } from './types.ts';
|
|
2
|
+
export interface FileStateRecord {
|
|
3
|
+
hash: string;
|
|
4
|
+
size: number;
|
|
5
|
+
mtimeMs: number;
|
|
6
|
+
language: string;
|
|
7
|
+
kind: FileKind;
|
|
8
|
+
}
|
|
9
|
+
export interface LocalStateCounts {
|
|
10
|
+
files: number;
|
|
11
|
+
modules: number;
|
|
12
|
+
dependencies: number;
|
|
13
|
+
entryPoints: number;
|
|
14
|
+
conventions: number;
|
|
15
|
+
decisions: number;
|
|
16
|
+
}
|
|
17
|
+
export interface LocalState {
|
|
18
|
+
schemaVersion: number;
|
|
19
|
+
generatedBy: string;
|
|
20
|
+
toolVersion: string;
|
|
21
|
+
/** ISO timestamp of the last successful scan (local only, never canonical). */
|
|
22
|
+
lastScanAt: string | null;
|
|
23
|
+
/** Hash of the resolved configuration; a change invalidates the cache. */
|
|
24
|
+
configHash: string;
|
|
25
|
+
counts: LocalStateCounts;
|
|
26
|
+
files: Record<string, FileStateRecord>;
|
|
27
|
+
/** Hashes of the canonical `.agent/*` files as written by the last scan. */
|
|
28
|
+
canonical: Record<string, string>;
|
|
29
|
+
}
|
|
30
|
+
export declare function localStatePath(root: string): string;
|
|
31
|
+
export declare function cacheDirectory(root: string): string;
|
|
32
|
+
export declare class LocalStateStore {
|
|
33
|
+
private readonly file;
|
|
34
|
+
constructor(root: string);
|
|
35
|
+
get path(): string;
|
|
36
|
+
read(): Promise<LocalState | null>;
|
|
37
|
+
write(state: LocalState): Promise<void>;
|
|
38
|
+
remove(): Promise<void>;
|
|
39
|
+
}
|
|
40
|
+
/** Content-addressed cache of parse results. */
|
|
41
|
+
export declare class ParseCache {
|
|
42
|
+
private readonly root;
|
|
43
|
+
constructor(root: string);
|
|
44
|
+
get directory(): string;
|
|
45
|
+
get(hash: string): Promise<ParsedFileSnapshot | null>;
|
|
46
|
+
put(hash: string, file: ParsedFileSnapshot): Promise<void>;
|
|
47
|
+
clear(): Promise<void>;
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=cache.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../../src/core/scanner/cache.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,QAAQ,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAI/D,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,QAAQ,CAAC;CAChB;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,UAAU;IACzB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,+EAA+E;IAC/E,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,0EAA0E;IAC1E,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,gBAAgB,CAAC;IACzB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IACvC,4EAA4E;IAC5E,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACnC;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEnD;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEnD;AAED,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAS;gBAElB,IAAI,EAAE,MAAM;IAIxB,IAAI,IAAI,IAAI,MAAM,CAEjB;IAEK,IAAI,IAAI,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IA2BlC,KAAK,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAKvC,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;CAG9B;AAMD,gDAAgD;AAChD,qBAAa,UAAU;IACrB,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAS;gBAElB,IAAI,EAAE,MAAM;IAIxB,IAAI,SAAS,IAAI,MAAM,CAEtB;IAEK,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC;IAYrD,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC;IAO1D,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAG7B"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Local (gitignored) incremental scanning state.
|
|
3
|
+
*
|
|
4
|
+
* Two artifacts, both inside `.agent/.local/` so they are never committed:
|
|
5
|
+
* - `state.json` — per file hash/size/mtime plus the last scan timestamp;
|
|
6
|
+
* - `cache/<shard>/<sha256>.json` — content-addressed parse results, so an
|
|
7
|
+
* unchanged file (or an identical file elsewhere in the repository) is never
|
|
8
|
+
* parsed twice.
|
|
9
|
+
*/
|
|
10
|
+
import { mkdir, readFile, rm, writeFile } from 'node:fs/promises';
|
|
11
|
+
import path from 'node:path';
|
|
12
|
+
import { AGENT_DIR, LOCAL_DIR, SCHEMA_VERSION, STATE_FILE, GENERATOR_NAME } from "../../model/schema.js";
|
|
13
|
+
import { stringifyCanonical } from "../../model/canonical.js";
|
|
14
|
+
export function localStatePath(root) {
|
|
15
|
+
return path.join(root, STATE_FILE);
|
|
16
|
+
}
|
|
17
|
+
export function cacheDirectory(root) {
|
|
18
|
+
return path.join(root, AGENT_DIR, LOCAL_DIR, 'cache');
|
|
19
|
+
}
|
|
20
|
+
export class LocalStateStore {
|
|
21
|
+
file;
|
|
22
|
+
constructor(root) {
|
|
23
|
+
this.file = localStatePath(root);
|
|
24
|
+
}
|
|
25
|
+
get path() {
|
|
26
|
+
return this.file;
|
|
27
|
+
}
|
|
28
|
+
async read() {
|
|
29
|
+
try {
|
|
30
|
+
const contents = await readFile(this.file, 'utf8');
|
|
31
|
+
const parsed = JSON.parse(contents);
|
|
32
|
+
if (parsed.schemaVersion !== SCHEMA_VERSION)
|
|
33
|
+
return null;
|
|
34
|
+
return {
|
|
35
|
+
schemaVersion: SCHEMA_VERSION,
|
|
36
|
+
generatedBy: parsed.generatedBy ?? GENERATOR_NAME,
|
|
37
|
+
toolVersion: parsed.toolVersion ?? '0.0.0',
|
|
38
|
+
lastScanAt: parsed.lastScanAt ?? null,
|
|
39
|
+
configHash: parsed.configHash ?? '',
|
|
40
|
+
counts: {
|
|
41
|
+
files: parsed.counts?.files ?? 0,
|
|
42
|
+
modules: parsed.counts?.modules ?? 0,
|
|
43
|
+
dependencies: parsed.counts?.dependencies ?? 0,
|
|
44
|
+
entryPoints: parsed.counts?.entryPoints ?? 0,
|
|
45
|
+
conventions: parsed.counts?.conventions ?? 0,
|
|
46
|
+
decisions: parsed.counts?.decisions ?? 0,
|
|
47
|
+
},
|
|
48
|
+
files: parsed.files ?? {},
|
|
49
|
+
canonical: parsed.canonical ?? {},
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
async write(state) {
|
|
57
|
+
await mkdir(path.dirname(this.file), { recursive: true });
|
|
58
|
+
await writeFile(this.file, stringifyCanonical(state), 'utf8');
|
|
59
|
+
}
|
|
60
|
+
async remove() {
|
|
61
|
+
await rm(this.file, { force: true });
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
function shardPath(root, hash) {
|
|
65
|
+
return path.join(cacheDirectory(root), hash.slice(0, 2), `${hash}.json`);
|
|
66
|
+
}
|
|
67
|
+
/** Content-addressed cache of parse results. */
|
|
68
|
+
export class ParseCache {
|
|
69
|
+
root;
|
|
70
|
+
constructor(root) {
|
|
71
|
+
this.root = root;
|
|
72
|
+
}
|
|
73
|
+
get directory() {
|
|
74
|
+
return cacheDirectory(this.root);
|
|
75
|
+
}
|
|
76
|
+
async get(hash) {
|
|
77
|
+
if (hash.length === 0)
|
|
78
|
+
return null;
|
|
79
|
+
try {
|
|
80
|
+
const contents = await readFile(shardPath(this.root, hash), 'utf8');
|
|
81
|
+
const parsed = JSON.parse(contents);
|
|
82
|
+
if (parsed.schemaVersion !== SCHEMA_VERSION || parsed.file === undefined)
|
|
83
|
+
return null;
|
|
84
|
+
return parsed.file;
|
|
85
|
+
}
|
|
86
|
+
catch {
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
async put(hash, file) {
|
|
91
|
+
if (hash.length === 0)
|
|
92
|
+
return;
|
|
93
|
+
const target = shardPath(this.root, hash);
|
|
94
|
+
await mkdir(path.dirname(target), { recursive: true });
|
|
95
|
+
await writeFile(target, stringifyCanonical({ schemaVersion: SCHEMA_VERSION, file }), 'utf8');
|
|
96
|
+
}
|
|
97
|
+
async clear() {
|
|
98
|
+
await rm(this.directory, { recursive: true, force: true });
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache.js","sourceRoot":"","sources":["../../../src/core/scanner/cache.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Repository scanner.
|
|
3
|
+
*
|
|
4
|
+
* Pipeline: walk → decide what changed → parse only what changed → emit file
|
|
5
|
+
* facts. Parsing is content-addressed, so:
|
|
6
|
+
*
|
|
7
|
+
* - a file whose size and mtime are unchanged is never read at all;
|
|
8
|
+
* - a changed file is hashed and, when its hash is already cached, not re-parsed;
|
|
9
|
+
* - a new file that is byte-identical to an existing one reuses its cache entry.
|
|
10
|
+
*
|
|
11
|
+
* The scanner performs no language specific work: adapters are resolved through
|
|
12
|
+
* the {@link LanguageRegistry} and return the language-agnostic IR.
|
|
13
|
+
*/
|
|
14
|
+
import type { ChangeSet, FileKind, FileNode } from '../../model/types.ts';
|
|
15
|
+
import type { ParsedFile } from '../../adapters/language/types.ts';
|
|
16
|
+
import type { AgentContextConfig } from '../../config/types.ts';
|
|
17
|
+
import type { DiagnosticsCollector, Logger, ProgressReporter } from '../../logging/diagnostics.ts';
|
|
18
|
+
import { FileSystemAdapter } from '../../adapters/filesystem/fs-adapter.ts';
|
|
19
|
+
import { LanguageRegistry } from '../../adapters/language/registry.ts';
|
|
20
|
+
import type { ParseCache, LocalState } from './cache.ts';
|
|
21
|
+
/** Classifies a file, language agnostically. */
|
|
22
|
+
export declare function classifyFile(path: string, signals?: readonly string[]): FileKind;
|
|
23
|
+
export interface ScanOptions {
|
|
24
|
+
root: string;
|
|
25
|
+
config: AgentContextConfig;
|
|
26
|
+
/** Hash of the resolved configuration, used for cache invalidation. */
|
|
27
|
+
configHash: string;
|
|
28
|
+
registry?: LanguageRegistry;
|
|
29
|
+
fsAdapter?: FileSystemAdapter;
|
|
30
|
+
/** Previous local state, when available (enables the incremental path). */
|
|
31
|
+
state: LocalState | null;
|
|
32
|
+
cache: ParseCache;
|
|
33
|
+
diagnostics: DiagnosticsCollector;
|
|
34
|
+
logger: Logger;
|
|
35
|
+
progress?: ProgressReporter;
|
|
36
|
+
}
|
|
37
|
+
export interface ScanOutput {
|
|
38
|
+
files: FileNode[];
|
|
39
|
+
/** Parsed facts of every readable file, keyed by repository-relative path. */
|
|
40
|
+
parsed: Map<string, ParsedFile>;
|
|
41
|
+
changes: ChangeSet;
|
|
42
|
+
/** Number of files whose content was parsed during this scan. */
|
|
43
|
+
parsedNow: number;
|
|
44
|
+
/** Number of files served from the local parse cache without being parsed. */
|
|
45
|
+
reused: number;
|
|
46
|
+
skippedSensitive: string[];
|
|
47
|
+
skippedLarge: string[];
|
|
48
|
+
failed: string[];
|
|
49
|
+
partial: string[];
|
|
50
|
+
/** All walked paths, used for lockfile and workspace detection. */
|
|
51
|
+
presentFiles: Set<string>;
|
|
52
|
+
/** Raw contents of pnpm-workspace.yaml, when present. */
|
|
53
|
+
pnpmWorkspaceYaml: string | null;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Scans a repository and returns file level facts plus the change set relative to
|
|
57
|
+
* the previous local state.
|
|
58
|
+
*/
|
|
59
|
+
export declare function scanRepository(options: ScanOptions): Promise<ScanOutput>;
|
|
60
|
+
//# sourceMappingURL=scanner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scanner.d.ts","sourceRoot":"","sources":["../../../src/core/scanner/scanner.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAC1E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kCAAkC,CAAC;AACnE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAKhE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AACnG,OAAO,EAAE,iBAAiB,EAAmB,MAAM,yCAAyC,CAAC;AAE7F,OAAO,EAAE,gBAAgB,EAAyB,MAAM,qCAAqC,CAAC;AAC9F,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AA6CzD,gDAAgD;AAChD,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,SAAS,MAAM,EAAO,GAAG,QAAQ,CAmBpF;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,kBAAkB,CAAC;IAC3B,uEAAuE;IACvE,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,gBAAgB,CAAC;IAC5B,SAAS,CAAC,EAAE,iBAAiB,CAAC;IAC9B,2EAA2E;IAC3E,KAAK,EAAE,UAAU,GAAG,IAAI,CAAC;IACzB,KAAK,EAAE,UAAU,CAAC;IAClB,WAAW,EAAE,oBAAoB,CAAC;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,gBAAgB,CAAC;CAC7B;AAED,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,8EAA8E;IAC9E,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IAChC,OAAO,EAAE,SAAS,CAAC;IACnB,iEAAiE;IACjE,SAAS,EAAE,MAAM,CAAC;IAClB,8EAA8E;IAC9E,MAAM,EAAE,MAAM,CAAC;IACf,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,mEAAmE;IACnE,YAAY,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC1B,yDAAyD;IACzD,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;CAClC;AAmCD;;;GAGG;AACH,wBAAsB,cAAc,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,CAsN9E"}
|