@eduardo-afonso/codebase-intelligence 0.1.0 → 2.0.1
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/README.md +86 -11
- package/README.pt-BR.md +88 -12
- package/dist/ai/CodebaseWithAI.d.ts +91 -0
- package/dist/ai/CodebaseWithAI.d.ts.map +1 -0
- package/dist/ai/CodebaseWithAI.js +149 -0
- package/dist/ai/CodebaseWithAI.js.map +1 -0
- package/dist/ai/RAGPipeline.d.ts +66 -0
- package/dist/ai/RAGPipeline.d.ts.map +1 -0
- package/dist/ai/RAGPipeline.js +102 -0
- package/dist/ai/RAGPipeline.js.map +1 -0
- package/dist/ai/index.d.ts +6 -0
- package/dist/ai/index.d.ts.map +1 -0
- package/dist/ai/index.js +5 -0
- package/dist/ai/index.js.map +1 -0
- package/dist/ai/providers/NoopAIProvider.d.ts +23 -0
- package/dist/ai/providers/NoopAIProvider.d.ts.map +1 -0
- package/dist/ai/providers/NoopAIProvider.js +24 -0
- package/dist/ai/providers/NoopAIProvider.js.map +1 -0
- package/dist/cli/index.js +168 -8
- package/dist/cli/index.js.map +1 -1
- package/dist/context/ContextEngine.d.ts +54 -0
- package/dist/context/ContextEngine.d.ts.map +1 -0
- package/dist/context/ContextEngine.js +179 -0
- package/dist/context/ContextEngine.js.map +1 -0
- package/dist/context/FileContextBuilder.d.ts +49 -0
- package/dist/context/FileContextBuilder.d.ts.map +1 -0
- package/dist/context/FileContextBuilder.js +124 -0
- package/dist/context/FileContextBuilder.js.map +1 -0
- package/dist/context/SemanticChunker.d.ts +105 -0
- package/dist/context/SemanticChunker.d.ts.map +1 -0
- package/dist/context/SemanticChunker.js +293 -0
- package/dist/context/SemanticChunker.js.map +1 -0
- package/dist/context/SignatureExtractor.d.ts +49 -0
- package/dist/context/SignatureExtractor.d.ts.map +1 -0
- package/dist/context/SignatureExtractor.js +167 -0
- package/dist/context/SignatureExtractor.js.map +1 -0
- package/dist/context/interfaces.d.ts +149 -0
- package/dist/context/interfaces.d.ts.map +1 -0
- package/dist/context/interfaces.js +13 -0
- package/dist/context/interfaces.js.map +1 -0
- package/dist/context/strategies/ContextBuildStrategy.d.ts +25 -0
- package/dist/context/strategies/ContextBuildStrategy.d.ts.map +1 -0
- package/dist/context/strategies/ContextBuildStrategy.js +3 -0
- package/dist/context/strategies/ContextBuildStrategy.js.map +1 -0
- package/dist/context/strategies/DeepStrategy.d.ts +18 -0
- package/dist/context/strategies/DeepStrategy.d.ts.map +1 -0
- package/dist/context/strategies/DeepStrategy.js +19 -0
- package/dist/context/strategies/DeepStrategy.js.map +1 -0
- package/dist/context/strategies/ShallowStrategy.d.ts +15 -0
- package/dist/context/strategies/ShallowStrategy.d.ts.map +1 -0
- package/dist/context/strategies/ShallowStrategy.js +15 -0
- package/dist/context/strategies/ShallowStrategy.js.map +1 -0
- package/dist/context/strategies/SignatureStrategy.d.ts +20 -0
- package/dist/context/strategies/SignatureStrategy.d.ts.map +1 -0
- package/dist/context/strategies/SignatureStrategy.js +59 -0
- package/dist/context/strategies/SignatureStrategy.js.map +1 -0
- package/dist/context/strategies/index.d.ts +5 -0
- package/dist/context/strategies/index.d.ts.map +1 -0
- package/dist/context/strategies/index.js +4 -0
- package/dist/context/strategies/index.js.map +1 -0
- package/dist/context/types.d.ts +136 -0
- package/dist/context/types.d.ts.map +1 -0
- package/dist/context/types.js +8 -0
- package/dist/context/types.js.map +1 -0
- package/dist/core/Codebase.d.ts +50 -0
- package/dist/core/Codebase.d.ts.map +1 -1
- package/dist/core/Codebase.js +104 -0
- package/dist/core/Codebase.js.map +1 -1
- package/dist/diff/ChangeSetImpactAnalyzer.d.ts +19 -0
- package/dist/diff/ChangeSetImpactAnalyzer.d.ts.map +1 -0
- package/dist/diff/ChangeSetImpactAnalyzer.js +121 -0
- package/dist/diff/ChangeSetImpactAnalyzer.js.map +1 -0
- package/dist/diff/GitChangeSetProvider.d.ts +86 -0
- package/dist/diff/GitChangeSetProvider.d.ts.map +1 -0
- package/dist/diff/GitChangeSetProvider.js +297 -0
- package/dist/diff/GitChangeSetProvider.js.map +1 -0
- package/dist/diff/errors.d.ts +48 -0
- package/dist/diff/errors.d.ts.map +1 -0
- package/dist/diff/errors.js +70 -0
- package/dist/diff/errors.js.map +1 -0
- package/dist/diff/types.d.ts +159 -0
- package/dist/diff/types.d.ts.map +1 -0
- package/dist/diff/types.js +8 -0
- package/dist/diff/types.js.map +1 -0
- package/dist/explorer/SnapshotBuilder.d.ts +22 -0
- package/dist/explorer/SnapshotBuilder.d.ts.map +1 -0
- package/dist/explorer/SnapshotBuilder.js +225 -0
- package/dist/explorer/SnapshotBuilder.js.map +1 -0
- package/dist/explorer/types.d.ts +88 -0
- package/dist/explorer/types.d.ts.map +1 -0
- package/dist/explorer/types.js +12 -0
- package/dist/explorer/types.js.map +1 -0
- package/dist/explorer/ui/App.d.ts +3 -0
- package/dist/explorer/ui/App.d.ts.map +1 -0
- package/dist/explorer/ui/App.js +43 -0
- package/dist/explorer/ui/App.js.map +1 -0
- package/dist/explorer/ui/main.d.ts +2 -0
- package/dist/explorer/ui/main.d.ts.map +1 -0
- package/dist/explorer/ui/main.js +8 -0
- package/dist/explorer/ui/main.js.map +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -1
- package/dist/ui/assets/index-D4w3JVrv.css +1 -0
- package/dist/ui/assets/index-DBRKE5qL.js +52 -0
- package/dist/ui/index.html +13 -0
- package/package.json +50 -50
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
import { Project, SyntaxKind } from 'ts-morph';
|
|
2
|
+
// ---------------------------------------------------------------------------
|
|
3
|
+
// SemanticChunker
|
|
4
|
+
// ---------------------------------------------------------------------------
|
|
5
|
+
/**
|
|
6
|
+
* Divides TypeScript/JavaScript source files into semantically coherent
|
|
7
|
+
* chunks using the `ts-morph` AST.
|
|
8
|
+
*
|
|
9
|
+
* Unlike character or line-based splitters, `SemanticChunker` guarantees that:
|
|
10
|
+
* - No chunk cuts across a declaration boundary.
|
|
11
|
+
* - Large symbols (classes with many methods) are split **by method**, not
|
|
12
|
+
* arbitrarily.
|
|
13
|
+
* - Each chunk includes the file header (imports) so it can be embedded
|
|
14
|
+
* and understood without additional context.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```ts
|
|
18
|
+
* const chunker = new SemanticChunker();
|
|
19
|
+
* const chunks = await chunker.chunk(codebase.files(), { maxChunkTokens: 512 });
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
export class SemanticChunker {
|
|
23
|
+
project;
|
|
24
|
+
constructor() {
|
|
25
|
+
this.project = new Project({
|
|
26
|
+
useInMemoryFileSystem: false,
|
|
27
|
+
skipFileDependencyResolution: true,
|
|
28
|
+
compilerOptions: {
|
|
29
|
+
allowJs: true,
|
|
30
|
+
noResolve: true,
|
|
31
|
+
},
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Chunks the given list of files into semantically complete fragments.
|
|
36
|
+
*
|
|
37
|
+
* Only TypeScript and JavaScript files are processed via AST chunking.
|
|
38
|
+
* Other file types (JSON, config files) are returned as a single whole-file
|
|
39
|
+
* chunk if they fit within `maxChunkTokens`, or omitted otherwise.
|
|
40
|
+
*
|
|
41
|
+
* @param files - The list of `CodebaseFile`s to chunk.
|
|
42
|
+
* @param options - Chunking configuration.
|
|
43
|
+
* @returns Ordered list of `SemanticChunk`s across all processed files.
|
|
44
|
+
*/
|
|
45
|
+
async chunk(files, options = {}) {
|
|
46
|
+
const { maxChunkTokens = 512, includeFileHeader = true } = options;
|
|
47
|
+
const allChunks = [];
|
|
48
|
+
for (const file of files) {
|
|
49
|
+
const chunks = await this.chunkFile(file, maxChunkTokens, includeFileHeader);
|
|
50
|
+
allChunks.push(...chunks);
|
|
51
|
+
}
|
|
52
|
+
return allChunks;
|
|
53
|
+
}
|
|
54
|
+
// ---- Per-file chunking --------------------------------------------------
|
|
55
|
+
async chunkFile(file, maxChunkTokens, includeFileHeader) {
|
|
56
|
+
if (file.language !== 'typescript' && file.language !== 'javascript') {
|
|
57
|
+
return this.chunkNonTsFile(file, maxChunkTokens);
|
|
58
|
+
}
|
|
59
|
+
let sourceFile;
|
|
60
|
+
try {
|
|
61
|
+
sourceFile =
|
|
62
|
+
this.project.getSourceFile(file.path) ??
|
|
63
|
+
this.project.addSourceFileAtPath(file.path);
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
// Unreadable or invalid file — skip silently
|
|
67
|
+
return [];
|
|
68
|
+
}
|
|
69
|
+
const fileHeader = includeFileHeader ? extractFileHeader(sourceFile) : '';
|
|
70
|
+
const chunks = [];
|
|
71
|
+
// Collect all top-level declarations (skip imports/exports re-declarations)
|
|
72
|
+
const topLevelDecls = getTopLevelDeclarations(sourceFile);
|
|
73
|
+
if (topLevelDecls.length === 0) {
|
|
74
|
+
// No meaningful symbols — emit the whole file as a single chunk
|
|
75
|
+
return [this.buildWholeFileChunk(file, sourceFile.getFullText())];
|
|
76
|
+
}
|
|
77
|
+
for (const decl of topLevelDecls) {
|
|
78
|
+
const declChunks = this.chunksForDeclaration(decl, file, fileHeader, maxChunkTokens);
|
|
79
|
+
chunks.push(...declChunks);
|
|
80
|
+
}
|
|
81
|
+
// If we produced no chunks (e.g. all declarations were expression statements),
|
|
82
|
+
// fall back to the whole file
|
|
83
|
+
return chunks.length > 0 ? chunks : [this.buildWholeFileChunk(file, sourceFile.getFullText())];
|
|
84
|
+
}
|
|
85
|
+
// ---- Declaration-level chunking ----------------------------------------
|
|
86
|
+
chunksForDeclaration(decl, file, fileHeader, maxChunkTokens) {
|
|
87
|
+
const kind = decl.getKind();
|
|
88
|
+
if (kind === SyntaxKind.ClassDeclaration) {
|
|
89
|
+
return this.chunksForClass(decl, file, fileHeader, maxChunkTokens);
|
|
90
|
+
}
|
|
91
|
+
// For everything else (functions, interfaces, type aliases, enums,
|
|
92
|
+
// variable statements) treat as a single symbol chunk.
|
|
93
|
+
return [this.buildSymbolChunk(decl, file, fileHeader, maxChunkTokens)];
|
|
94
|
+
}
|
|
95
|
+
// ---- Class chunking -----------------------------------------------------
|
|
96
|
+
/**
|
|
97
|
+
* Emits the class as one chunk. If that chunk exceeds `maxChunkTokens`,
|
|
98
|
+
* falls back to per-method sub-chunking.
|
|
99
|
+
*/
|
|
100
|
+
chunksForClass(classNode, file, fileHeader, maxChunkTokens) {
|
|
101
|
+
const classDecl = classNode.asKindOrThrow(SyntaxKind.ClassDeclaration);
|
|
102
|
+
const classText = classDecl.getText();
|
|
103
|
+
const headerPrefix = fileHeader ? `${fileHeader}\n\n` : '';
|
|
104
|
+
const combined = `${headerPrefix}${classText}`;
|
|
105
|
+
if (estimateTokens(combined) <= maxChunkTokens) {
|
|
106
|
+
// Fits as a whole — emit the entire class
|
|
107
|
+
const startLine = classDecl.getStartLineNumber();
|
|
108
|
+
const endLine = classDecl.getEndLineNumber();
|
|
109
|
+
return [
|
|
110
|
+
this.buildChunk(file, combined, 'class', classDecl.getName() ?? '<anonymous>', startLine, endLine),
|
|
111
|
+
];
|
|
112
|
+
}
|
|
113
|
+
// Class is too large — sub-chunk by method
|
|
114
|
+
return this.subChunkByMethod(classDecl, file, fileHeader, maxChunkTokens);
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Splits an oversized class into one chunk per method/constructor.
|
|
118
|
+
* Properties and the class header are included in every method chunk.
|
|
119
|
+
*/
|
|
120
|
+
subChunkByMethod(classDecl, file, fileHeader, maxChunkTokens) {
|
|
121
|
+
const cd = classDecl.asKindOrThrow(SyntaxKind.ClassDeclaration);
|
|
122
|
+
const headerPrefix = fileHeader ? `${fileHeader}\n\n` : '';
|
|
123
|
+
// Build the class "skeleton" (header + properties, no methods)
|
|
124
|
+
const classHeader = buildClassHeader(cd);
|
|
125
|
+
const properties = cd
|
|
126
|
+
.getMembers()
|
|
127
|
+
.filter(m => m.getKind() === SyntaxKind.PropertyDeclaration ||
|
|
128
|
+
m.getKind() === SyntaxKind.GetAccessor ||
|
|
129
|
+
m.getKind() === SyntaxKind.SetAccessor)
|
|
130
|
+
.map(m => ` ${m.getText()}`)
|
|
131
|
+
.join('\n');
|
|
132
|
+
const classSkeleton = properties
|
|
133
|
+
? `${classHeader} {\n${properties}\n // ... methods below\n}`
|
|
134
|
+
: `${classHeader} { /* ... */ }`;
|
|
135
|
+
const chunks = [];
|
|
136
|
+
for (const member of cd.getMembers()) {
|
|
137
|
+
const memberKind = member.getKind();
|
|
138
|
+
if (memberKind !== SyntaxKind.Constructor &&
|
|
139
|
+
memberKind !== SyntaxKind.MethodDeclaration) {
|
|
140
|
+
continue;
|
|
141
|
+
}
|
|
142
|
+
const memberText = member.getText();
|
|
143
|
+
const methodChunkContent = [
|
|
144
|
+
headerPrefix + classSkeleton,
|
|
145
|
+
'',
|
|
146
|
+
` // Method: ${getMemberName(member)}`,
|
|
147
|
+
` ${memberText}`,
|
|
148
|
+
'}',
|
|
149
|
+
].join('\n');
|
|
150
|
+
const startLine = member.getStartLineNumber();
|
|
151
|
+
const endLine = member.getEndLineNumber();
|
|
152
|
+
chunks.push(this.buildChunk(file, methodChunkContent, 'method', getMemberName(member), startLine, endLine));
|
|
153
|
+
}
|
|
154
|
+
// If no methods were found, fall back to the whole class
|
|
155
|
+
if (chunks.length === 0) {
|
|
156
|
+
const combined = `${headerPrefix}${cd.getText()}`;
|
|
157
|
+
const startLine = cd.getStartLineNumber();
|
|
158
|
+
const endLine = cd.getEndLineNumber();
|
|
159
|
+
chunks.push(this.buildChunk(file, combined, 'class', cd.getName() ?? '<anonymous>', startLine, endLine));
|
|
160
|
+
}
|
|
161
|
+
return chunks;
|
|
162
|
+
}
|
|
163
|
+
// ---- Generic symbol chunk -----------------------------------------------
|
|
164
|
+
buildSymbolChunk(node, file, fileHeader, _maxChunkTokens) {
|
|
165
|
+
const headerPrefix = fileHeader ? `${fileHeader}\n\n` : '';
|
|
166
|
+
const content = `${headerPrefix}${node.getText()}`;
|
|
167
|
+
const startLine = node.getStartLineNumber();
|
|
168
|
+
const endLine = node.getEndLineNumber();
|
|
169
|
+
const { kind, name } = getNodeKindAndName(node);
|
|
170
|
+
return this.buildChunk(file, content, kind, name, startLine, endLine);
|
|
171
|
+
}
|
|
172
|
+
// ---- Whole-file fallback ------------------------------------------------
|
|
173
|
+
buildWholeFileChunk(file, content) {
|
|
174
|
+
const lines = content.split('\n').length;
|
|
175
|
+
return this.buildChunk(file, content, 'file', undefined, 1, lines);
|
|
176
|
+
}
|
|
177
|
+
chunkNonTsFile(file, maxChunkTokens) {
|
|
178
|
+
// Non-TS files: return as a single chunk if small enough
|
|
179
|
+
const content = ''; // We skip reading non-TS files
|
|
180
|
+
void content; // avoid unused warning
|
|
181
|
+
// Without reading the file, we can't produce useful chunks.
|
|
182
|
+
// These will be added when the RAG pipeline actually needs to embed them.
|
|
183
|
+
void maxChunkTokens;
|
|
184
|
+
return [];
|
|
185
|
+
}
|
|
186
|
+
// ---- Chunk builder ------------------------------------------------------
|
|
187
|
+
buildChunk(file, content, symbolKind, symbolName, startLine, endLine) {
|
|
188
|
+
const id = `${file.relativePath}:${startLine}-${endLine}`;
|
|
189
|
+
const chunk = {
|
|
190
|
+
id,
|
|
191
|
+
file: file.path,
|
|
192
|
+
relativePath: file.relativePath,
|
|
193
|
+
content: content.trim(),
|
|
194
|
+
symbolKind,
|
|
195
|
+
startLine,
|
|
196
|
+
endLine,
|
|
197
|
+
tokenEstimate: estimateTokens(content),
|
|
198
|
+
};
|
|
199
|
+
if (symbolName !== undefined) {
|
|
200
|
+
chunk.symbolName = symbolName;
|
|
201
|
+
}
|
|
202
|
+
return chunk;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
// ---------------------------------------------------------------------------
|
|
206
|
+
// AST helpers
|
|
207
|
+
// ---------------------------------------------------------------------------
|
|
208
|
+
/**
|
|
209
|
+
* Extracts the file "header" — import/export declarations and leading
|
|
210
|
+
* comments/trivia at the top of the file.
|
|
211
|
+
*/
|
|
212
|
+
function extractFileHeader(sourceFile) {
|
|
213
|
+
const headerLines = [];
|
|
214
|
+
for (const statement of sourceFile.getStatements()) {
|
|
215
|
+
const kind = statement.getKind();
|
|
216
|
+
if (kind === SyntaxKind.ImportDeclaration ||
|
|
217
|
+
kind === SyntaxKind.ExportDeclaration) {
|
|
218
|
+
headerLines.push(statement.getText());
|
|
219
|
+
}
|
|
220
|
+
else {
|
|
221
|
+
// Stop at the first non-import statement
|
|
222
|
+
break;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
return headerLines.join('\n');
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Returns all top-level declarations that represent meaningful code units
|
|
229
|
+
* (classes, functions, interfaces, type aliases, enums, variable statements).
|
|
230
|
+
* Import/export declarations are excluded — they form the file header.
|
|
231
|
+
*/
|
|
232
|
+
function getTopLevelDeclarations(sourceFile) {
|
|
233
|
+
const result = [];
|
|
234
|
+
for (const statement of sourceFile.getStatements()) {
|
|
235
|
+
const kind = statement.getKind();
|
|
236
|
+
if (kind === SyntaxKind.ClassDeclaration ||
|
|
237
|
+
kind === SyntaxKind.FunctionDeclaration ||
|
|
238
|
+
kind === SyntaxKind.InterfaceDeclaration ||
|
|
239
|
+
kind === SyntaxKind.TypeAliasDeclaration ||
|
|
240
|
+
kind === SyntaxKind.EnumDeclaration ||
|
|
241
|
+
kind === SyntaxKind.VariableStatement) {
|
|
242
|
+
result.push(statement);
|
|
243
|
+
}
|
|
244
|
+
// Skip: ImportDeclaration, ExportDeclaration, ExpressionStatement
|
|
245
|
+
}
|
|
246
|
+
return result;
|
|
247
|
+
}
|
|
248
|
+
/** Builds the class declaration line (everything before the opening `{`). */
|
|
249
|
+
function buildClassHeader(classDecl) {
|
|
250
|
+
if (!classDecl)
|
|
251
|
+
return 'class <anonymous>';
|
|
252
|
+
const fullText = classDecl.getText();
|
|
253
|
+
const braceIdx = fullText.indexOf('{');
|
|
254
|
+
return braceIdx !== -1 ? fullText.slice(0, braceIdx).trimEnd() : fullText;
|
|
255
|
+
}
|
|
256
|
+
/** Returns the `SymbolKind` and name for an arbitrary top-level AST node. */
|
|
257
|
+
function getNodeKindAndName(node) {
|
|
258
|
+
const k = node.getKind();
|
|
259
|
+
if (k === SyntaxKind.ClassDeclaration) {
|
|
260
|
+
return { kind: 'class', name: node.asKindOrThrow(SyntaxKind.ClassDeclaration).getName() };
|
|
261
|
+
}
|
|
262
|
+
if (k === SyntaxKind.FunctionDeclaration) {
|
|
263
|
+
return { kind: 'function', name: node.asKindOrThrow(SyntaxKind.FunctionDeclaration).getName() };
|
|
264
|
+
}
|
|
265
|
+
if (k === SyntaxKind.InterfaceDeclaration) {
|
|
266
|
+
return { kind: 'interface', name: node.asKindOrThrow(SyntaxKind.InterfaceDeclaration).getName() };
|
|
267
|
+
}
|
|
268
|
+
if (k === SyntaxKind.TypeAliasDeclaration) {
|
|
269
|
+
return { kind: 'typeAlias', name: node.asKindOrThrow(SyntaxKind.TypeAliasDeclaration).getName() };
|
|
270
|
+
}
|
|
271
|
+
if (k === SyntaxKind.VariableStatement) {
|
|
272
|
+
const decls = node.asKindOrThrow(SyntaxKind.VariableStatement).getDeclarations();
|
|
273
|
+
return { kind: 'variable', name: decls[0]?.getName() };
|
|
274
|
+
}
|
|
275
|
+
return { kind: 'file', name: undefined };
|
|
276
|
+
}
|
|
277
|
+
/** Returns the name of a class member (method or constructor). */
|
|
278
|
+
function getMemberName(member) {
|
|
279
|
+
const kind = member.getKind();
|
|
280
|
+
if (kind === SyntaxKind.Constructor)
|
|
281
|
+
return 'constructor';
|
|
282
|
+
if (kind === SyntaxKind.MethodDeclaration) {
|
|
283
|
+
return member.asKindOrThrow(SyntaxKind.MethodDeclaration).getName();
|
|
284
|
+
}
|
|
285
|
+
return '<member>';
|
|
286
|
+
}
|
|
287
|
+
// ---------------------------------------------------------------------------
|
|
288
|
+
// Token estimation
|
|
289
|
+
// ---------------------------------------------------------------------------
|
|
290
|
+
function estimateTokens(content) {
|
|
291
|
+
return Math.ceil(content.length / 4);
|
|
292
|
+
}
|
|
293
|
+
//# sourceMappingURL=SemanticChunker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SemanticChunker.js","sourceRoot":"","sources":["../../src/context/SemanticChunker.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extracts structural signatures from TypeScript source files using the AST.
|
|
3
|
+
*
|
|
4
|
+
* A "signature" is a representation that preserves the public shape of a
|
|
5
|
+
* declaration (name, parameters, return types, generics, modifiers) without
|
|
6
|
+
* including the implementation body. This gives an LLM full type information
|
|
7
|
+
* at a fraction of the token cost of the full source.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```ts
|
|
11
|
+
* const extractor = new SignatureExtractor();
|
|
12
|
+
* const sig = extractor.extract('/path/to/UserService.ts');
|
|
13
|
+
* // → "export class UserService {\n constructor(...);\n async createUser(...);\n}"
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
export declare class SignatureExtractor {
|
|
17
|
+
private readonly project;
|
|
18
|
+
constructor();
|
|
19
|
+
/**
|
|
20
|
+
* Extracts the signature string for all top-level declarations in the file.
|
|
21
|
+
*
|
|
22
|
+
* The returned string is valid(ish) TypeScript with implementation bodies
|
|
23
|
+
* replaced by `;`. Import statements are preserved verbatim so the LLM
|
|
24
|
+
* retains the dependency context.
|
|
25
|
+
*
|
|
26
|
+
* @param filePath - Absolute path to the source file.
|
|
27
|
+
* @returns The full signature representation as a string.
|
|
28
|
+
*/
|
|
29
|
+
extract(filePath: string): string;
|
|
30
|
+
/**
|
|
31
|
+
* Extracts the signature string from raw TypeScript source text.
|
|
32
|
+
* Useful when the file is not on disk (e.g. in tests or virtual filesystems).
|
|
33
|
+
*
|
|
34
|
+
* @param content - Raw TypeScript source text.
|
|
35
|
+
* @param fileName - Virtual file name used to determine language (must end in `.ts` or `.tsx`).
|
|
36
|
+
*/
|
|
37
|
+
extractFromText(content: string, fileName: string): string;
|
|
38
|
+
private buildSignatureString;
|
|
39
|
+
private extractClassSignature;
|
|
40
|
+
private extractFunctionSignature;
|
|
41
|
+
private extractVariableSignature;
|
|
42
|
+
/**
|
|
43
|
+
* Strips a function/method body by replacing `{ ... }` with `;`.
|
|
44
|
+
*
|
|
45
|
+
* Works by locating the last `{` block in the text representation.
|
|
46
|
+
*/
|
|
47
|
+
private stripBody;
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=SignatureExtractor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SignatureExtractor.d.ts","sourceRoot":"","sources":["../../src/context/SignatureExtractor.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;GAcG;AACH,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAU;IAElC,cAWC;IAED;;;;;;;;;OASG;IACI,OAAO,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAOvC;IAED;;;;;;OAMG;IACI,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAchE;IAID,OAAO,CAAC,oBAAoB;IA0D5B,OAAO,CAAC,qBAAqB;IAkC7B,OAAO,CAAC,wBAAwB;IAMhC,OAAO,CAAC,wBAAwB;IAShC;;;;OAIG;IACH,OAAO,CAAC,SAAS;CAOlB"}
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import { Project, SourceFile, SyntaxKind } from 'ts-morph';
|
|
2
|
+
/**
|
|
3
|
+
* Extracts structural signatures from TypeScript source files using the AST.
|
|
4
|
+
*
|
|
5
|
+
* A "signature" is a representation that preserves the public shape of a
|
|
6
|
+
* declaration (name, parameters, return types, generics, modifiers) without
|
|
7
|
+
* including the implementation body. This gives an LLM full type information
|
|
8
|
+
* at a fraction of the token cost of the full source.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```ts
|
|
12
|
+
* const extractor = new SignatureExtractor();
|
|
13
|
+
* const sig = extractor.extract('/path/to/UserService.ts');
|
|
14
|
+
* // → "export class UserService {\n constructor(...);\n async createUser(...);\n}"
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
export class SignatureExtractor {
|
|
18
|
+
project;
|
|
19
|
+
constructor() {
|
|
20
|
+
// In-memory project: we add individual source files on demand.
|
|
21
|
+
// No tsconfig.json is needed — we only need type-level text extraction.
|
|
22
|
+
this.project = new Project({
|
|
23
|
+
useInMemoryFileSystem: false,
|
|
24
|
+
skipFileDependencyResolution: true,
|
|
25
|
+
compilerOptions: {
|
|
26
|
+
allowJs: true,
|
|
27
|
+
noResolve: true,
|
|
28
|
+
},
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Extracts the signature string for all top-level declarations in the file.
|
|
33
|
+
*
|
|
34
|
+
* The returned string is valid(ish) TypeScript with implementation bodies
|
|
35
|
+
* replaced by `;`. Import statements are preserved verbatim so the LLM
|
|
36
|
+
* retains the dependency context.
|
|
37
|
+
*
|
|
38
|
+
* @param filePath - Absolute path to the source file.
|
|
39
|
+
* @returns The full signature representation as a string.
|
|
40
|
+
*/
|
|
41
|
+
extract(filePath) {
|
|
42
|
+
// Reuse an existing source file if already added; add it otherwise.
|
|
43
|
+
const sourceFile = this.project.getSourceFile(filePath) ??
|
|
44
|
+
this.project.addSourceFileAtPath(filePath);
|
|
45
|
+
return this.buildSignatureString(sourceFile);
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Extracts the signature string from raw TypeScript source text.
|
|
49
|
+
* Useful when the file is not on disk (e.g. in tests or virtual filesystems).
|
|
50
|
+
*
|
|
51
|
+
* @param content - Raw TypeScript source text.
|
|
52
|
+
* @param fileName - Virtual file name used to determine language (must end in `.ts` or `.tsx`).
|
|
53
|
+
*/
|
|
54
|
+
extractFromText(content, fileName) {
|
|
55
|
+
const key = `__virtual__/${fileName}`;
|
|
56
|
+
// Remove any stale virtual file before re-adding
|
|
57
|
+
const existing = this.project.getSourceFile(key);
|
|
58
|
+
if (existing) {
|
|
59
|
+
this.project.removeSourceFile(existing);
|
|
60
|
+
}
|
|
61
|
+
const sourceFile = this.project.createSourceFile(key, content, {
|
|
62
|
+
overwrite: true,
|
|
63
|
+
});
|
|
64
|
+
const result = this.buildSignatureString(sourceFile);
|
|
65
|
+
// Clean up after extraction to avoid memory bloat
|
|
66
|
+
this.project.removeSourceFile(sourceFile);
|
|
67
|
+
return result;
|
|
68
|
+
}
|
|
69
|
+
// ---- Core extraction logic -----------------------------------------------
|
|
70
|
+
buildSignatureString(sourceFile) {
|
|
71
|
+
const lines = [];
|
|
72
|
+
for (const statement of sourceFile.getStatements()) {
|
|
73
|
+
const kind = statement.getKind();
|
|
74
|
+
switch (kind) {
|
|
75
|
+
// Preserve import/export declarations verbatim
|
|
76
|
+
case SyntaxKind.ImportDeclaration:
|
|
77
|
+
case SyntaxKind.ExportDeclaration:
|
|
78
|
+
lines.push(statement.getText());
|
|
79
|
+
break;
|
|
80
|
+
case SyntaxKind.ClassDeclaration: {
|
|
81
|
+
lines.push(this.extractClassSignature(statement));
|
|
82
|
+
break;
|
|
83
|
+
}
|
|
84
|
+
case SyntaxKind.InterfaceDeclaration: {
|
|
85
|
+
// Interfaces have no bodies to strip — include as-is
|
|
86
|
+
lines.push(statement.getText());
|
|
87
|
+
break;
|
|
88
|
+
}
|
|
89
|
+
case SyntaxKind.FunctionDeclaration: {
|
|
90
|
+
lines.push(this.extractFunctionSignature(statement));
|
|
91
|
+
break;
|
|
92
|
+
}
|
|
93
|
+
case SyntaxKind.TypeAliasDeclaration:
|
|
94
|
+
case SyntaxKind.EnumDeclaration: {
|
|
95
|
+
// Type aliases and enums are declarations without bodies
|
|
96
|
+
lines.push(statement.getText());
|
|
97
|
+
break;
|
|
98
|
+
}
|
|
99
|
+
case SyntaxKind.VariableStatement: {
|
|
100
|
+
lines.push(this.extractVariableSignature(statement));
|
|
101
|
+
break;
|
|
102
|
+
}
|
|
103
|
+
case SyntaxKind.ExpressionStatement: {
|
|
104
|
+
// Skip bare expression statements (e.g. `defaultUser.doSomething()`)
|
|
105
|
+
break;
|
|
106
|
+
}
|
|
107
|
+
default:
|
|
108
|
+
// Unknown statement kind — include the first line as a comment
|
|
109
|
+
// so the LLM knows something exists without including large blobs.
|
|
110
|
+
break;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
return lines.join('\n').trim();
|
|
114
|
+
}
|
|
115
|
+
// ---- Per-declaration extractors ------------------------------------------
|
|
116
|
+
extractClassSignature(node) {
|
|
117
|
+
const classDecl = node.asKindOrThrow(SyntaxKind.ClassDeclaration);
|
|
118
|
+
const memberLines = [];
|
|
119
|
+
for (const member of classDecl.getMembers()) {
|
|
120
|
+
const memberKind = member.getKind();
|
|
121
|
+
if (memberKind === SyntaxKind.Constructor ||
|
|
122
|
+
memberKind === SyntaxKind.MethodDeclaration) {
|
|
123
|
+
memberLines.push(' ' + this.stripBody(member.getText()));
|
|
124
|
+
}
|
|
125
|
+
else if (memberKind === SyntaxKind.PropertyDeclaration ||
|
|
126
|
+
memberKind === SyntaxKind.GetAccessor ||
|
|
127
|
+
memberKind === SyntaxKind.SetAccessor) {
|
|
128
|
+
// Properties and accessors: emit declaration line only
|
|
129
|
+
const text = member.getText().split('\n')[0];
|
|
130
|
+
memberLines.push(' ' + (text ?? '').trim());
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
// Class "header": everything up to the first `{`
|
|
134
|
+
const classText = classDecl.getText();
|
|
135
|
+
const braceIndex = classText.indexOf('{');
|
|
136
|
+
const header = braceIndex !== -1 ? classText.slice(0, braceIndex).trimEnd() : classText;
|
|
137
|
+
if (memberLines.length === 0) {
|
|
138
|
+
return `${header} {}`;
|
|
139
|
+
}
|
|
140
|
+
return `${header} {\n${memberLines.join('\n')}\n}`;
|
|
141
|
+
}
|
|
142
|
+
extractFunctionSignature(node) {
|
|
143
|
+
const fn = node.asKindOrThrow(SyntaxKind.FunctionDeclaration);
|
|
144
|
+
const fullText = fn.getText();
|
|
145
|
+
return this.stripBody(fullText);
|
|
146
|
+
}
|
|
147
|
+
extractVariableSignature(node) {
|
|
148
|
+
const varStmt = node.asKindOrThrow(SyntaxKind.VariableStatement);
|
|
149
|
+
// Include only the first line (the declaration) — the initialiser is
|
|
150
|
+
// usually an implementation detail.
|
|
151
|
+
return varStmt.getText().split('\n')[0] ?? varStmt.getText();
|
|
152
|
+
}
|
|
153
|
+
// ---- Helpers -------------------------------------------------------------
|
|
154
|
+
/**
|
|
155
|
+
* Strips a function/method body by replacing `{ ... }` with `;`.
|
|
156
|
+
*
|
|
157
|
+
* Works by locating the last `{` block in the text representation.
|
|
158
|
+
*/
|
|
159
|
+
stripBody(text) {
|
|
160
|
+
const bodyStart = text.indexOf('{');
|
|
161
|
+
if (bodyStart === -1)
|
|
162
|
+
return text.trim();
|
|
163
|
+
const signature = text.slice(0, bodyStart).trimEnd();
|
|
164
|
+
return `${signature};`;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
//# sourceMappingURL=SignatureExtractor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SignatureExtractor.js","sourceRoot":"","sources":["../../src/context/SignatureExtractor.ts"],"names":[],"mappings":"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"}
|