@git.zone/tsdoc 1.6.0 → 1.7.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/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/cli.js +10 -25
- package/dist_ts/context/config-manager.d.ts +5 -1
- package/dist_ts/context/config-manager.js +28 -3
- package/dist_ts/context/context-cache.js +2 -1
- package/dist_ts/context/enhanced-context.d.ts +2 -15
- package/dist_ts/context/enhanced-context.js +26 -191
- package/dist_ts/context/index.d.ts +2 -2
- package/dist_ts/context/index.js +1 -1
- package/dist_ts/context/iterative-context-builder.d.ts +58 -0
- package/dist_ts/context/iterative-context-builder.js +361 -0
- package/dist_ts/context/task-context-factory.d.ts +8 -8
- package/dist_ts/context/task-context-factory.js +17 -41
- package/dist_ts/context/types.d.ts +71 -3
- package/package.json +1 -1
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/cli.ts +21 -38
- package/ts/context/config-manager.ts +35 -7
- package/ts/context/context-cache.ts +1 -0
- package/ts/context/enhanced-context.ts +29 -246
- package/ts/context/index.ts +6 -2
- package/ts/context/iterative-context-builder.ts +467 -0
- package/ts/context/task-context-factory.ts +40 -63
- package/ts/context/types.ts +76 -3
|
@@ -62,6 +62,8 @@ export interface IContextConfig {
|
|
|
62
62
|
prioritization?: IPrioritizationWeights;
|
|
63
63
|
/** Tier configuration for adaptive trimming */
|
|
64
64
|
tiers?: ITierConfig;
|
|
65
|
+
/** Iterative context building configuration */
|
|
66
|
+
iterative?: IIterativeConfig;
|
|
65
67
|
}
|
|
66
68
|
/**
|
|
67
69
|
* Cache configuration
|
|
@@ -78,11 +80,10 @@ export interface ICacheConfig {
|
|
|
78
80
|
}
|
|
79
81
|
/**
|
|
80
82
|
* Analyzer configuration
|
|
83
|
+
* Note: Smart analysis is always enabled; this config only controls advanced options
|
|
81
84
|
*/
|
|
82
85
|
export interface IAnalyzerConfig {
|
|
83
|
-
/** Whether
|
|
84
|
-
enabled?: boolean;
|
|
85
|
-
/** Whether to use AI refinement for selection */
|
|
86
|
+
/** Whether to use AI refinement for selection (advanced, disabled by default) */
|
|
86
87
|
useAIRefinement?: boolean;
|
|
87
88
|
/** AI model to use for refinement */
|
|
88
89
|
aiModel?: string;
|
|
@@ -230,3 +231,70 @@ export interface IAnalysisResult {
|
|
|
230
231
|
/** Analysis duration in ms */
|
|
231
232
|
analysisDuration: number;
|
|
232
233
|
}
|
|
234
|
+
/**
|
|
235
|
+
* Configuration for iterative context building
|
|
236
|
+
*/
|
|
237
|
+
export interface IIterativeConfig {
|
|
238
|
+
/** Maximum number of iterations allowed */
|
|
239
|
+
maxIterations?: number;
|
|
240
|
+
/** Maximum files to request in first iteration */
|
|
241
|
+
firstPassFileLimit?: number;
|
|
242
|
+
/** Maximum files to request in subsequent iterations */
|
|
243
|
+
subsequentPassFileLimit?: number;
|
|
244
|
+
/** Temperature for AI decision making (0-1) */
|
|
245
|
+
temperature?: number;
|
|
246
|
+
/** Model to use for iterative decisions */
|
|
247
|
+
model?: string;
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* AI decision for file selection
|
|
251
|
+
*/
|
|
252
|
+
export interface IFileSelectionDecision {
|
|
253
|
+
/** AI's reasoning for file selection */
|
|
254
|
+
reasoning: string;
|
|
255
|
+
/** File paths to load */
|
|
256
|
+
filesToLoad: string[];
|
|
257
|
+
/** Estimated tokens needed */
|
|
258
|
+
estimatedTokensNeeded?: number;
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* AI decision for context sufficiency
|
|
262
|
+
*/
|
|
263
|
+
export interface IContextSufficiencyDecision {
|
|
264
|
+
/** Whether context is sufficient */
|
|
265
|
+
sufficient: boolean;
|
|
266
|
+
/** AI's reasoning */
|
|
267
|
+
reasoning: string;
|
|
268
|
+
/** Additional files needed (if not sufficient) */
|
|
269
|
+
additionalFilesNeeded?: string[];
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* State for a single iteration
|
|
273
|
+
*/
|
|
274
|
+
export interface IIterationState {
|
|
275
|
+
/** Iteration number (1-based) */
|
|
276
|
+
iteration: number;
|
|
277
|
+
/** Files loaded in this iteration */
|
|
278
|
+
filesLoaded: IFileInfo[];
|
|
279
|
+
/** Tokens used in this iteration */
|
|
280
|
+
tokensUsed: number;
|
|
281
|
+
/** Total tokens used so far */
|
|
282
|
+
totalTokensUsed: number;
|
|
283
|
+
/** AI decision made in this iteration */
|
|
284
|
+
decision: IFileSelectionDecision | IContextSufficiencyDecision;
|
|
285
|
+
/** Duration of this iteration in ms */
|
|
286
|
+
duration: number;
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* Result of iterative context building
|
|
290
|
+
*/
|
|
291
|
+
export interface IIterativeContextResult extends IContextResult {
|
|
292
|
+
/** Number of iterations performed */
|
|
293
|
+
iterationCount: number;
|
|
294
|
+
/** Details of each iteration */
|
|
295
|
+
iterations: IIterationState[];
|
|
296
|
+
/** Total API calls made */
|
|
297
|
+
apiCallCount: number;
|
|
298
|
+
/** Total duration in ms */
|
|
299
|
+
totalDuration: number;
|
|
300
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@git.zone/tsdoc",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.7.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "A comprehensive TypeScript documentation tool that leverages AI to generate and enhance project documentation, including dynamic README creation, API docs via TypeDoc, and smart commit message generation.",
|
|
6
6
|
"type": "module",
|
package/ts/00_commitinfo_data.ts
CHANGED
|
@@ -3,6 +3,6 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export const commitinfo = {
|
|
5
5
|
name: '@git.zone/tsdoc',
|
|
6
|
-
version: '1.
|
|
6
|
+
version: '1.7.0',
|
|
7
7
|
description: 'A comprehensive TypeScript documentation tool that leverages AI to generate and enhance project documentation, including dynamic README creation, API docs via TypeDoc, and smart commit message generation.'
|
|
8
8
|
}
|
package/ts/cli.ts
CHANGED
|
@@ -31,18 +31,18 @@ export const run = async () => {
|
|
|
31
31
|
tsdocCli.addCommand('aidoc').subscribe(async (argvArg) => {
|
|
32
32
|
const aidocInstance = new AiDoc();
|
|
33
33
|
await aidocInstance.start();
|
|
34
|
-
|
|
34
|
+
|
|
35
35
|
// Get context token count if requested
|
|
36
36
|
if (argvArg.tokens || argvArg.showTokens) {
|
|
37
37
|
logger.log('info', `Calculating context token count...`);
|
|
38
38
|
const tokenCount = await aidocInstance.getProjectContextTokenCount(paths.cwd);
|
|
39
39
|
logger.log('ok', `Total context token count: ${tokenCount}`);
|
|
40
|
-
|
|
40
|
+
|
|
41
41
|
if (argvArg.tokensOnly) {
|
|
42
42
|
return; // Exit early if we only want token count
|
|
43
43
|
}
|
|
44
44
|
}
|
|
45
|
-
|
|
45
|
+
|
|
46
46
|
logger.log('info', `Generating new readme...`);
|
|
47
47
|
logger.log('info', `This may take some time...`);
|
|
48
48
|
await aidocInstance.buildReadme(paths.cwd);
|
|
@@ -54,67 +54,50 @@ export const run = async () => {
|
|
|
54
54
|
tsdocCli.addCommand('tokens').subscribe(async (argvArg) => {
|
|
55
55
|
const aidocInstance = new AiDoc();
|
|
56
56
|
await aidocInstance.start();
|
|
57
|
-
|
|
57
|
+
|
|
58
58
|
logger.log('info', `Calculating context token count...`);
|
|
59
|
-
|
|
60
|
-
// Determine context mode based on args
|
|
61
|
-
let contextMode: context.ContextMode = 'full';
|
|
62
|
-
if (argvArg.trim || argvArg.trimmed) {
|
|
63
|
-
contextMode = 'trimmed';
|
|
64
|
-
} else if (argvArg.summarize || argvArg.summarized) {
|
|
65
|
-
contextMode = 'summarized';
|
|
66
|
-
}
|
|
67
|
-
|
|
59
|
+
|
|
68
60
|
// Get task type if specified
|
|
69
61
|
let taskType: context.TaskType | undefined = undefined;
|
|
70
62
|
if (argvArg.task) {
|
|
71
63
|
if (['readme', 'commit', 'description'].includes(argvArg.task)) {
|
|
72
64
|
taskType = argvArg.task as context.TaskType;
|
|
73
65
|
} else {
|
|
74
|
-
logger.log('warn', `Unknown task type: ${argvArg.task}. Using default
|
|
66
|
+
logger.log('warn', `Unknown task type: ${argvArg.task}. Using default (readme).`);
|
|
67
|
+
taskType = 'readme';
|
|
75
68
|
}
|
|
69
|
+
} else {
|
|
70
|
+
// Default to readme if no task specified
|
|
71
|
+
taskType = 'readme';
|
|
76
72
|
}
|
|
77
|
-
|
|
78
|
-
// Use
|
|
73
|
+
|
|
74
|
+
// Use iterative context building
|
|
79
75
|
const taskFactory = new context.TaskContextFactory(paths.cwd);
|
|
80
76
|
await taskFactory.initialize();
|
|
81
|
-
|
|
82
|
-
let contextResult: context.
|
|
83
|
-
|
|
77
|
+
|
|
78
|
+
let contextResult: context.IIterativeContextResult;
|
|
79
|
+
|
|
84
80
|
if (argvArg.all) {
|
|
85
81
|
// Show stats for all task types
|
|
86
82
|
const stats = await taskFactory.getTokenStats();
|
|
87
|
-
|
|
83
|
+
|
|
88
84
|
logger.log('ok', 'Token statistics by task:');
|
|
89
85
|
for (const [task, data] of Object.entries(stats)) {
|
|
90
86
|
logger.log('info', `\n${task.toUpperCase()}:`);
|
|
91
87
|
logger.log('info', ` Tokens: ${data.tokenCount}`);
|
|
92
88
|
logger.log('info', ` Token savings: ${data.savings}`);
|
|
93
89
|
logger.log('info', ` Files: ${data.includedFiles} included, ${data.trimmedFiles} trimmed, ${data.excludedFiles} excluded`);
|
|
94
|
-
|
|
90
|
+
|
|
95
91
|
// Calculate percentage of model context
|
|
96
92
|
const o4MiniPercentage = (data.tokenCount / 200000 * 100).toFixed(2);
|
|
97
93
|
logger.log('info', ` Context usage: ${o4MiniPercentage}% of o4-mini (200K tokens)`);
|
|
98
94
|
}
|
|
99
|
-
|
|
95
|
+
|
|
100
96
|
return;
|
|
101
97
|
}
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
contextResult = await taskFactory.createContextForTask(taskType);
|
|
106
|
-
} else {
|
|
107
|
-
// Get generic context with specified mode
|
|
108
|
-
const enhancedContext = new context.EnhancedContext(paths.cwd);
|
|
109
|
-
await enhancedContext.initialize();
|
|
110
|
-
enhancedContext.setContextMode(contextMode);
|
|
111
|
-
|
|
112
|
-
if (argvArg.maxTokens) {
|
|
113
|
-
enhancedContext.setTokenBudget(parseInt(argvArg.maxTokens, 10));
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
contextResult = await enhancedContext.buildContext();
|
|
117
|
-
}
|
|
98
|
+
|
|
99
|
+
// Get context for specific task
|
|
100
|
+
contextResult = await taskFactory.createContextForTask(taskType);
|
|
118
101
|
|
|
119
102
|
// Display results
|
|
120
103
|
logger.log('ok', `Total context token count: ${contextResult.tokenCount}`);
|
|
@@ -9,7 +9,8 @@ import type {
|
|
|
9
9
|
ICacheConfig,
|
|
10
10
|
IAnalyzerConfig,
|
|
11
11
|
IPrioritizationWeights,
|
|
12
|
-
ITierConfig
|
|
12
|
+
ITierConfig,
|
|
13
|
+
IIterativeConfig
|
|
13
14
|
} from './types.js';
|
|
14
15
|
|
|
15
16
|
/**
|
|
@@ -85,7 +86,6 @@ export class ConfigManager {
|
|
|
85
86
|
directory: undefined // Will be set to .nogit/context-cache by ContextCache
|
|
86
87
|
},
|
|
87
88
|
analyzer: {
|
|
88
|
-
enabled: true,
|
|
89
89
|
useAIRefinement: false, // Disabled by default for now
|
|
90
90
|
aiModel: 'haiku'
|
|
91
91
|
},
|
|
@@ -99,6 +99,13 @@ export class ConfigManager {
|
|
|
99
99
|
essential: { minScore: 0.8, trimLevel: 'none' },
|
|
100
100
|
important: { minScore: 0.5, trimLevel: 'light' },
|
|
101
101
|
optional: { minScore: 0.2, trimLevel: 'aggressive' }
|
|
102
|
+
},
|
|
103
|
+
iterative: {
|
|
104
|
+
maxIterations: 5,
|
|
105
|
+
firstPassFileLimit: 10,
|
|
106
|
+
subsequentPassFileLimit: 5,
|
|
107
|
+
temperature: 0.3,
|
|
108
|
+
model: 'gpt-4-turbo-preview'
|
|
102
109
|
}
|
|
103
110
|
};
|
|
104
111
|
}
|
|
@@ -157,15 +164,15 @@ export class ConfigManager {
|
|
|
157
164
|
*/
|
|
158
165
|
private mergeConfigs(defaultConfig: IContextConfig, userConfig: Partial<IContextConfig>): IContextConfig {
|
|
159
166
|
const result: IContextConfig = { ...defaultConfig };
|
|
160
|
-
|
|
167
|
+
|
|
161
168
|
// Merge top-level properties
|
|
162
169
|
if (userConfig.maxTokens !== undefined) result.maxTokens = userConfig.maxTokens;
|
|
163
170
|
if (userConfig.defaultMode !== undefined) result.defaultMode = userConfig.defaultMode;
|
|
164
|
-
|
|
171
|
+
|
|
165
172
|
// Merge task-specific settings
|
|
166
173
|
if (userConfig.taskSpecificSettings) {
|
|
167
174
|
result.taskSpecificSettings = result.taskSpecificSettings || {};
|
|
168
|
-
|
|
175
|
+
|
|
169
176
|
// For each task type, merge settings
|
|
170
177
|
(['readme', 'commit', 'description'] as TaskType[]).forEach(taskType => {
|
|
171
178
|
if (userConfig.taskSpecificSettings?.[taskType]) {
|
|
@@ -176,7 +183,7 @@ export class ConfigManager {
|
|
|
176
183
|
}
|
|
177
184
|
});
|
|
178
185
|
}
|
|
179
|
-
|
|
186
|
+
|
|
180
187
|
// Merge trimming configuration
|
|
181
188
|
if (userConfig.trimming) {
|
|
182
189
|
result.trimming = {
|
|
@@ -217,6 +224,14 @@ export class ConfigManager {
|
|
|
217
224
|
};
|
|
218
225
|
}
|
|
219
226
|
|
|
227
|
+
// Merge iterative configuration
|
|
228
|
+
if (userConfig.iterative) {
|
|
229
|
+
result.iterative = {
|
|
230
|
+
...result.iterative,
|
|
231
|
+
...userConfig.iterative
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
|
|
220
235
|
return result;
|
|
221
236
|
}
|
|
222
237
|
|
|
@@ -306,7 +321,7 @@ export class ConfigManager {
|
|
|
306
321
|
* Get analyzer configuration
|
|
307
322
|
*/
|
|
308
323
|
public getAnalyzerConfig(): IAnalyzerConfig {
|
|
309
|
-
return this.config.analyzer || {
|
|
324
|
+
return this.config.analyzer || { useAIRefinement: false, aiModel: 'haiku' };
|
|
310
325
|
}
|
|
311
326
|
|
|
312
327
|
/**
|
|
@@ -332,6 +347,19 @@ export class ConfigManager {
|
|
|
332
347
|
};
|
|
333
348
|
}
|
|
334
349
|
|
|
350
|
+
/**
|
|
351
|
+
* Get iterative configuration
|
|
352
|
+
*/
|
|
353
|
+
public getIterativeConfig(): IIterativeConfig {
|
|
354
|
+
return this.config.iterative || {
|
|
355
|
+
maxIterations: 5,
|
|
356
|
+
firstPassFileLimit: 10,
|
|
357
|
+
subsequentPassFileLimit: 5,
|
|
358
|
+
temperature: 0.3,
|
|
359
|
+
model: 'gpt-4-turbo-preview'
|
|
360
|
+
};
|
|
361
|
+
}
|
|
362
|
+
|
|
335
363
|
/**
|
|
336
364
|
* Clear the config cache (force reload on next access)
|
|
337
365
|
*/
|
|
@@ -69,181 +69,7 @@ export class EnhancedContext {
|
|
|
69
69
|
public setTokenBudget(maxTokens: number): void {
|
|
70
70
|
this.tokenBudget = maxTokens;
|
|
71
71
|
}
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* Gather files from the project
|
|
75
|
-
* @param includePaths Optional paths to include
|
|
76
|
-
* @param excludePaths Optional paths to exclude
|
|
77
|
-
*/
|
|
78
|
-
public async gatherFiles(includePaths?: string[], excludePaths?: string[]): Promise<Record<string, plugins.smartfile.SmartFile | plugins.smartfile.SmartFile[]>> {
|
|
79
|
-
const smartfilePackageJSON = await plugins.smartfile.SmartFile.fromFilePath(
|
|
80
|
-
plugins.path.join(this.projectDir, 'package.json'),
|
|
81
|
-
this.projectDir,
|
|
82
|
-
);
|
|
83
|
-
|
|
84
|
-
const smartfilesReadme = await plugins.smartfile.SmartFile.fromFilePath(
|
|
85
|
-
plugins.path.join(this.projectDir, 'readme.md'),
|
|
86
|
-
this.projectDir,
|
|
87
|
-
);
|
|
88
72
|
|
|
89
|
-
const smartfilesReadmeHints = await plugins.smartfile.SmartFile.fromFilePath(
|
|
90
|
-
plugins.path.join(this.projectDir, 'readme.hints.md'),
|
|
91
|
-
this.projectDir,
|
|
92
|
-
);
|
|
93
|
-
|
|
94
|
-
const smartfilesNpmextraJSON = await plugins.smartfile.SmartFile.fromFilePath(
|
|
95
|
-
plugins.path.join(this.projectDir, 'npmextra.json'),
|
|
96
|
-
this.projectDir,
|
|
97
|
-
);
|
|
98
|
-
|
|
99
|
-
// Use provided include paths or default to all TypeScript files
|
|
100
|
-
const includeGlobs = includePaths?.map(path => `${path}/**/*.ts`) || ['ts*/**/*.ts'];
|
|
101
|
-
|
|
102
|
-
// Get TypeScript files
|
|
103
|
-
const smartfilesModPromises = includeGlobs.map(glob =>
|
|
104
|
-
plugins.smartfile.fs.fileTreeToObject(this.projectDir, glob)
|
|
105
|
-
);
|
|
106
|
-
|
|
107
|
-
const smartfilesModArrays = await Promise.all(smartfilesModPromises);
|
|
108
|
-
|
|
109
|
-
// Flatten the arrays
|
|
110
|
-
const smartfilesMod: plugins.smartfile.SmartFile[] = [];
|
|
111
|
-
smartfilesModArrays.forEach(array => {
|
|
112
|
-
smartfilesMod.push(...array);
|
|
113
|
-
});
|
|
114
|
-
|
|
115
|
-
// Get test files if not excluded
|
|
116
|
-
let smartfilesTest: plugins.smartfile.SmartFile[] = [];
|
|
117
|
-
if (!excludePaths?.includes('test/')) {
|
|
118
|
-
smartfilesTest = await plugins.smartfile.fs.fileTreeToObject(
|
|
119
|
-
this.projectDir,
|
|
120
|
-
'test/**/*.ts',
|
|
121
|
-
);
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
return {
|
|
125
|
-
smartfilePackageJSON,
|
|
126
|
-
smartfilesReadme,
|
|
127
|
-
smartfilesReadmeHints,
|
|
128
|
-
smartfilesNpmextraJSON,
|
|
129
|
-
smartfilesMod,
|
|
130
|
-
smartfilesTest,
|
|
131
|
-
};
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
/**
|
|
135
|
-
* Convert files to context string
|
|
136
|
-
* @param files The files to convert
|
|
137
|
-
* @param mode The context mode to use
|
|
138
|
-
*/
|
|
139
|
-
public async convertFilesToContext(
|
|
140
|
-
files: plugins.smartfile.SmartFile[],
|
|
141
|
-
mode: ContextMode = this.contextMode
|
|
142
|
-
): Promise<string> {
|
|
143
|
-
// Reset context result
|
|
144
|
-
this.contextResult = {
|
|
145
|
-
context: '',
|
|
146
|
-
tokenCount: 0,
|
|
147
|
-
includedFiles: [],
|
|
148
|
-
trimmedFiles: [],
|
|
149
|
-
excludedFiles: [],
|
|
150
|
-
tokenSavings: 0
|
|
151
|
-
};
|
|
152
|
-
|
|
153
|
-
let totalTokenCount = 0;
|
|
154
|
-
let totalOriginalTokens = 0;
|
|
155
|
-
|
|
156
|
-
// Convert SmartFile objects to IFileMetadata for analysis
|
|
157
|
-
const metadata: IFileMetadata[] = files.map(sf => ({
|
|
158
|
-
path: sf.path,
|
|
159
|
-
relativePath: sf.relative,
|
|
160
|
-
size: sf.contents.toString().length,
|
|
161
|
-
mtime: Date.now(), // SmartFile doesn't expose mtime, use current time
|
|
162
|
-
estimatedTokens: this.countTokens(sf.contents.toString()),
|
|
163
|
-
importanceScore: 0
|
|
164
|
-
}));
|
|
165
|
-
|
|
166
|
-
// Analyze files using ContextAnalyzer to get smart prioritization
|
|
167
|
-
// (Note: This requires task type which we'll pass from buildContext)
|
|
168
|
-
// For now, sort files by estimated tokens (smaller files first for better efficiency)
|
|
169
|
-
const sortedFiles = [...files].sort((a, b) => {
|
|
170
|
-
const aTokens = this.countTokens(a.contents.toString());
|
|
171
|
-
const bTokens = this.countTokens(b.contents.toString());
|
|
172
|
-
return aTokens - bTokens;
|
|
173
|
-
});
|
|
174
|
-
|
|
175
|
-
const processedFiles: string[] = [];
|
|
176
|
-
|
|
177
|
-
for (const smartfile of sortedFiles) {
|
|
178
|
-
// Calculate original token count
|
|
179
|
-
const originalContent = smartfile.contents.toString();
|
|
180
|
-
const originalTokenCount = this.countTokens(originalContent);
|
|
181
|
-
totalOriginalTokens += originalTokenCount;
|
|
182
|
-
|
|
183
|
-
// Apply trimming based on mode
|
|
184
|
-
let processedContent = originalContent;
|
|
185
|
-
|
|
186
|
-
if (mode !== 'full') {
|
|
187
|
-
processedContent = this.trimmer.trimFile(
|
|
188
|
-
smartfile.relative,
|
|
189
|
-
originalContent,
|
|
190
|
-
mode
|
|
191
|
-
);
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
// Calculate new token count
|
|
195
|
-
const processedTokenCount = this.countTokens(processedContent);
|
|
196
|
-
|
|
197
|
-
// Check if we have budget for this file
|
|
198
|
-
if (totalTokenCount + processedTokenCount > this.tokenBudget) {
|
|
199
|
-
// We don't have budget for this file
|
|
200
|
-
this.contextResult.excludedFiles.push({
|
|
201
|
-
path: smartfile.path,
|
|
202
|
-
contents: originalContent,
|
|
203
|
-
relativePath: smartfile.relative,
|
|
204
|
-
tokenCount: originalTokenCount
|
|
205
|
-
});
|
|
206
|
-
continue;
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
// Format the file for context
|
|
210
|
-
const formattedContent = `
|
|
211
|
-
====== START OF FILE ${smartfile.relative} ======
|
|
212
|
-
|
|
213
|
-
${processedContent}
|
|
214
|
-
|
|
215
|
-
====== END OF FILE ${smartfile.relative} ======
|
|
216
|
-
`;
|
|
217
|
-
|
|
218
|
-
processedFiles.push(formattedContent);
|
|
219
|
-
totalTokenCount += processedTokenCount;
|
|
220
|
-
|
|
221
|
-
// Track file in appropriate list
|
|
222
|
-
const fileInfo: IFileInfo = {
|
|
223
|
-
path: smartfile.path,
|
|
224
|
-
contents: processedContent,
|
|
225
|
-
relativePath: smartfile.relative,
|
|
226
|
-
tokenCount: processedTokenCount
|
|
227
|
-
};
|
|
228
|
-
|
|
229
|
-
if (mode === 'full' || processedContent === originalContent) {
|
|
230
|
-
this.contextResult.includedFiles.push(fileInfo);
|
|
231
|
-
} else {
|
|
232
|
-
this.contextResult.trimmedFiles.push(fileInfo);
|
|
233
|
-
this.contextResult.tokenSavings += (originalTokenCount - processedTokenCount);
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
// Join all processed files
|
|
238
|
-
const context = processedFiles.join('\n');
|
|
239
|
-
|
|
240
|
-
// Update context result
|
|
241
|
-
this.contextResult.context = context;
|
|
242
|
-
this.contextResult.tokenCount = totalTokenCount;
|
|
243
|
-
|
|
244
|
-
return context;
|
|
245
|
-
}
|
|
246
|
-
|
|
247
73
|
/**
|
|
248
74
|
* Convert files to context with smart analysis and prioritization
|
|
249
75
|
* @param metadata - File metadata to analyze
|
|
@@ -393,88 +219,45 @@ ${processedContent}
|
|
|
393
219
|
}
|
|
394
220
|
|
|
395
221
|
/**
|
|
396
|
-
* Build context for the project
|
|
397
|
-
* @param taskType
|
|
222
|
+
* Build context for the project using smart analysis
|
|
223
|
+
* @param taskType Task type for context-aware prioritization (defaults to 'description')
|
|
398
224
|
*/
|
|
399
225
|
public async buildContext(taskType?: TaskType): Promise<IContextResult> {
|
|
400
226
|
// Initialize if needed
|
|
401
227
|
if (this.tokenBudget === 0) {
|
|
402
228
|
await this.initialize();
|
|
403
229
|
}
|
|
404
|
-
|
|
405
|
-
// Get task-specific configuration if a task type is provided
|
|
406
|
-
if (taskType) {
|
|
407
|
-
const taskConfig = this.configManager.getTaskConfig(taskType);
|
|
408
|
-
if (taskConfig.mode) {
|
|
409
|
-
this.setContextMode(taskConfig.mode);
|
|
410
|
-
}
|
|
411
|
-
}
|
|
412
|
-
|
|
413
|
-
// Check if analyzer is enabled in config
|
|
414
|
-
const analyzerConfig = this.configManager.getAnalyzerConfig();
|
|
415
|
-
const useAnalyzer = analyzerConfig.enabled && taskType;
|
|
416
|
-
|
|
417
|
-
if (useAnalyzer) {
|
|
418
|
-
// Use new smart context building with lazy loading and analysis
|
|
419
|
-
const taskConfig = this.configManager.getTaskConfig(taskType!);
|
|
420
|
-
|
|
421
|
-
// Build globs for scanning
|
|
422
|
-
const includeGlobs = taskConfig?.includePaths?.map(p => `${p}/**/*.ts`) || [
|
|
423
|
-
'ts/**/*.ts',
|
|
424
|
-
'ts*/**/*.ts'
|
|
425
|
-
];
|
|
426
|
-
|
|
427
|
-
// Add config files
|
|
428
|
-
const configGlobs = [
|
|
429
|
-
'package.json',
|
|
430
|
-
'readme.md',
|
|
431
|
-
'readme.hints.md',
|
|
432
|
-
'npmextra.json'
|
|
433
|
-
];
|
|
434
|
-
|
|
435
|
-
// Scan files for metadata (fast, doesn't load contents)
|
|
436
|
-
const metadata = await this.lazyLoader.scanFiles([...configGlobs, ...includeGlobs]);
|
|
437
|
-
|
|
438
|
-
// Use analyzer to build context with smart prioritization
|
|
439
|
-
await this.convertFilesToContextWithAnalysis(metadata, taskType!, this.contextMode);
|
|
440
|
-
} else {
|
|
441
|
-
// Fall back to old method for backward compatibility
|
|
442
|
-
const taskConfig = taskType ? this.configManager.getTaskConfig(taskType) : undefined;
|
|
443
|
-
const files = await this.gatherFiles(
|
|
444
|
-
taskConfig?.includePaths,
|
|
445
|
-
taskConfig?.excludePaths
|
|
446
|
-
);
|
|
447
|
-
|
|
448
|
-
// Convert files to context
|
|
449
|
-
// Create an array of all files to process
|
|
450
|
-
const allFiles: plugins.smartfile.SmartFile[] = [];
|
|
451
|
-
|
|
452
|
-
// Add individual files
|
|
453
|
-
if (files.smartfilePackageJSON) allFiles.push(files.smartfilePackageJSON as plugins.smartfile.SmartFile);
|
|
454
|
-
if (files.smartfilesReadme) allFiles.push(files.smartfilesReadme as plugins.smartfile.SmartFile);
|
|
455
|
-
if (files.smartfilesReadmeHints) allFiles.push(files.smartfilesReadmeHints as plugins.smartfile.SmartFile);
|
|
456
|
-
if (files.smartfilesNpmextraJSON) allFiles.push(files.smartfilesNpmextraJSON as plugins.smartfile.SmartFile);
|
|
457
|
-
|
|
458
|
-
// Add arrays of files
|
|
459
|
-
if (files.smartfilesMod) {
|
|
460
|
-
if (Array.isArray(files.smartfilesMod)) {
|
|
461
|
-
allFiles.push(...files.smartfilesMod);
|
|
462
|
-
} else {
|
|
463
|
-
allFiles.push(files.smartfilesMod);
|
|
464
|
-
}
|
|
465
|
-
}
|
|
466
230
|
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
} else {
|
|
471
|
-
allFiles.push(files.smartfilesTest);
|
|
472
|
-
}
|
|
473
|
-
}
|
|
231
|
+
// Smart context building always requires a task type for optimal prioritization
|
|
232
|
+
// Default to 'description' if not provided
|
|
233
|
+
const effectiveTaskType = taskType || 'description';
|
|
474
234
|
|
|
475
|
-
|
|
235
|
+
// Get task-specific configuration
|
|
236
|
+
const taskConfig = this.configManager.getTaskConfig(effectiveTaskType);
|
|
237
|
+
if (taskConfig.mode) {
|
|
238
|
+
this.setContextMode(taskConfig.mode);
|
|
476
239
|
}
|
|
477
240
|
|
|
241
|
+
// Build globs for scanning
|
|
242
|
+
const includeGlobs = taskConfig?.includePaths?.map(p => `${p}/**/*.ts`) || [
|
|
243
|
+
'ts/**/*.ts',
|
|
244
|
+
'ts*/**/*.ts'
|
|
245
|
+
];
|
|
246
|
+
|
|
247
|
+
// Add config files
|
|
248
|
+
const configGlobs = [
|
|
249
|
+
'package.json',
|
|
250
|
+
'readme.md',
|
|
251
|
+
'readme.hints.md',
|
|
252
|
+
'npmextra.json'
|
|
253
|
+
];
|
|
254
|
+
|
|
255
|
+
// Scan files for metadata (fast, doesn't load contents)
|
|
256
|
+
const metadata = await this.lazyLoader.scanFiles([...configGlobs, ...includeGlobs]);
|
|
257
|
+
|
|
258
|
+
// Use smart analyzer to build context with intelligent prioritization
|
|
259
|
+
await this.convertFilesToContextWithAnalysis(metadata, effectiveTaskType, this.contextMode);
|
|
260
|
+
|
|
478
261
|
return this.contextResult;
|
|
479
262
|
}
|
|
480
263
|
|
package/ts/context/index.ts
CHANGED
|
@@ -22,7 +22,9 @@ import type {
|
|
|
22
22
|
ICacheEntry,
|
|
23
23
|
IFileDependencies,
|
|
24
24
|
IFileAnalysis,
|
|
25
|
-
IAnalysisResult
|
|
25
|
+
IAnalysisResult,
|
|
26
|
+
IIterativeConfig,
|
|
27
|
+
IIterativeContextResult
|
|
26
28
|
} from './types.js';
|
|
27
29
|
|
|
28
30
|
export {
|
|
@@ -54,5 +56,7 @@ export type {
|
|
|
54
56
|
ICacheEntry,
|
|
55
57
|
IFileDependencies,
|
|
56
58
|
IFileAnalysis,
|
|
57
|
-
IAnalysisResult
|
|
59
|
+
IAnalysisResult,
|
|
60
|
+
IIterativeConfig,
|
|
61
|
+
IIterativeContextResult
|
|
58
62
|
};
|