@git.zone/tsdoc 1.4.5 → 1.5.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/dist_ts/00_commitinfo_data.js +3 -3
- package/dist_ts/aidocs_classes/commit.js +16 -10
- package/dist_ts/aidocs_classes/description.js +14 -6
- package/dist_ts/aidocs_classes/projectcontext.d.ts +22 -0
- package/dist_ts/aidocs_classes/projectcontext.js +41 -1
- package/dist_ts/aidocs_classes/readme.js +10 -4
- package/dist_ts/classes.aidoc.d.ts +23 -0
- package/dist_ts/classes.aidoc.js +34 -1
- package/dist_ts/cli.js +110 -1
- package/dist_ts/context/config-manager.d.ts +58 -0
- package/dist_ts/context/config-manager.js +183 -0
- package/dist_ts/context/context-trimmer.d.ts +52 -0
- package/dist_ts/context/context-trimmer.js +199 -0
- package/dist_ts/context/enhanced-context.d.ts +75 -0
- package/dist_ts/context/enhanced-context.js +272 -0
- package/dist_ts/context/index.d.ts +7 -0
- package/dist_ts/context/index.js +8 -0
- package/dist_ts/context/task-context-factory.d.ts +46 -0
- package/dist_ts/context/task-context-factory.js +109 -0
- package/dist_ts/context/types.d.ts +89 -0
- package/dist_ts/context/types.js +2 -0
- package/dist_ts/plugins.d.ts +2 -1
- package/dist_ts/plugins.js +3 -2
- package/npmextra.json +10 -9
- package/package.json +25 -23
- package/readme.md +588 -174
- package/readme.plan.md +314 -0
- package/ts/00_commitinfo_data.ts +2 -2
- package/ts/aidocs_classes/commit.ts +21 -9
- package/ts/aidocs_classes/description.ts +16 -5
- package/ts/aidocs_classes/projectcontext.ts +43 -0
- package/ts/aidocs_classes/readme.ts +11 -3
- package/ts/classes.aidoc.ts +37 -0
- package/ts/cli.ts +128 -0
- package/ts/context/config-manager.ts +209 -0
- package/ts/context/context-trimmer.ts +246 -0
- package/ts/context/enhanced-context.ts +343 -0
- package/ts/context/index.ts +32 -0
- package/ts/context/task-context-factory.ts +138 -0
- package/ts/context/types.ts +95 -0
- package/ts/plugins.ts +2 -1
|
@@ -0,0 +1,343 @@
|
|
|
1
|
+
import * as plugins from '../plugins.js';
|
|
2
|
+
import type { ContextMode, IContextResult, IFileInfo, TaskType } from './types.js';
|
|
3
|
+
import { ContextTrimmer } from './context-trimmer.js';
|
|
4
|
+
import { ConfigManager } from './config-manager.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Enhanced ProjectContext that supports context optimization strategies
|
|
8
|
+
*/
|
|
9
|
+
export class EnhancedContext {
|
|
10
|
+
private projectDir: string;
|
|
11
|
+
private trimmer: ContextTrimmer;
|
|
12
|
+
private configManager: ConfigManager;
|
|
13
|
+
private contextMode: ContextMode = 'trimmed';
|
|
14
|
+
private tokenBudget: number = 190000; // Default for o4-mini
|
|
15
|
+
private contextResult: IContextResult = {
|
|
16
|
+
context: '',
|
|
17
|
+
tokenCount: 0,
|
|
18
|
+
includedFiles: [],
|
|
19
|
+
trimmedFiles: [],
|
|
20
|
+
excludedFiles: [],
|
|
21
|
+
tokenSavings: 0
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Create a new EnhancedContext
|
|
26
|
+
* @param projectDirArg The project directory
|
|
27
|
+
*/
|
|
28
|
+
constructor(projectDirArg: string) {
|
|
29
|
+
this.projectDir = projectDirArg;
|
|
30
|
+
this.configManager = ConfigManager.getInstance();
|
|
31
|
+
this.trimmer = new ContextTrimmer(this.configManager.getTrimConfig());
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Initialize the context builder
|
|
36
|
+
*/
|
|
37
|
+
public async initialize(): Promise<void> {
|
|
38
|
+
await this.configManager.initialize(this.projectDir);
|
|
39
|
+
this.tokenBudget = this.configManager.getMaxTokens();
|
|
40
|
+
this.trimmer.updateConfig(this.configManager.getTrimConfig());
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Set the context mode
|
|
45
|
+
* @param mode The context mode to use
|
|
46
|
+
*/
|
|
47
|
+
public setContextMode(mode: ContextMode): void {
|
|
48
|
+
this.contextMode = mode;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Set the token budget
|
|
53
|
+
* @param maxTokens The maximum tokens to use
|
|
54
|
+
*/
|
|
55
|
+
public setTokenBudget(maxTokens: number): void {
|
|
56
|
+
this.tokenBudget = maxTokens;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Gather files from the project
|
|
61
|
+
* @param includePaths Optional paths to include
|
|
62
|
+
* @param excludePaths Optional paths to exclude
|
|
63
|
+
*/
|
|
64
|
+
public async gatherFiles(includePaths?: string[], excludePaths?: string[]): Promise<Record<string, plugins.smartfile.SmartFile | plugins.smartfile.SmartFile[]>> {
|
|
65
|
+
const smartfilePackageJSON = await plugins.smartfile.SmartFile.fromFilePath(
|
|
66
|
+
plugins.path.join(this.projectDir, 'package.json'),
|
|
67
|
+
this.projectDir,
|
|
68
|
+
);
|
|
69
|
+
|
|
70
|
+
const smartfilesReadme = await plugins.smartfile.SmartFile.fromFilePath(
|
|
71
|
+
plugins.path.join(this.projectDir, 'readme.md'),
|
|
72
|
+
this.projectDir,
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
const smartfilesReadmeHints = await plugins.smartfile.SmartFile.fromFilePath(
|
|
76
|
+
plugins.path.join(this.projectDir, 'readme.hints.md'),
|
|
77
|
+
this.projectDir,
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
const smartfilesNpmextraJSON = await plugins.smartfile.SmartFile.fromFilePath(
|
|
81
|
+
plugins.path.join(this.projectDir, 'npmextra.json'),
|
|
82
|
+
this.projectDir,
|
|
83
|
+
);
|
|
84
|
+
|
|
85
|
+
// Use provided include paths or default to all TypeScript files
|
|
86
|
+
const includeGlobs = includePaths?.map(path => `${path}/**/*.ts`) || ['ts*/**/*.ts'];
|
|
87
|
+
|
|
88
|
+
// Get TypeScript files
|
|
89
|
+
const smartfilesModPromises = includeGlobs.map(glob =>
|
|
90
|
+
plugins.smartfile.fs.fileTreeToObject(this.projectDir, glob)
|
|
91
|
+
);
|
|
92
|
+
|
|
93
|
+
const smartfilesModArrays = await Promise.all(smartfilesModPromises);
|
|
94
|
+
|
|
95
|
+
// Flatten the arrays
|
|
96
|
+
const smartfilesMod: plugins.smartfile.SmartFile[] = [];
|
|
97
|
+
smartfilesModArrays.forEach(array => {
|
|
98
|
+
smartfilesMod.push(...array);
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
// Get test files if not excluded
|
|
102
|
+
let smartfilesTest: plugins.smartfile.SmartFile[] = [];
|
|
103
|
+
if (!excludePaths?.includes('test/')) {
|
|
104
|
+
smartfilesTest = await plugins.smartfile.fs.fileTreeToObject(
|
|
105
|
+
this.projectDir,
|
|
106
|
+
'test/**/*.ts',
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
return {
|
|
111
|
+
smartfilePackageJSON,
|
|
112
|
+
smartfilesReadme,
|
|
113
|
+
smartfilesReadmeHints,
|
|
114
|
+
smartfilesNpmextraJSON,
|
|
115
|
+
smartfilesMod,
|
|
116
|
+
smartfilesTest,
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Convert files to context string
|
|
122
|
+
* @param files The files to convert
|
|
123
|
+
* @param mode The context mode to use
|
|
124
|
+
*/
|
|
125
|
+
public async convertFilesToContext(
|
|
126
|
+
files: plugins.smartfile.SmartFile[],
|
|
127
|
+
mode: ContextMode = this.contextMode
|
|
128
|
+
): Promise<string> {
|
|
129
|
+
// Reset context result
|
|
130
|
+
this.contextResult = {
|
|
131
|
+
context: '',
|
|
132
|
+
tokenCount: 0,
|
|
133
|
+
includedFiles: [],
|
|
134
|
+
trimmedFiles: [],
|
|
135
|
+
excludedFiles: [],
|
|
136
|
+
tokenSavings: 0
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
let totalTokenCount = 0;
|
|
140
|
+
let totalOriginalTokens = 0;
|
|
141
|
+
|
|
142
|
+
// Sort files by importance (for now just a simple alphabetical sort)
|
|
143
|
+
// Later this could be enhanced with more sophisticated prioritization
|
|
144
|
+
const sortedFiles = [...files].sort((a, b) => a.relative.localeCompare(b.relative));
|
|
145
|
+
|
|
146
|
+
const processedFiles: string[] = [];
|
|
147
|
+
|
|
148
|
+
for (const smartfile of sortedFiles) {
|
|
149
|
+
// Calculate original token count
|
|
150
|
+
const originalContent = smartfile.contents.toString();
|
|
151
|
+
const originalTokenCount = this.countTokens(originalContent);
|
|
152
|
+
totalOriginalTokens += originalTokenCount;
|
|
153
|
+
|
|
154
|
+
// Apply trimming based on mode
|
|
155
|
+
let processedContent = originalContent;
|
|
156
|
+
|
|
157
|
+
if (mode !== 'full') {
|
|
158
|
+
processedContent = this.trimmer.trimFile(
|
|
159
|
+
smartfile.relative,
|
|
160
|
+
originalContent,
|
|
161
|
+
mode
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// Calculate new token count
|
|
166
|
+
const processedTokenCount = this.countTokens(processedContent);
|
|
167
|
+
|
|
168
|
+
// Check if we have budget for this file
|
|
169
|
+
if (totalTokenCount + processedTokenCount > this.tokenBudget) {
|
|
170
|
+
// We don't have budget for this file
|
|
171
|
+
this.contextResult.excludedFiles.push({
|
|
172
|
+
path: smartfile.path,
|
|
173
|
+
contents: originalContent,
|
|
174
|
+
relativePath: smartfile.relative,
|
|
175
|
+
tokenCount: originalTokenCount
|
|
176
|
+
});
|
|
177
|
+
continue;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// Format the file for context
|
|
181
|
+
const formattedContent = `
|
|
182
|
+
====== START OF FILE ${smartfile.relative} ======
|
|
183
|
+
|
|
184
|
+
${processedContent}
|
|
185
|
+
|
|
186
|
+
====== END OF FILE ${smartfile.relative} ======
|
|
187
|
+
`;
|
|
188
|
+
|
|
189
|
+
processedFiles.push(formattedContent);
|
|
190
|
+
totalTokenCount += processedTokenCount;
|
|
191
|
+
|
|
192
|
+
// Track file in appropriate list
|
|
193
|
+
const fileInfo: IFileInfo = {
|
|
194
|
+
path: smartfile.path,
|
|
195
|
+
contents: processedContent,
|
|
196
|
+
relativePath: smartfile.relative,
|
|
197
|
+
tokenCount: processedTokenCount
|
|
198
|
+
};
|
|
199
|
+
|
|
200
|
+
if (mode === 'full' || processedContent === originalContent) {
|
|
201
|
+
this.contextResult.includedFiles.push(fileInfo);
|
|
202
|
+
} else {
|
|
203
|
+
this.contextResult.trimmedFiles.push(fileInfo);
|
|
204
|
+
this.contextResult.tokenSavings += (originalTokenCount - processedTokenCount);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// Join all processed files
|
|
209
|
+
const context = processedFiles.join('\n');
|
|
210
|
+
|
|
211
|
+
// Update context result
|
|
212
|
+
this.contextResult.context = context;
|
|
213
|
+
this.contextResult.tokenCount = totalTokenCount;
|
|
214
|
+
|
|
215
|
+
return context;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Build context for the project
|
|
220
|
+
* @param taskType Optional task type for task-specific context
|
|
221
|
+
*/
|
|
222
|
+
public async buildContext(taskType?: TaskType): Promise<IContextResult> {
|
|
223
|
+
// Initialize if needed
|
|
224
|
+
if (this.tokenBudget === 0) {
|
|
225
|
+
await this.initialize();
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// Get task-specific configuration if a task type is provided
|
|
229
|
+
if (taskType) {
|
|
230
|
+
const taskConfig = this.configManager.getTaskConfig(taskType);
|
|
231
|
+
if (taskConfig.mode) {
|
|
232
|
+
this.setContextMode(taskConfig.mode);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// Gather files
|
|
237
|
+
const taskConfig = taskType ? this.configManager.getTaskConfig(taskType) : undefined;
|
|
238
|
+
const files = await this.gatherFiles(
|
|
239
|
+
taskConfig?.includePaths,
|
|
240
|
+
taskConfig?.excludePaths
|
|
241
|
+
);
|
|
242
|
+
|
|
243
|
+
// Convert files to context
|
|
244
|
+
// Create an array of all files to process
|
|
245
|
+
const allFiles: plugins.smartfile.SmartFile[] = [];
|
|
246
|
+
|
|
247
|
+
// Add individual files
|
|
248
|
+
if (files.smartfilePackageJSON) allFiles.push(files.smartfilePackageJSON as plugins.smartfile.SmartFile);
|
|
249
|
+
if (files.smartfilesReadme) allFiles.push(files.smartfilesReadme as plugins.smartfile.SmartFile);
|
|
250
|
+
if (files.smartfilesReadmeHints) allFiles.push(files.smartfilesReadmeHints as plugins.smartfile.SmartFile);
|
|
251
|
+
if (files.smartfilesNpmextraJSON) allFiles.push(files.smartfilesNpmextraJSON as plugins.smartfile.SmartFile);
|
|
252
|
+
|
|
253
|
+
// Add arrays of files
|
|
254
|
+
if (files.smartfilesMod) {
|
|
255
|
+
if (Array.isArray(files.smartfilesMod)) {
|
|
256
|
+
allFiles.push(...files.smartfilesMod);
|
|
257
|
+
} else {
|
|
258
|
+
allFiles.push(files.smartfilesMod);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
if (files.smartfilesTest) {
|
|
263
|
+
if (Array.isArray(files.smartfilesTest)) {
|
|
264
|
+
allFiles.push(...files.smartfilesTest);
|
|
265
|
+
} else {
|
|
266
|
+
allFiles.push(files.smartfilesTest);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
const context = await this.convertFilesToContext(allFiles);
|
|
271
|
+
|
|
272
|
+
return this.contextResult;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* Update the context with git diff information for commit tasks
|
|
277
|
+
* @param gitDiff The git diff to include
|
|
278
|
+
*/
|
|
279
|
+
public updateWithGitDiff(gitDiff: string): IContextResult {
|
|
280
|
+
// If we don't have a context yet, return empty result
|
|
281
|
+
if (!this.contextResult.context) {
|
|
282
|
+
return this.contextResult;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
// Add git diff to context
|
|
286
|
+
const diffSection = `
|
|
287
|
+
====== GIT DIFF ======
|
|
288
|
+
|
|
289
|
+
${gitDiff}
|
|
290
|
+
|
|
291
|
+
====== END GIT DIFF ======
|
|
292
|
+
`;
|
|
293
|
+
|
|
294
|
+
const diffTokenCount = this.countTokens(diffSection);
|
|
295
|
+
|
|
296
|
+
// Update context and token count
|
|
297
|
+
this.contextResult.context += diffSection;
|
|
298
|
+
this.contextResult.tokenCount += diffTokenCount;
|
|
299
|
+
|
|
300
|
+
return this.contextResult;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
/**
|
|
304
|
+
* Count tokens in a string
|
|
305
|
+
* @param text The text to count tokens for
|
|
306
|
+
* @param model The model to use for token counting
|
|
307
|
+
*/
|
|
308
|
+
public countTokens(text: string, model: string = 'gpt-3.5-turbo'): number {
|
|
309
|
+
try {
|
|
310
|
+
// Use the gpt-tokenizer library to count tokens
|
|
311
|
+
const tokens = plugins.gptTokenizer.encode(text);
|
|
312
|
+
return tokens.length;
|
|
313
|
+
} catch (error) {
|
|
314
|
+
console.error('Error counting tokens:', error);
|
|
315
|
+
// Provide a rough estimate if tokenization fails
|
|
316
|
+
return Math.ceil(text.length / 4);
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
/**
|
|
321
|
+
* Get the context result
|
|
322
|
+
*/
|
|
323
|
+
public getContextResult(): IContextResult {
|
|
324
|
+
return this.contextResult;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
/**
|
|
328
|
+
* Get the token count for the current context
|
|
329
|
+
*/
|
|
330
|
+
public getTokenCount(): number {
|
|
331
|
+
return this.contextResult.tokenCount;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
/**
|
|
335
|
+
* Get both the context string and its token count
|
|
336
|
+
*/
|
|
337
|
+
public getContextWithTokenCount(): { context: string; tokenCount: number } {
|
|
338
|
+
return {
|
|
339
|
+
context: this.contextResult.context,
|
|
340
|
+
tokenCount: this.contextResult.tokenCount
|
|
341
|
+
};
|
|
342
|
+
}
|
|
343
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { EnhancedContext } from './enhanced-context.js';
|
|
2
|
+
import { TaskContextFactory } from './task-context-factory.js';
|
|
3
|
+
import { ConfigManager } from './config-manager.js';
|
|
4
|
+
import { ContextTrimmer } from './context-trimmer.js';
|
|
5
|
+
import type {
|
|
6
|
+
ContextMode,
|
|
7
|
+
IContextConfig,
|
|
8
|
+
IContextResult,
|
|
9
|
+
IFileInfo,
|
|
10
|
+
ITrimConfig,
|
|
11
|
+
ITaskConfig,
|
|
12
|
+
TaskType
|
|
13
|
+
} from './types.js';
|
|
14
|
+
|
|
15
|
+
export {
|
|
16
|
+
// Classes
|
|
17
|
+
EnhancedContext,
|
|
18
|
+
TaskContextFactory,
|
|
19
|
+
ConfigManager,
|
|
20
|
+
ContextTrimmer,
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
// Types
|
|
24
|
+
export type {
|
|
25
|
+
ContextMode,
|
|
26
|
+
IContextConfig,
|
|
27
|
+
IContextResult,
|
|
28
|
+
IFileInfo,
|
|
29
|
+
ITrimConfig,
|
|
30
|
+
ITaskConfig,
|
|
31
|
+
TaskType
|
|
32
|
+
};
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import * as plugins from '../plugins.js';
|
|
2
|
+
import { EnhancedContext } from './enhanced-context.js';
|
|
3
|
+
import { ConfigManager } from './config-manager.js';
|
|
4
|
+
import type { IContextResult, TaskType } from './types.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Factory class for creating task-specific context
|
|
8
|
+
*/
|
|
9
|
+
export class TaskContextFactory {
|
|
10
|
+
private projectDir: string;
|
|
11
|
+
private configManager: ConfigManager;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Create a new TaskContextFactory
|
|
15
|
+
* @param projectDirArg The project directory
|
|
16
|
+
*/
|
|
17
|
+
constructor(projectDirArg: string) {
|
|
18
|
+
this.projectDir = projectDirArg;
|
|
19
|
+
this.configManager = ConfigManager.getInstance();
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Initialize the factory
|
|
24
|
+
*/
|
|
25
|
+
public async initialize(): Promise<void> {
|
|
26
|
+
await this.configManager.initialize(this.projectDir);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Create context for README generation
|
|
31
|
+
*/
|
|
32
|
+
public async createContextForReadme(): Promise<IContextResult> {
|
|
33
|
+
const contextBuilder = new EnhancedContext(this.projectDir);
|
|
34
|
+
await contextBuilder.initialize();
|
|
35
|
+
|
|
36
|
+
// Get README-specific configuration
|
|
37
|
+
const taskConfig = this.configManager.getTaskConfig('readme');
|
|
38
|
+
if (taskConfig.mode) {
|
|
39
|
+
contextBuilder.setContextMode(taskConfig.mode);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Build the context for README task
|
|
43
|
+
return await contextBuilder.buildContext('readme');
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Create context for description generation
|
|
48
|
+
*/
|
|
49
|
+
public async createContextForDescription(): Promise<IContextResult> {
|
|
50
|
+
const contextBuilder = new EnhancedContext(this.projectDir);
|
|
51
|
+
await contextBuilder.initialize();
|
|
52
|
+
|
|
53
|
+
// Get description-specific configuration
|
|
54
|
+
const taskConfig = this.configManager.getTaskConfig('description');
|
|
55
|
+
if (taskConfig.mode) {
|
|
56
|
+
contextBuilder.setContextMode(taskConfig.mode);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Build the context for description task
|
|
60
|
+
return await contextBuilder.buildContext('description');
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Create context for commit message generation
|
|
65
|
+
* @param gitDiff Optional git diff to include
|
|
66
|
+
*/
|
|
67
|
+
public async createContextForCommit(gitDiff?: string): Promise<IContextResult> {
|
|
68
|
+
const contextBuilder = new EnhancedContext(this.projectDir);
|
|
69
|
+
await contextBuilder.initialize();
|
|
70
|
+
|
|
71
|
+
// Get commit-specific configuration
|
|
72
|
+
const taskConfig = this.configManager.getTaskConfig('commit');
|
|
73
|
+
if (taskConfig.mode) {
|
|
74
|
+
contextBuilder.setContextMode(taskConfig.mode);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Build the context for commit task
|
|
78
|
+
const contextResult = await contextBuilder.buildContext('commit');
|
|
79
|
+
|
|
80
|
+
// If git diff is provided, add it to the context
|
|
81
|
+
if (gitDiff) {
|
|
82
|
+
contextBuilder.updateWithGitDiff(gitDiff);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return contextBuilder.getContextResult();
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Create context for any task type
|
|
90
|
+
* @param taskType The task type to create context for
|
|
91
|
+
* @param additionalContent Optional additional content to include
|
|
92
|
+
*/
|
|
93
|
+
public async createContextForTask(
|
|
94
|
+
taskType: TaskType,
|
|
95
|
+
additionalContent?: string
|
|
96
|
+
): Promise<IContextResult> {
|
|
97
|
+
switch (taskType) {
|
|
98
|
+
case 'readme':
|
|
99
|
+
return this.createContextForReadme();
|
|
100
|
+
case 'description':
|
|
101
|
+
return this.createContextForDescription();
|
|
102
|
+
case 'commit':
|
|
103
|
+
return this.createContextForCommit(additionalContent);
|
|
104
|
+
default:
|
|
105
|
+
// Generic context for unknown task types
|
|
106
|
+
const contextBuilder = new EnhancedContext(this.projectDir);
|
|
107
|
+
await contextBuilder.initialize();
|
|
108
|
+
return await contextBuilder.buildContext();
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Get token stats for all task types
|
|
114
|
+
*/
|
|
115
|
+
public async getTokenStats(): Promise<Record<TaskType, {
|
|
116
|
+
tokenCount: number;
|
|
117
|
+
savings: number;
|
|
118
|
+
includedFiles: number;
|
|
119
|
+
trimmedFiles: number;
|
|
120
|
+
excludedFiles: number;
|
|
121
|
+
}>> {
|
|
122
|
+
const taskTypes: TaskType[] = ['readme', 'description', 'commit'];
|
|
123
|
+
const stats: Record<TaskType, any> = {} as any;
|
|
124
|
+
|
|
125
|
+
for (const taskType of taskTypes) {
|
|
126
|
+
const result = await this.createContextForTask(taskType);
|
|
127
|
+
stats[taskType] = {
|
|
128
|
+
tokenCount: result.tokenCount,
|
|
129
|
+
savings: result.tokenSavings,
|
|
130
|
+
includedFiles: result.includedFiles.length,
|
|
131
|
+
trimmedFiles: result.trimmedFiles.length,
|
|
132
|
+
excludedFiles: result.excludedFiles.length
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
return stats;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Context processing mode to control how context is built
|
|
3
|
+
*/
|
|
4
|
+
export type ContextMode = 'full' | 'trimmed' | 'summarized';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Configuration for context trimming
|
|
8
|
+
*/
|
|
9
|
+
export interface ITrimConfig {
|
|
10
|
+
/** Whether to remove function implementations */
|
|
11
|
+
removeImplementations?: boolean;
|
|
12
|
+
/** Whether to preserve interface definitions */
|
|
13
|
+
preserveInterfaces?: boolean;
|
|
14
|
+
/** Whether to preserve type definitions */
|
|
15
|
+
preserveTypeDefs?: boolean;
|
|
16
|
+
/** Whether to preserve JSDoc comments */
|
|
17
|
+
preserveJSDoc?: boolean;
|
|
18
|
+
/** Maximum lines to keep for function bodies (if not removing completely) */
|
|
19
|
+
maxFunctionLines?: number;
|
|
20
|
+
/** Whether to remove normal comments (non-JSDoc) */
|
|
21
|
+
removeComments?: boolean;
|
|
22
|
+
/** Whether to remove blank lines */
|
|
23
|
+
removeBlankLines?: boolean;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Task types that require different context optimization
|
|
28
|
+
*/
|
|
29
|
+
export type TaskType = 'readme' | 'commit' | 'description';
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Configuration for different tasks
|
|
33
|
+
*/
|
|
34
|
+
export interface ITaskConfig {
|
|
35
|
+
/** The context mode to use for this task */
|
|
36
|
+
mode?: ContextMode;
|
|
37
|
+
/** File paths to include for this task */
|
|
38
|
+
includePaths?: string[];
|
|
39
|
+
/** File paths to exclude for this task */
|
|
40
|
+
excludePaths?: string[];
|
|
41
|
+
/** For commit tasks, whether to focus on changed files */
|
|
42
|
+
focusOnChangedFiles?: boolean;
|
|
43
|
+
/** For description tasks, whether to include package info */
|
|
44
|
+
includePackageInfo?: boolean;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Complete context configuration
|
|
49
|
+
*/
|
|
50
|
+
export interface IContextConfig {
|
|
51
|
+
/** Maximum tokens to use for context */
|
|
52
|
+
maxTokens?: number;
|
|
53
|
+
/** Default context mode */
|
|
54
|
+
defaultMode?: ContextMode;
|
|
55
|
+
/** Task-specific settings */
|
|
56
|
+
taskSpecificSettings?: {
|
|
57
|
+
[key in TaskType]?: ITaskConfig;
|
|
58
|
+
};
|
|
59
|
+
/** Trimming configuration */
|
|
60
|
+
trimming?: ITrimConfig;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Basic file information interface
|
|
65
|
+
*/
|
|
66
|
+
export interface IFileInfo {
|
|
67
|
+
/** The file path */
|
|
68
|
+
path: string;
|
|
69
|
+
/** The file contents */
|
|
70
|
+
contents: string;
|
|
71
|
+
/** The file's relative path from the project root */
|
|
72
|
+
relativePath: string;
|
|
73
|
+
/** The estimated token count of the file */
|
|
74
|
+
tokenCount?: number;
|
|
75
|
+
/** The file's importance score (higher is more important) */
|
|
76
|
+
importanceScore?: number;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Result of context building
|
|
81
|
+
*/
|
|
82
|
+
export interface IContextResult {
|
|
83
|
+
/** The generated context string */
|
|
84
|
+
context: string;
|
|
85
|
+
/** The total token count of the context */
|
|
86
|
+
tokenCount: number;
|
|
87
|
+
/** Files included in the context */
|
|
88
|
+
includedFiles: IFileInfo[];
|
|
89
|
+
/** Files that were trimmed */
|
|
90
|
+
trimmedFiles: IFileInfo[];
|
|
91
|
+
/** Files that were excluded */
|
|
92
|
+
excludedFiles: IFileInfo[];
|
|
93
|
+
/** Token savings from trimming */
|
|
94
|
+
tokenSavings: number;
|
|
95
|
+
}
|