@git.zone/tsdoc 1.4.5 → 1.5.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.
Files changed (41) hide show
  1. package/dist_ts/00_commitinfo_data.js +3 -3
  2. package/dist_ts/aidocs_classes/commit.js +16 -10
  3. package/dist_ts/aidocs_classes/description.js +14 -6
  4. package/dist_ts/aidocs_classes/projectcontext.d.ts +22 -0
  5. package/dist_ts/aidocs_classes/projectcontext.js +41 -1
  6. package/dist_ts/aidocs_classes/readme.js +10 -4
  7. package/dist_ts/classes.aidoc.d.ts +22 -0
  8. package/dist_ts/classes.aidoc.js +31 -1
  9. package/dist_ts/cli.js +110 -1
  10. package/dist_ts/context/config-manager.d.ts +58 -0
  11. package/dist_ts/context/config-manager.js +183 -0
  12. package/dist_ts/context/context-trimmer.d.ts +52 -0
  13. package/dist_ts/context/context-trimmer.js +199 -0
  14. package/dist_ts/context/enhanced-context.d.ts +75 -0
  15. package/dist_ts/context/enhanced-context.js +272 -0
  16. package/dist_ts/context/index.d.ts +7 -0
  17. package/dist_ts/context/index.js +8 -0
  18. package/dist_ts/context/task-context-factory.d.ts +46 -0
  19. package/dist_ts/context/task-context-factory.js +109 -0
  20. package/dist_ts/context/types.d.ts +89 -0
  21. package/dist_ts/context/types.js +2 -0
  22. package/dist_ts/plugins.d.ts +2 -1
  23. package/dist_ts/plugins.js +3 -2
  24. package/npmextra.json +10 -9
  25. package/package.json +12 -10
  26. package/readme.md +588 -174
  27. package/readme.plan.md +314 -0
  28. package/ts/00_commitinfo_data.ts +2 -2
  29. package/ts/aidocs_classes/commit.ts +21 -9
  30. package/ts/aidocs_classes/description.ts +16 -5
  31. package/ts/aidocs_classes/projectcontext.ts +43 -0
  32. package/ts/aidocs_classes/readme.ts +11 -3
  33. package/ts/classes.aidoc.ts +33 -0
  34. package/ts/cli.ts +128 -0
  35. package/ts/context/config-manager.ts +209 -0
  36. package/ts/context/context-trimmer.ts +246 -0
  37. package/ts/context/enhanced-context.ts +343 -0
  38. package/ts/context/index.ts +32 -0
  39. package/ts/context/task-context-factory.ts +138 -0
  40. package/ts/context/types.ts +95 -0
  41. package/ts/plugins.ts +2 -1
@@ -0,0 +1,209 @@
1
+ import * as plugins from '../plugins.js';
2
+ import type { IContextConfig, ITrimConfig, ITaskConfig, TaskType, ContextMode } from './types.js';
3
+
4
+ /**
5
+ * Manages configuration for context building
6
+ */
7
+ export class ConfigManager {
8
+ private static instance: ConfigManager;
9
+ private config: IContextConfig;
10
+ private projectDir: string = '';
11
+
12
+ /**
13
+ * Get the singleton instance of ConfigManager
14
+ */
15
+ public static getInstance(): ConfigManager {
16
+ if (!ConfigManager.instance) {
17
+ ConfigManager.instance = new ConfigManager();
18
+ }
19
+ return ConfigManager.instance;
20
+ }
21
+
22
+ /**
23
+ * Private constructor for singleton pattern
24
+ */
25
+ private constructor() {
26
+ this.config = this.getDefaultConfig();
27
+ }
28
+
29
+ /**
30
+ * Initialize the config manager with a project directory
31
+ * @param projectDir The project directory
32
+ */
33
+ public async initialize(projectDir: string): Promise<void> {
34
+ this.projectDir = projectDir;
35
+ await this.loadConfig();
36
+ }
37
+
38
+ /**
39
+ * Get the default configuration
40
+ */
41
+ private getDefaultConfig(): IContextConfig {
42
+ return {
43
+ maxTokens: 190000, // Default for o4-mini with some buffer
44
+ defaultMode: 'trimmed',
45
+ taskSpecificSettings: {
46
+ readme: {
47
+ mode: 'trimmed',
48
+ includePaths: ['ts/', 'src/'],
49
+ excludePaths: ['test/', 'node_modules/']
50
+ },
51
+ commit: {
52
+ mode: 'trimmed',
53
+ focusOnChangedFiles: true
54
+ },
55
+ description: {
56
+ mode: 'trimmed',
57
+ includePackageInfo: true
58
+ }
59
+ },
60
+ trimming: {
61
+ removeImplementations: true,
62
+ preserveInterfaces: true,
63
+ preserveTypeDefs: true,
64
+ preserveJSDoc: true,
65
+ maxFunctionLines: 5,
66
+ removeComments: true,
67
+ removeBlankLines: true
68
+ }
69
+ };
70
+ }
71
+
72
+ /**
73
+ * Load configuration from npmextra.json
74
+ */
75
+ private async loadConfig(): Promise<void> {
76
+ try {
77
+ if (!this.projectDir) {
78
+ return;
79
+ }
80
+
81
+ // Create KeyValueStore for this project
82
+ // We'll just use smartfile directly instead of KeyValueStore
83
+
84
+ // Read the npmextra.json file
85
+ const npmextraJsonFile = await plugins.smartfile.SmartFile.fromFilePath(
86
+ plugins.path.join(this.projectDir, 'npmextra.json')
87
+ );
88
+ const npmextraContent = JSON.parse(npmextraJsonFile.contents.toString());
89
+
90
+ // Check for tsdoc context configuration
91
+ if (npmextraContent?.tsdoc?.context) {
92
+ // Merge with default config
93
+ this.config = this.mergeConfigs(this.config, npmextraContent.tsdoc.context);
94
+ }
95
+ } catch (error) {
96
+ console.error('Error loading context configuration:', error);
97
+ }
98
+ }
99
+
100
+ /**
101
+ * Merge configurations, with userConfig taking precedence
102
+ * @param defaultConfig The default configuration
103
+ * @param userConfig The user configuration
104
+ */
105
+ private mergeConfigs(defaultConfig: IContextConfig, userConfig: Partial<IContextConfig>): IContextConfig {
106
+ const result: IContextConfig = { ...defaultConfig };
107
+
108
+ // Merge top-level properties
109
+ if (userConfig.maxTokens !== undefined) result.maxTokens = userConfig.maxTokens;
110
+ if (userConfig.defaultMode !== undefined) result.defaultMode = userConfig.defaultMode;
111
+
112
+ // Merge task-specific settings
113
+ if (userConfig.taskSpecificSettings) {
114
+ result.taskSpecificSettings = result.taskSpecificSettings || {};
115
+
116
+ // For each task type, merge settings
117
+ (['readme', 'commit', 'description'] as TaskType[]).forEach(taskType => {
118
+ if (userConfig.taskSpecificSettings?.[taskType]) {
119
+ result.taskSpecificSettings![taskType] = {
120
+ ...result.taskSpecificSettings![taskType],
121
+ ...userConfig.taskSpecificSettings[taskType]
122
+ };
123
+ }
124
+ });
125
+ }
126
+
127
+ // Merge trimming configuration
128
+ if (userConfig.trimming) {
129
+ result.trimming = {
130
+ ...result.trimming,
131
+ ...userConfig.trimming
132
+ };
133
+ }
134
+
135
+ return result;
136
+ }
137
+
138
+ /**
139
+ * Get the complete configuration
140
+ */
141
+ public getConfig(): IContextConfig {
142
+ return this.config;
143
+ }
144
+
145
+ /**
146
+ * Get the trimming configuration
147
+ */
148
+ public getTrimConfig(): ITrimConfig {
149
+ return this.config.trimming || {};
150
+ }
151
+
152
+ /**
153
+ * Get configuration for a specific task
154
+ * @param taskType The type of task
155
+ */
156
+ public getTaskConfig(taskType: TaskType): ITaskConfig {
157
+ // Get task-specific config or empty object
158
+ const taskConfig = this.config.taskSpecificSettings?.[taskType] || {};
159
+
160
+ // If mode is not specified, use default mode
161
+ if (!taskConfig.mode) {
162
+ taskConfig.mode = this.config.defaultMode;
163
+ }
164
+
165
+ return taskConfig;
166
+ }
167
+
168
+ /**
169
+ * Get the maximum tokens allowed for context
170
+ */
171
+ public getMaxTokens(): number {
172
+ return this.config.maxTokens || 190000;
173
+ }
174
+
175
+ /**
176
+ * Update the configuration
177
+ * @param config The new configuration
178
+ */
179
+ public async updateConfig(config: Partial<IContextConfig>): Promise<void> {
180
+ // Merge with existing config
181
+ this.config = this.mergeConfigs(this.config, config);
182
+
183
+ try {
184
+ if (!this.projectDir) {
185
+ return;
186
+ }
187
+
188
+ // Read the existing npmextra.json file
189
+ const npmextraJsonPath = plugins.path.join(this.projectDir, 'npmextra.json');
190
+ let npmextraContent = {};
191
+
192
+ if (await plugins.smartfile.fs.fileExists(npmextraJsonPath)) {
193
+ const npmextraJsonFile = await plugins.smartfile.SmartFile.fromFilePath(npmextraJsonPath);
194
+ npmextraContent = JSON.parse(npmextraJsonFile.contents.toString()) || {};
195
+ }
196
+
197
+ // Update the tsdoc context configuration
198
+ const typedContent = npmextraContent as any;
199
+ if (!typedContent.tsdoc) typedContent.tsdoc = {};
200
+ typedContent.tsdoc.context = this.config;
201
+
202
+ // Write back to npmextra.json
203
+ const updatedContent = JSON.stringify(npmextraContent, null, 2);
204
+ await plugins.smartfile.memory.toFs(updatedContent, npmextraJsonPath);
205
+ } catch (error) {
206
+ console.error('Error updating context configuration:', error);
207
+ }
208
+ }
209
+ }
@@ -0,0 +1,246 @@
1
+ import * as plugins from '../plugins.js';
2
+ import type { ITrimConfig, ContextMode } from './types.js';
3
+
4
+ /**
5
+ * Class responsible for trimming file contents to reduce token usage
6
+ * while preserving important information for context
7
+ */
8
+ export class ContextTrimmer {
9
+ private config: ITrimConfig;
10
+
11
+ /**
12
+ * Create a new ContextTrimmer with the given configuration
13
+ * @param config The trimming configuration
14
+ */
15
+ constructor(config?: ITrimConfig) {
16
+ this.config = {
17
+ removeImplementations: true,
18
+ preserveInterfaces: true,
19
+ preserveTypeDefs: true,
20
+ preserveJSDoc: true,
21
+ maxFunctionLines: 5,
22
+ removeComments: true,
23
+ removeBlankLines: true,
24
+ ...config
25
+ };
26
+ }
27
+
28
+ /**
29
+ * Trim a file's contents based on the configuration
30
+ * @param filePath The path to the file
31
+ * @param content The file's contents
32
+ * @param mode The context mode to use
33
+ * @returns The trimmed file contents
34
+ */
35
+ public trimFile(filePath: string, content: string, mode: ContextMode = 'trimmed'): string {
36
+ // If mode is 'full', return the original content
37
+ if (mode === 'full') {
38
+ return content;
39
+ }
40
+
41
+ // Process based on file type
42
+ if (filePath.endsWith('.ts') || filePath.endsWith('.tsx')) {
43
+ return this.trimTypeScriptFile(content);
44
+ } else if (filePath.endsWith('.md')) {
45
+ return this.trimMarkdownFile(content);
46
+ } else if (filePath.endsWith('.json')) {
47
+ return this.trimJsonFile(content);
48
+ }
49
+
50
+ // Default to returning the original content for unknown file types
51
+ return content;
52
+ }
53
+
54
+ /**
55
+ * Trim a TypeScript file to reduce token usage
56
+ * @param content The TypeScript file contents
57
+ * @returns The trimmed file contents
58
+ */
59
+ private trimTypeScriptFile(content: string): string {
60
+ let result = content;
61
+
62
+ // Step 1: Preserve JSDoc comments if configured
63
+ const jsDocComments: string[] = [];
64
+ if (this.config.preserveJSDoc) {
65
+ const jsDocRegex = /\/\*\*[\s\S]*?\*\//g;
66
+ const matches = result.match(jsDocRegex) || [];
67
+ jsDocComments.push(...matches);
68
+ }
69
+
70
+ // Step 2: Remove comments if configured
71
+ if (this.config.removeComments) {
72
+ // Remove single-line comments
73
+ result = result.replace(/\/\/.*$/gm, '');
74
+ // Remove multi-line comments (except JSDoc if preserveJSDoc is true)
75
+ if (!this.config.preserveJSDoc) {
76
+ result = result.replace(/\/\*[\s\S]*?\*\//g, '');
77
+ } else {
78
+ // Only remove non-JSDoc comments
79
+ result = result.replace(/\/\*(?!\*)[\s\S]*?\*\//g, '');
80
+ }
81
+ }
82
+
83
+ // Step 3: Remove function implementations if configured
84
+ if (this.config.removeImplementations) {
85
+ // Match function and method bodies
86
+ result = result.replace(
87
+ /(\b(function|constructor|async function)\s+[\w$]*\s*\([^)]*\)\s*{)([\s\S]*?)(})/g,
88
+ (match, start, funcType, body, end) => {
89
+ // Keep function signature and opening brace, replace body with comment
90
+ return `${start} /* implementation removed */ ${end}`;
91
+ }
92
+ );
93
+
94
+ // Match arrow function bodies
95
+ result = result.replace(
96
+ /(\([^)]*\)\s*=>\s*{)([\s\S]*?)(})/g,
97
+ (match, start, body, end) => {
98
+ return `${start} /* implementation removed */ ${end}`;
99
+ }
100
+ );
101
+
102
+ // Match method declarations
103
+ result = result.replace(
104
+ /(^\s*[\w$]*\s*\([^)]*\)\s*{)([\s\S]*?)(})/gm,
105
+ (match, start, body, end) => {
106
+ return `${start} /* implementation removed */ ${end}`;
107
+ }
108
+ );
109
+
110
+ // Match class methods
111
+ result = result.replace(
112
+ /(\b(public|private|protected|static|async)?\s+[\w$]+\s*\([^)]*\)\s*{)([\s\S]*?)(})/g,
113
+ (match, start, modifier, body, end) => {
114
+ return `${start} /* implementation removed */ ${end}`;
115
+ }
116
+ );
117
+ } else if (this.config.maxFunctionLines && this.config.maxFunctionLines > 0) {
118
+ // If not removing implementations completely, limit the number of lines
119
+ // Match function and method bodies
120
+ result = result.replace(
121
+ /(\b(function|constructor|async function)\s+[\w$]*\s*\([^)]*\)\s*{)([\s\S]*?)(})/g,
122
+ (match, start, funcType, body, end) => {
123
+ return this.limitFunctionBody(start, body, end);
124
+ }
125
+ );
126
+
127
+ // Match arrow function bodies
128
+ result = result.replace(
129
+ /(\([^)]*\)\s*=>\s*{)([\s\S]*?)(})/g,
130
+ (match, start, body, end) => {
131
+ return this.limitFunctionBody(start, body, end);
132
+ }
133
+ );
134
+
135
+ // Match method declarations
136
+ result = result.replace(
137
+ /(^\s*[\w$]*\s*\([^)]*\)\s*{)([\s\S]*?)(})/gm,
138
+ (match, start, body, end) => {
139
+ return this.limitFunctionBody(start, body, end);
140
+ }
141
+ );
142
+
143
+ // Match class methods
144
+ result = result.replace(
145
+ /(\b(public|private|protected|static|async)?\s+[\w$]+\s*\([^)]*\)\s*{)([\s\S]*?)(})/g,
146
+ (match, start, modifier, body, end) => {
147
+ return this.limitFunctionBody(start, body, end);
148
+ }
149
+ );
150
+ }
151
+
152
+ // Step 4: Remove blank lines if configured
153
+ if (this.config.removeBlankLines) {
154
+ result = result.replace(/^\s*[\r\n]/gm, '');
155
+ }
156
+
157
+ // Step 5: Restore preserved JSDoc comments
158
+ if (this.config.preserveJSDoc && jsDocComments.length > 0) {
159
+ // This is a placeholder; we already preserved JSDoc comments in the regex steps
160
+ }
161
+
162
+ return result;
163
+ }
164
+
165
+ /**
166
+ * Limit a function body to a maximum number of lines
167
+ * @param start The function signature and opening brace
168
+ * @param body The function body
169
+ * @param end The closing brace
170
+ * @returns The limited function body
171
+ */
172
+ private limitFunctionBody(start: string, body: string, end: string): string {
173
+ const lines = body.split('\n');
174
+ if (lines.length > this.config.maxFunctionLines!) {
175
+ const limitedBody = lines.slice(0, this.config.maxFunctionLines!).join('\n');
176
+ return `${start}${limitedBody}\n // ... (${lines.length - this.config.maxFunctionLines!} lines trimmed)\n${end}`;
177
+ }
178
+ return `${start}${body}${end}`;
179
+ }
180
+
181
+ /**
182
+ * Trim a Markdown file to reduce token usage
183
+ * @param content The Markdown file contents
184
+ * @returns The trimmed file contents
185
+ */
186
+ private trimMarkdownFile(content: string): string {
187
+ // For markdown files, we generally want to keep most content
188
+ // but we can remove lengthy code blocks if needed
189
+ return content;
190
+ }
191
+
192
+ /**
193
+ * Trim a JSON file to reduce token usage
194
+ * @param content The JSON file contents
195
+ * @returns The trimmed file contents
196
+ */
197
+ private trimJsonFile(content: string): string {
198
+ try {
199
+ // Parse the JSON
200
+ const json = JSON.parse(content);
201
+
202
+ // For package.json, keep only essential information
203
+ if ('name' in json && 'version' in json && 'dependencies' in json) {
204
+ const essentialKeys = [
205
+ 'name', 'version', 'description', 'author', 'license',
206
+ 'main', 'types', 'exports', 'type'
207
+ ];
208
+
209
+ const trimmedJson: any = {};
210
+ essentialKeys.forEach(key => {
211
+ if (key in json) {
212
+ trimmedJson[key] = json[key];
213
+ }
214
+ });
215
+
216
+ // Add dependency information without versions
217
+ if ('dependencies' in json) {
218
+ trimmedJson.dependencies = Object.keys(json.dependencies).reduce((acc, dep) => {
219
+ acc[dep] = '*'; // Replace version with wildcard
220
+ return acc;
221
+ }, {} as Record<string, string>);
222
+ }
223
+
224
+ // Return the trimmed JSON
225
+ return JSON.stringify(trimmedJson, null, 2);
226
+ }
227
+
228
+ // For other JSON files, leave as is
229
+ return content;
230
+ } catch (error) {
231
+ // If there's an error parsing the JSON, return the original content
232
+ return content;
233
+ }
234
+ }
235
+
236
+ /**
237
+ * Update the trimmer configuration
238
+ * @param config The new configuration to apply
239
+ */
240
+ public updateConfig(config: ITrimConfig): void {
241
+ this.config = {
242
+ ...this.config,
243
+ ...config
244
+ };
245
+ }
246
+ }