@git.zone/tsdoc 1.5.1 → 1.6.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/aidocs_classes/commit.js +2 -2
- package/dist_ts/context/config-manager.d.ts +22 -1
- package/dist_ts/context/config-manager.js +114 -4
- package/dist_ts/context/context-analyzer.d.ts +73 -0
- package/dist_ts/context/context-analyzer.js +311 -0
- package/dist_ts/context/context-cache.d.ts +73 -0
- package/dist_ts/context/context-cache.js +238 -0
- package/dist_ts/context/context-trimmer.d.ts +8 -0
- package/dist_ts/context/context-trimmer.js +60 -1
- package/dist_ts/context/enhanced-context.d.ts +12 -1
- package/dist_ts/context/enhanced-context.js +201 -33
- package/dist_ts/context/index.d.ts +6 -3
- package/dist_ts/context/index.js +5 -2
- package/dist_ts/context/lazy-file-loader.d.ts +60 -0
- package/dist_ts/context/lazy-file-loader.js +164 -0
- package/dist_ts/context/types.d.ts +143 -0
- package/package.json +12 -13
- package/readme.md +441 -587
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/aidocs_classes/commit.ts +2 -2
- package/ts/context/config-manager.ts +147 -15
- package/ts/context/context-analyzer.ts +391 -0
- package/ts/context/context-cache.ts +285 -0
- package/ts/context/context-trimmer.ts +64 -0
- package/ts/context/enhanced-context.ts +246 -40
- package/ts/context/index.ts +31 -5
- package/ts/context/lazy-file-loader.ts +191 -0
- package/ts/context/types.ts +153 -0
package/ts/context/index.ts
CHANGED
|
@@ -2,14 +2,27 @@ import { EnhancedContext } from './enhanced-context.js';
|
|
|
2
2
|
import { TaskContextFactory } from './task-context-factory.js';
|
|
3
3
|
import { ConfigManager } from './config-manager.js';
|
|
4
4
|
import { ContextTrimmer } from './context-trimmer.js';
|
|
5
|
-
import
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
import { LazyFileLoader } from './lazy-file-loader.js';
|
|
6
|
+
import { ContextCache } from './context-cache.js';
|
|
7
|
+
import { ContextAnalyzer } from './context-analyzer.js';
|
|
8
|
+
import type {
|
|
9
|
+
ContextMode,
|
|
10
|
+
IContextConfig,
|
|
8
11
|
IContextResult,
|
|
9
12
|
IFileInfo,
|
|
10
13
|
ITrimConfig,
|
|
11
14
|
ITaskConfig,
|
|
12
|
-
TaskType
|
|
15
|
+
TaskType,
|
|
16
|
+
ICacheConfig,
|
|
17
|
+
IAnalyzerConfig,
|
|
18
|
+
IPrioritizationWeights,
|
|
19
|
+
ITierConfig,
|
|
20
|
+
ITierSettings,
|
|
21
|
+
IFileMetadata,
|
|
22
|
+
ICacheEntry,
|
|
23
|
+
IFileDependencies,
|
|
24
|
+
IFileAnalysis,
|
|
25
|
+
IAnalysisResult
|
|
13
26
|
} from './types.js';
|
|
14
27
|
|
|
15
28
|
export {
|
|
@@ -18,6 +31,9 @@ export {
|
|
|
18
31
|
TaskContextFactory,
|
|
19
32
|
ConfigManager,
|
|
20
33
|
ContextTrimmer,
|
|
34
|
+
LazyFileLoader,
|
|
35
|
+
ContextCache,
|
|
36
|
+
ContextAnalyzer,
|
|
21
37
|
};
|
|
22
38
|
|
|
23
39
|
// Types
|
|
@@ -28,5 +44,15 @@ export type {
|
|
|
28
44
|
IFileInfo,
|
|
29
45
|
ITrimConfig,
|
|
30
46
|
ITaskConfig,
|
|
31
|
-
TaskType
|
|
47
|
+
TaskType,
|
|
48
|
+
ICacheConfig,
|
|
49
|
+
IAnalyzerConfig,
|
|
50
|
+
IPrioritizationWeights,
|
|
51
|
+
ITierConfig,
|
|
52
|
+
ITierSettings,
|
|
53
|
+
IFileMetadata,
|
|
54
|
+
ICacheEntry,
|
|
55
|
+
IFileDependencies,
|
|
56
|
+
IFileAnalysis,
|
|
57
|
+
IAnalysisResult
|
|
32
58
|
};
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import * as plugins from '../plugins.js';
|
|
2
|
+
import * as fs from 'fs';
|
|
3
|
+
import type { IFileMetadata, IFileInfo } from './types.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* LazyFileLoader handles efficient file loading by:
|
|
7
|
+
* - Scanning files for metadata without loading contents
|
|
8
|
+
* - Providing fast file size and token estimates
|
|
9
|
+
* - Loading contents only when requested
|
|
10
|
+
* - Parallel loading of selected files
|
|
11
|
+
*/
|
|
12
|
+
export class LazyFileLoader {
|
|
13
|
+
private projectRoot: string;
|
|
14
|
+
private metadataCache: Map<string, IFileMetadata> = new Map();
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Creates a new LazyFileLoader
|
|
18
|
+
* @param projectRoot - Root directory of the project
|
|
19
|
+
*/
|
|
20
|
+
constructor(projectRoot: string) {
|
|
21
|
+
this.projectRoot = projectRoot;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Scans files in given globs and creates metadata without loading contents
|
|
26
|
+
* @param globs - File patterns to scan (e.g., ['ts/**\/*.ts', 'test/**\/*.ts'])
|
|
27
|
+
* @returns Array of file metadata
|
|
28
|
+
*/
|
|
29
|
+
public async scanFiles(globs: string[]): Promise<IFileMetadata[]> {
|
|
30
|
+
const metadata: IFileMetadata[] = [];
|
|
31
|
+
|
|
32
|
+
for (const globPattern of globs) {
|
|
33
|
+
try {
|
|
34
|
+
const smartFiles = await plugins.smartfile.fs.fileTreeToObject(this.projectRoot, globPattern);
|
|
35
|
+
const fileArray = Array.isArray(smartFiles) ? smartFiles : [smartFiles];
|
|
36
|
+
|
|
37
|
+
for (const smartFile of fileArray) {
|
|
38
|
+
try {
|
|
39
|
+
const meta = await this.getMetadata(smartFile.path);
|
|
40
|
+
metadata.push(meta);
|
|
41
|
+
} catch (error) {
|
|
42
|
+
// Skip files that can't be read
|
|
43
|
+
console.warn(`Failed to get metadata for ${smartFile.path}:`, error.message);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
} catch (error) {
|
|
47
|
+
// Skip patterns that don't match any files
|
|
48
|
+
console.warn(`No files found for pattern ${globPattern}`);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return metadata;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Gets metadata for a single file without loading contents
|
|
57
|
+
* @param filePath - Absolute path to the file
|
|
58
|
+
* @returns File metadata
|
|
59
|
+
*/
|
|
60
|
+
public async getMetadata(filePath: string): Promise<IFileMetadata> {
|
|
61
|
+
// Check cache first
|
|
62
|
+
if (this.metadataCache.has(filePath)) {
|
|
63
|
+
const cached = this.metadataCache.get(filePath)!;
|
|
64
|
+
const currentStats = await fs.promises.stat(filePath);
|
|
65
|
+
|
|
66
|
+
// Return cached if file hasn't changed
|
|
67
|
+
if (cached.mtime === Math.floor(currentStats.mtimeMs)) {
|
|
68
|
+
return cached;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Get file stats
|
|
73
|
+
const stats = await fs.promises.stat(filePath);
|
|
74
|
+
const relativePath = plugins.path.relative(this.projectRoot, filePath);
|
|
75
|
+
|
|
76
|
+
// Estimate tokens: rough estimate of ~4 characters per token
|
|
77
|
+
// This is faster than reading and tokenizing the entire file
|
|
78
|
+
const estimatedTokens = Math.ceil(stats.size / 4);
|
|
79
|
+
|
|
80
|
+
const metadata: IFileMetadata = {
|
|
81
|
+
path: filePath,
|
|
82
|
+
relativePath,
|
|
83
|
+
size: stats.size,
|
|
84
|
+
mtime: Math.floor(stats.mtimeMs),
|
|
85
|
+
estimatedTokens,
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
// Cache the metadata
|
|
89
|
+
this.metadataCache.set(filePath, metadata);
|
|
90
|
+
|
|
91
|
+
return metadata;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Loads file contents for selected files in parallel
|
|
96
|
+
* @param metadata - Array of file metadata to load
|
|
97
|
+
* @param tokenizer - Function to calculate accurate token count
|
|
98
|
+
* @returns Array of complete file info with contents
|
|
99
|
+
*/
|
|
100
|
+
public async loadFiles(
|
|
101
|
+
metadata: IFileMetadata[],
|
|
102
|
+
tokenizer: (content: string) => number
|
|
103
|
+
): Promise<IFileInfo[]> {
|
|
104
|
+
// Load files in parallel
|
|
105
|
+
const loadPromises = metadata.map(async (meta) => {
|
|
106
|
+
try {
|
|
107
|
+
const contents = await plugins.smartfile.fs.toStringSync(meta.path);
|
|
108
|
+
const tokenCount = tokenizer(contents);
|
|
109
|
+
|
|
110
|
+
const fileInfo: IFileInfo = {
|
|
111
|
+
path: meta.path,
|
|
112
|
+
relativePath: meta.relativePath,
|
|
113
|
+
contents,
|
|
114
|
+
tokenCount,
|
|
115
|
+
importanceScore: meta.importanceScore,
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
return fileInfo;
|
|
119
|
+
} catch (error) {
|
|
120
|
+
console.warn(`Failed to load file ${meta.path}:`, error.message);
|
|
121
|
+
return null;
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
// Wait for all loads to complete and filter out failures
|
|
126
|
+
const results = await Promise.all(loadPromises);
|
|
127
|
+
return results.filter((r): r is IFileInfo => r !== null);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Loads a single file with contents
|
|
132
|
+
* @param filePath - Absolute path to the file
|
|
133
|
+
* @param tokenizer - Function to calculate accurate token count
|
|
134
|
+
* @returns Complete file info with contents
|
|
135
|
+
*/
|
|
136
|
+
public async loadFile(
|
|
137
|
+
filePath: string,
|
|
138
|
+
tokenizer: (content: string) => number
|
|
139
|
+
): Promise<IFileInfo> {
|
|
140
|
+
const meta = await this.getMetadata(filePath);
|
|
141
|
+
const contents = await plugins.smartfile.fs.toStringSync(filePath);
|
|
142
|
+
const tokenCount = tokenizer(contents);
|
|
143
|
+
const relativePath = plugins.path.relative(this.projectRoot, filePath);
|
|
144
|
+
|
|
145
|
+
return {
|
|
146
|
+
path: filePath,
|
|
147
|
+
relativePath,
|
|
148
|
+
contents,
|
|
149
|
+
tokenCount,
|
|
150
|
+
importanceScore: meta.importanceScore,
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Updates importance scores for metadata entries
|
|
156
|
+
* @param scores - Map of file paths to importance scores
|
|
157
|
+
*/
|
|
158
|
+
public updateImportanceScores(scores: Map<string, number>): void {
|
|
159
|
+
for (const [path, score] of scores) {
|
|
160
|
+
const meta = this.metadataCache.get(path);
|
|
161
|
+
if (meta) {
|
|
162
|
+
meta.importanceScore = score;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Clears the metadata cache
|
|
169
|
+
*/
|
|
170
|
+
public clearCache(): void {
|
|
171
|
+
this.metadataCache.clear();
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Gets total estimated tokens for all cached metadata
|
|
176
|
+
*/
|
|
177
|
+
public getTotalEstimatedTokens(): number {
|
|
178
|
+
let total = 0;
|
|
179
|
+
for (const meta of this.metadataCache.values()) {
|
|
180
|
+
total += meta.estimatedTokens;
|
|
181
|
+
}
|
|
182
|
+
return total;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Gets cached metadata entries
|
|
187
|
+
*/
|
|
188
|
+
public getCachedMetadata(): IFileMetadata[] {
|
|
189
|
+
return Array.from(this.metadataCache.values());
|
|
190
|
+
}
|
|
191
|
+
}
|
package/ts/context/types.ts
CHANGED
|
@@ -58,6 +58,73 @@ export interface IContextConfig {
|
|
|
58
58
|
};
|
|
59
59
|
/** Trimming configuration */
|
|
60
60
|
trimming?: ITrimConfig;
|
|
61
|
+
/** Cache configuration */
|
|
62
|
+
cache?: ICacheConfig;
|
|
63
|
+
/** Analyzer configuration */
|
|
64
|
+
analyzer?: IAnalyzerConfig;
|
|
65
|
+
/** Prioritization weights */
|
|
66
|
+
prioritization?: IPrioritizationWeights;
|
|
67
|
+
/** Tier configuration for adaptive trimming */
|
|
68
|
+
tiers?: ITierConfig;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Cache configuration
|
|
73
|
+
*/
|
|
74
|
+
export interface ICacheConfig {
|
|
75
|
+
/** Whether caching is enabled */
|
|
76
|
+
enabled?: boolean;
|
|
77
|
+
/** Time-to-live in seconds */
|
|
78
|
+
ttl?: number;
|
|
79
|
+
/** Maximum cache size in MB */
|
|
80
|
+
maxSize?: number;
|
|
81
|
+
/** Cache directory path */
|
|
82
|
+
directory?: string;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Analyzer configuration
|
|
87
|
+
*/
|
|
88
|
+
export interface IAnalyzerConfig {
|
|
89
|
+
/** Whether analyzer is enabled */
|
|
90
|
+
enabled?: boolean;
|
|
91
|
+
/** Whether to use AI refinement for selection */
|
|
92
|
+
useAIRefinement?: boolean;
|
|
93
|
+
/** AI model to use for refinement */
|
|
94
|
+
aiModel?: string;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Weights for file prioritization
|
|
99
|
+
*/
|
|
100
|
+
export interface IPrioritizationWeights {
|
|
101
|
+
/** Weight for dependency centrality */
|
|
102
|
+
dependencyWeight?: number;
|
|
103
|
+
/** Weight for task relevance */
|
|
104
|
+
relevanceWeight?: number;
|
|
105
|
+
/** Weight for token efficiency */
|
|
106
|
+
efficiencyWeight?: number;
|
|
107
|
+
/** Weight for file recency */
|
|
108
|
+
recencyWeight?: number;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Tier configuration for adaptive trimming
|
|
113
|
+
*/
|
|
114
|
+
export interface ITierConfig {
|
|
115
|
+
essential?: ITierSettings;
|
|
116
|
+
important?: ITierSettings;
|
|
117
|
+
optional?: ITierSettings;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Settings for a single tier
|
|
122
|
+
*/
|
|
123
|
+
export interface ITierSettings {
|
|
124
|
+
/** Minimum score to qualify for this tier */
|
|
125
|
+
minScore: number;
|
|
126
|
+
/** Trimming level to apply */
|
|
127
|
+
trimLevel: 'none' | 'light' | 'aggressive';
|
|
61
128
|
}
|
|
62
129
|
|
|
63
130
|
/**
|
|
@@ -92,4 +159,90 @@ export interface IContextResult {
|
|
|
92
159
|
excludedFiles: IFileInfo[];
|
|
93
160
|
/** Token savings from trimming */
|
|
94
161
|
tokenSavings: number;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* File metadata without contents (for lazy loading)
|
|
166
|
+
*/
|
|
167
|
+
export interface IFileMetadata {
|
|
168
|
+
/** The file path */
|
|
169
|
+
path: string;
|
|
170
|
+
/** The file's relative path from the project root */
|
|
171
|
+
relativePath: string;
|
|
172
|
+
/** File size in bytes */
|
|
173
|
+
size: number;
|
|
174
|
+
/** Last modified time (Unix timestamp) */
|
|
175
|
+
mtime: number;
|
|
176
|
+
/** Estimated token count (without loading full contents) */
|
|
177
|
+
estimatedTokens: number;
|
|
178
|
+
/** The file's importance score */
|
|
179
|
+
importanceScore?: number;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Cache entry for a file
|
|
184
|
+
*/
|
|
185
|
+
export interface ICacheEntry {
|
|
186
|
+
/** File path */
|
|
187
|
+
path: string;
|
|
188
|
+
/** File contents */
|
|
189
|
+
contents: string;
|
|
190
|
+
/** Token count */
|
|
191
|
+
tokenCount: number;
|
|
192
|
+
/** Last modified time when cached */
|
|
193
|
+
mtime: number;
|
|
194
|
+
/** When this cache entry was created */
|
|
195
|
+
cachedAt: number;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Dependency information for a file
|
|
200
|
+
*/
|
|
201
|
+
export interface IFileDependencies {
|
|
202
|
+
/** File path */
|
|
203
|
+
path: string;
|
|
204
|
+
/** Files this file imports */
|
|
205
|
+
imports: string[];
|
|
206
|
+
/** Files that import this file */
|
|
207
|
+
importedBy: string[];
|
|
208
|
+
/** Centrality score (0-1) - how central this file is in the dependency graph */
|
|
209
|
+
centrality: number;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Analysis result for a file
|
|
214
|
+
*/
|
|
215
|
+
export interface IFileAnalysis {
|
|
216
|
+
/** File path */
|
|
217
|
+
path: string;
|
|
218
|
+
/** Task relevance score (0-1) */
|
|
219
|
+
relevanceScore: number;
|
|
220
|
+
/** Dependency centrality score (0-1) */
|
|
221
|
+
centralityScore: number;
|
|
222
|
+
/** Token efficiency score (0-1) */
|
|
223
|
+
efficiencyScore: number;
|
|
224
|
+
/** Recency score (0-1) */
|
|
225
|
+
recencyScore: number;
|
|
226
|
+
/** Combined importance score (0-1) */
|
|
227
|
+
importanceScore: number;
|
|
228
|
+
/** Assigned tier */
|
|
229
|
+
tier: 'essential' | 'important' | 'optional' | 'excluded';
|
|
230
|
+
/** Reason for the score */
|
|
231
|
+
reason?: string;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* Result of context analysis
|
|
236
|
+
*/
|
|
237
|
+
export interface IAnalysisResult {
|
|
238
|
+
/** Task type being analyzed */
|
|
239
|
+
taskType: TaskType;
|
|
240
|
+
/** Analyzed files with scores */
|
|
241
|
+
files: IFileAnalysis[];
|
|
242
|
+
/** Dependency graph */
|
|
243
|
+
dependencyGraph: Map<string, IFileDependencies>;
|
|
244
|
+
/** Total files analyzed */
|
|
245
|
+
totalFiles: number;
|
|
246
|
+
/** Analysis duration in ms */
|
|
247
|
+
analysisDuration: number;
|
|
95
248
|
}
|