@git.zone/tsdoc 1.11.1 → 1.11.3
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/aidocs_classes/commit.js +65 -42
- package/dist_ts/aidocs_classes/description.js +68 -29
- package/dist_ts/aidocs_classes/projectcontext.d.ts +5 -5
- package/dist_ts/aidocs_classes/projectcontext.js +8 -16
- package/dist_ts/aidocs_classes/readme.js +156 -88
- package/dist_ts/classes.aidoc.d.ts +10 -6
- package/dist_ts/classes.aidoc.js +17 -11
- package/dist_ts/classes.diffprocessor.js +284 -0
- package/dist_ts/cli.js +21 -92
- package/dist_ts/plugins.d.ts +1 -2
- package/dist_ts/plugins.js +2 -3
- package/package.json +2 -3
- package/ts/aidocs_classes/commit.ts +67 -51
- package/ts/aidocs_classes/description.ts +72 -34
- package/ts/aidocs_classes/projectcontext.ts +7 -14
- package/ts/aidocs_classes/readme.ts +168 -93
- package/ts/classes.aidoc.ts +18 -11
- package/ts/cli.ts +20 -100
- package/ts/plugins.ts +1 -2
- package/dist_ts/context/config-manager.d.ts +0 -83
- package/dist_ts/context/config-manager.js +0 -318
- package/dist_ts/context/context-analyzer.d.ts +0 -73
- package/dist_ts/context/context-analyzer.js +0 -311
- package/dist_ts/context/context-cache.d.ts +0 -73
- package/dist_ts/context/context-cache.js +0 -239
- package/dist_ts/context/context-trimmer.d.ts +0 -60
- package/dist_ts/context/context-trimmer.js +0 -258
- package/dist_ts/context/diff-processor.js +0 -284
- package/dist_ts/context/enhanced-context.d.ts +0 -73
- package/dist_ts/context/enhanced-context.js +0 -275
- package/dist_ts/context/index.d.ts +0 -11
- package/dist_ts/context/index.js +0 -12
- package/dist_ts/context/iterative-context-builder.d.ts +0 -62
- package/dist_ts/context/iterative-context-builder.js +0 -395
- package/dist_ts/context/lazy-file-loader.d.ts +0 -60
- package/dist_ts/context/lazy-file-loader.js +0 -182
- package/dist_ts/context/task-context-factory.d.ts +0 -48
- package/dist_ts/context/task-context-factory.js +0 -86
- package/dist_ts/context/types.d.ts +0 -301
- package/dist_ts/context/types.js +0 -2
- package/dist_ts/tsdoc.classes.typedoc.d.ts +0 -10
- package/dist_ts/tsdoc.classes.typedoc.js +0 -48
- package/dist_ts/tsdoc.cli.d.ts +0 -1
- package/dist_ts/tsdoc.cli.js +0 -32
- package/dist_ts/tsdoc.logging.d.ts +0 -2
- package/dist_ts/tsdoc.logging.js +0 -14
- package/dist_ts/tsdoc.paths.d.ts +0 -8
- package/dist_ts/tsdoc.paths.js +0 -12
- package/dist_ts/tsdoc.plugins.d.ts +0 -11
- package/dist_ts/tsdoc.plugins.js +0 -15
- package/ts/context/config-manager.ts +0 -369
- package/ts/context/context-analyzer.ts +0 -391
- package/ts/context/context-cache.ts +0 -286
- package/ts/context/context-trimmer.ts +0 -310
- package/ts/context/enhanced-context.ts +0 -332
- package/ts/context/index.ts +0 -70
- package/ts/context/iterative-context-builder.ts +0 -512
- package/ts/context/lazy-file-loader.ts +0 -207
- package/ts/context/task-context-factory.ts +0 -120
- package/ts/context/types.ts +0 -324
- /package/dist_ts/{context/diff-processor.d.ts → classes.diffprocessor.d.ts} +0 -0
- /package/ts/{context/diff-processor.ts → classes.diffprocessor.ts} +0 -0
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import * as plugins from '../plugins.js';
|
|
2
2
|
import { AiDoc } from '../classes.aidoc.js';
|
|
3
3
|
import { ProjectContext } from './projectcontext.js';
|
|
4
|
-
import { DiffProcessor } from '../
|
|
4
|
+
import { DiffProcessor } from '../classes.diffprocessor.js';
|
|
5
|
+
import { logger } from '../logging.js';
|
|
5
6
|
|
|
6
7
|
export interface INextCommitObject {
|
|
7
8
|
recommendedNextVersionLevel: 'fix' | 'feat' | 'BREAKING CHANGE'; // the recommended next version level of the project
|
|
@@ -114,80 +115,83 @@ export class Commit {
|
|
|
114
115
|
processedDiffString = 'No changes.';
|
|
115
116
|
}
|
|
116
117
|
|
|
117
|
-
// Use
|
|
118
|
-
const taskContextFactory = new (await import('../context/index.js')).TaskContextFactory(
|
|
119
|
-
this.projectDir,
|
|
120
|
-
this.aiDocsRef.openaiInstance
|
|
121
|
-
);
|
|
122
|
-
await taskContextFactory.initialize();
|
|
123
|
-
|
|
124
|
-
// Generate context specifically for commit task
|
|
125
|
-
const contextResult = await taskContextFactory.createContextForCommit(processedDiffString);
|
|
126
|
-
|
|
127
|
-
// Get the optimized context string
|
|
128
|
-
let contextString = contextResult.context;
|
|
129
|
-
|
|
130
|
-
// Log token usage statistics
|
|
131
|
-
console.log(`Token usage - Context: ${contextResult.tokenCount}, Files: ${contextResult.includedFiles.length + contextResult.trimmedFiles.length}, Savings: ${contextResult.tokenSavings}`);
|
|
132
|
-
|
|
133
|
-
// Check for token overflow against model limits
|
|
134
|
-
const MODEL_TOKEN_LIMIT = 200000; // o4-mini
|
|
135
|
-
if (contextResult.tokenCount > MODEL_TOKEN_LIMIT * 0.9) {
|
|
136
|
-
console.log(`⚠️ Warning: Context size (${contextResult.tokenCount} tokens) is close to or exceeds model limit (${MODEL_TOKEN_LIMIT} tokens).`);
|
|
137
|
-
console.log(`The model may not be able to process all information effectively.`);
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
// Use DualAgentOrchestrator for commit message generation with Guardian validation
|
|
118
|
+
// Use DualAgentOrchestrator for commit message generation
|
|
141
119
|
const commitOrchestrator = new plugins.smartagent.DualAgentOrchestrator({
|
|
142
|
-
|
|
120
|
+
smartAiInstance: this.aiDocsRef.smartAiInstance,
|
|
143
121
|
defaultProvider: 'openai',
|
|
122
|
+
logPrefix: '[Commit]',
|
|
123
|
+
onProgress: (event) => logger.log(event.logLevel, event.logMessage),
|
|
144
124
|
guardianPolicyPrompt: `
|
|
145
125
|
You validate commit messages for semantic versioning compliance.
|
|
146
126
|
|
|
147
|
-
APPROVE
|
|
127
|
+
APPROVE tool calls for:
|
|
128
|
+
- Reading package.json or source files to understand project context
|
|
129
|
+
- Using tree to see project structure
|
|
130
|
+
- Listing directory contents
|
|
131
|
+
|
|
132
|
+
REJECT tool calls for:
|
|
133
|
+
- Reading files outside the project directory
|
|
134
|
+
- Writing, deleting, or modifying any files
|
|
135
|
+
- Any destructive operations
|
|
136
|
+
|
|
137
|
+
APPROVE final output if:
|
|
148
138
|
- Version level (fix/feat/BREAKING CHANGE) matches the scope of changes in the diff
|
|
149
139
|
- Commit message is clear, professional, and follows conventional commit conventions
|
|
150
140
|
- No personal information, licensing details, or AI mentions (Claude/Codex) included
|
|
151
141
|
- JSON structure is valid with all required fields
|
|
152
142
|
- Scope accurately reflects the changed modules/files
|
|
153
143
|
|
|
154
|
-
REJECT
|
|
144
|
+
REJECT final output if:
|
|
155
145
|
- Version level doesn't match the scope of changes (e.g., "feat" for a typo fix should be "fix")
|
|
156
146
|
- Message is vague, unprofessional, or contains sensitive information
|
|
157
|
-
- JSON is malformed or missing required fields
|
|
147
|
+
- JSON is malformed or missing required fields
|
|
158
148
|
`,
|
|
159
149
|
});
|
|
160
150
|
|
|
151
|
+
// Register scoped filesystem tool for agent exploration
|
|
152
|
+
commitOrchestrator.registerScopedFilesystemTool(this.projectDir, [
|
|
153
|
+
'.nogit/**',
|
|
154
|
+
'node_modules/**',
|
|
155
|
+
'.git/**',
|
|
156
|
+
'dist/**',
|
|
157
|
+
'dist_*/**',
|
|
158
|
+
]);
|
|
159
|
+
|
|
161
160
|
await commitOrchestrator.start();
|
|
162
161
|
|
|
163
162
|
const commitTaskPrompt = `
|
|
164
163
|
You create a commit message for a git commit.
|
|
165
|
-
|
|
166
|
-
You should not include any licensing information.
|
|
167
|
-
You should not include any personal information.
|
|
164
|
+
Project directory: ${this.projectDir}
|
|
168
165
|
|
|
169
|
-
|
|
166
|
+
You have access to a filesystem tool to explore the project if needed:
|
|
167
|
+
- Use tree to see project structure
|
|
168
|
+
- Use read to read package.json or source files for context
|
|
170
169
|
|
|
171
|
-
|
|
170
|
+
Analyze the git diff below to understand what changed and generate a commit message.
|
|
172
171
|
|
|
173
|
-
|
|
172
|
+
You should not include any licensing information or personal information.
|
|
173
|
+
Never mention CLAUDE code, or codex.
|
|
174
174
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
175
|
+
Your final output (inside the task_complete tags) must be ONLY valid JSON - the raw JSON object, nothing else.
|
|
176
|
+
No explanations, no summaries, no markdown - just the JSON object that can be parsed with JSON.parse().
|
|
177
|
+
|
|
178
|
+
Here is the structure of the JSON you must return:
|
|
179
|
+
|
|
180
|
+
{
|
|
181
|
+
"recommendedNextVersionLevel": "fix" | "feat" | "BREAKING CHANGE",
|
|
182
|
+
"recommendedNextVersionScope": "string",
|
|
183
|
+
"recommendedNextVersionMessage": "string",
|
|
184
|
+
"recommendedNextVersionDetails": ["string"],
|
|
185
|
+
"recommendedNextVersion": "x.x.x"
|
|
181
186
|
}
|
|
182
187
|
|
|
183
|
-
For
|
|
188
|
+
For recommendedNextVersionDetails, only add entries that have obvious value to the reader.
|
|
184
189
|
|
|
185
|
-
|
|
186
|
-
Also you are given a diff.
|
|
187
|
-
Never mention CLAUDE code, or codex.
|
|
190
|
+
Here is the git diff showing what changed:
|
|
188
191
|
|
|
189
|
-
|
|
190
|
-
|
|
192
|
+
${processedDiffString}
|
|
193
|
+
|
|
194
|
+
Analyze these changes and output the JSON commit message object.
|
|
191
195
|
`;
|
|
192
196
|
|
|
193
197
|
const commitResult = await commitOrchestrator.run(commitTaskPrompt);
|
|
@@ -197,9 +201,19 @@ ${contextString}
|
|
|
197
201
|
throw new Error(`Commit message generation failed: ${commitResult.status}`);
|
|
198
202
|
}
|
|
199
203
|
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
204
|
+
// Extract JSON from result - handle cases where AI adds text around it
|
|
205
|
+
let jsonString = commitResult.result
|
|
206
|
+
.replace(/```json\n?/gi, '')
|
|
207
|
+
.replace(/```\n?/gi, '');
|
|
208
|
+
|
|
209
|
+
// Try to find JSON object in the result
|
|
210
|
+
const jsonMatch = jsonString.match(/\{[\s\S]*\}/);
|
|
211
|
+
if (!jsonMatch) {
|
|
212
|
+
throw new Error(`Could not find JSON object in result: ${jsonString.substring(0, 100)}...`);
|
|
213
|
+
}
|
|
214
|
+
jsonString = jsonMatch[0];
|
|
215
|
+
|
|
216
|
+
const resultObject: INextCommitObject = JSON.parse(jsonString);
|
|
203
217
|
|
|
204
218
|
const previousChangelogPath = plugins.path.join(this.projectDir, 'changelog.md');
|
|
205
219
|
let previousChangelog: plugins.smartfile.SmartFile;
|
|
@@ -214,8 +228,10 @@ ${contextString}
|
|
|
214
228
|
|
|
215
229
|
// Use DualAgentOrchestrator for changelog generation with Guardian validation
|
|
216
230
|
const changelogOrchestrator = new plugins.smartagent.DualAgentOrchestrator({
|
|
217
|
-
|
|
231
|
+
smartAiInstance: this.aiDocsRef.smartAiInstance,
|
|
218
232
|
defaultProvider: 'openai',
|
|
233
|
+
logPrefix: '[Changelog]',
|
|
234
|
+
onProgress: (event) => logger.log(event.logLevel, event.logMessage),
|
|
219
235
|
guardianPolicyPrompt: `
|
|
220
236
|
You validate changelog generation.
|
|
221
237
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { AiDoc } from '../classes.aidoc.js';
|
|
2
2
|
import * as plugins from '../plugins.js';
|
|
3
3
|
import { ProjectContext } from './projectcontext.js';
|
|
4
|
+
import { logger } from '../logging.js';
|
|
4
5
|
|
|
5
6
|
interface IDescriptionInterface {
|
|
6
7
|
description: string;
|
|
@@ -18,50 +19,87 @@ export class Description {
|
|
|
18
19
|
}
|
|
19
20
|
|
|
20
21
|
public async build() {
|
|
21
|
-
// Use
|
|
22
|
-
const
|
|
23
|
-
this.
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
22
|
+
// Use DualAgentOrchestrator with filesystem tool for agent-driven exploration
|
|
23
|
+
const descriptionOrchestrator = new plugins.smartagent.DualAgentOrchestrator({
|
|
24
|
+
smartAiInstance: this.aiDocsRef.smartAiInstance,
|
|
25
|
+
defaultProvider: 'openai',
|
|
26
|
+
maxIterations: 15,
|
|
27
|
+
maxResultChars: 10000, // Limit tool output to prevent token explosion
|
|
28
|
+
maxHistoryMessages: 15, // Limit history window
|
|
29
|
+
logPrefix: '[Description]',
|
|
30
|
+
onProgress: (event) => logger.log(event.logLevel, event.logMessage),
|
|
31
|
+
guardianPolicyPrompt: `
|
|
32
|
+
You validate description generation tool calls and outputs.
|
|
33
|
+
|
|
34
|
+
APPROVE tool calls for:
|
|
35
|
+
- Reading package.json, npmextra.json, or source files in the ts/ directory
|
|
36
|
+
- Listing directory contents to understand project structure
|
|
37
|
+
- Using tree to see project structure
|
|
38
|
+
|
|
39
|
+
REJECT tool calls for:
|
|
40
|
+
- Reading files outside the project directory
|
|
41
|
+
- Writing, deleting, or modifying any files
|
|
42
|
+
- Any destructive operations
|
|
43
|
+
|
|
44
|
+
For final output, APPROVE if:
|
|
45
|
+
- JSON is valid and parseable
|
|
46
|
+
- Description is a clear, concise one-sentence summary
|
|
47
|
+
- Keywords are relevant to the project's use cases
|
|
48
|
+
- Both description and keywords fields are present
|
|
49
|
+
|
|
50
|
+
REJECT final output if:
|
|
51
|
+
- JSON is malformed or wrapped in markdown code blocks
|
|
52
|
+
- Description is too long or vague
|
|
53
|
+
- Keywords are irrelevant or generic
|
|
54
|
+
`,
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
// Register scoped filesystem tool for agent exploration
|
|
58
|
+
descriptionOrchestrator.registerScopedFilesystemTool(this.projectDir);
|
|
59
|
+
|
|
60
|
+
await descriptionOrchestrator.start();
|
|
61
|
+
|
|
62
|
+
const descriptionTaskPrompt = `
|
|
63
|
+
You create a project description and keywords for an npm package.
|
|
64
|
+
|
|
65
|
+
PROJECT DIRECTORY: ${this.projectDir}
|
|
66
|
+
|
|
67
|
+
Use the filesystem tool to explore the project and understand what it does:
|
|
68
|
+
1. First, use tree to see the project structure
|
|
69
|
+
2. Read package.json to understand the package name and current description
|
|
70
|
+
3. Read npmextra.json if it exists for additional metadata
|
|
71
|
+
4. Read key source files in ts/ directory to understand the implementation
|
|
72
|
+
|
|
73
|
+
Then generate a description and keywords based on your exploration.
|
|
74
|
+
|
|
75
|
+
Your FINAL response must be valid JSON adhering to this interface:
|
|
38
76
|
{
|
|
39
77
|
description: string; // a sensible short, one sentence description of the project
|
|
40
|
-
keywords: string[]; // an array of tags that describe the project
|
|
78
|
+
keywords: string[]; // an array of tags that describe the project based on use cases
|
|
41
79
|
}
|
|
42
80
|
|
|
43
|
-
The description should be based on what you understand from the project's files.
|
|
44
|
-
The keywords should be based on use cases you see from the files.
|
|
45
|
-
Don't be cheap about the way you think.
|
|
46
|
-
|
|
47
81
|
Important: Answer only in valid JSON.
|
|
48
|
-
|
|
82
|
+
Your answer should be parseable with JSON.parse() without modifying anything.
|
|
83
|
+
Don't wrap the JSON in \`\`\`json\`\`\` - just return the raw JSON object.
|
|
84
|
+
`;
|
|
49
85
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
messageHistory: [],
|
|
53
|
-
userMessage: contextString,
|
|
54
|
-
});
|
|
86
|
+
const descriptionResult = await descriptionOrchestrator.run(descriptionTaskPrompt);
|
|
87
|
+
await descriptionOrchestrator.stop();
|
|
55
88
|
|
|
56
|
-
|
|
89
|
+
if (!descriptionResult.success) {
|
|
90
|
+
throw new Error(`Description generation failed: ${descriptionResult.status}`);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
console.log(descriptionResult.result);
|
|
57
94
|
const resultObject: IDescriptionInterface = JSON.parse(
|
|
58
|
-
result.
|
|
95
|
+
descriptionResult.result.replace('```json', '').replace('```', ''),
|
|
59
96
|
);
|
|
60
97
|
|
|
61
|
-
//
|
|
98
|
+
// Use ProjectContext to get file handles for writing
|
|
62
99
|
const projectContext = new ProjectContext(this.projectDir);
|
|
63
100
|
const files = await projectContext.gatherFiles();
|
|
64
|
-
|
|
101
|
+
|
|
102
|
+
// Update npmextra.json
|
|
65
103
|
const npmextraJson = files.smartfilesNpmextraJSON;
|
|
66
104
|
const npmextraJsonContent = JSON.parse(npmextraJson.contents.toString());
|
|
67
105
|
|
|
@@ -71,7 +109,7 @@ Don't wrap the JSON in three ticks json!!!
|
|
|
71
109
|
npmextraJson.contents = Buffer.from(JSON.stringify(npmextraJsonContent, null, 2));
|
|
72
110
|
await npmextraJson.write();
|
|
73
111
|
|
|
74
|
-
//
|
|
112
|
+
// Update package.json
|
|
75
113
|
const packageJson = files.smartfilePackageJSON;
|
|
76
114
|
const packageJsonContent = JSON.parse(packageJson.contents.toString());
|
|
77
115
|
packageJsonContent.description = resultObject.description;
|
|
@@ -82,6 +120,6 @@ Don't wrap the JSON in three ticks json!!!
|
|
|
82
120
|
console.log(`\n======================\n`);
|
|
83
121
|
console.log(JSON.stringify(resultObject, null, 2));
|
|
84
122
|
console.log(`\n======================\n`);
|
|
85
|
-
return result
|
|
123
|
+
return descriptionResult.result;
|
|
86
124
|
}
|
|
87
125
|
}
|
|
@@ -64,21 +64,14 @@ ${smartfile.contents.toString()}
|
|
|
64
64
|
}
|
|
65
65
|
|
|
66
66
|
/**
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
* @param
|
|
70
|
-
* @returns
|
|
67
|
+
* Estimate token count for a string
|
|
68
|
+
* Uses a rough estimate of 4 characters per token
|
|
69
|
+
* @param text The text to estimate tokens for
|
|
70
|
+
* @returns Estimated number of tokens
|
|
71
71
|
*/
|
|
72
|
-
public countTokens(text: string
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
const tokens = plugins.gptTokenizer.encode(text);
|
|
76
|
-
return tokens.length;
|
|
77
|
-
} catch (error) {
|
|
78
|
-
console.error('Error counting tokens:', error);
|
|
79
|
-
// Provide a rough estimate (4 chars per token) if tokenization fails
|
|
80
|
-
return Math.ceil(text.length / 4);
|
|
81
|
-
}
|
|
72
|
+
public countTokens(text: string): number {
|
|
73
|
+
// Rough estimate: ~4 characters per token for English text
|
|
74
|
+
return Math.ceil(text.length / 4);
|
|
82
75
|
}
|
|
83
76
|
|
|
84
77
|
private async buildContext(dirArg: string) {
|
|
@@ -17,21 +17,7 @@ export class Readme {
|
|
|
17
17
|
public async build() {
|
|
18
18
|
let finalReadmeString = ``;
|
|
19
19
|
|
|
20
|
-
//
|
|
21
|
-
const taskContextFactory = new (await import('../context/index.js')).TaskContextFactory(
|
|
22
|
-
this.projectDir,
|
|
23
|
-
this.aiDocsRef.openaiInstance
|
|
24
|
-
);
|
|
25
|
-
await taskContextFactory.initialize();
|
|
26
|
-
|
|
27
|
-
// Generate context specifically for readme task
|
|
28
|
-
const contextResult = await taskContextFactory.createContextForReadme();
|
|
29
|
-
const contextString = contextResult.context;
|
|
30
|
-
|
|
31
|
-
// Log token usage statistics
|
|
32
|
-
console.log(`Token usage - Context: ${contextResult.tokenCount}, Files: ${contextResult.includedFiles.length + contextResult.trimmedFiles.length}, Savings: ${contextResult.tokenSavings}`);
|
|
33
|
-
|
|
34
|
-
// lets first check legal before introducung any cost
|
|
20
|
+
// First check legal info before introducing any cost
|
|
35
21
|
const projectContext = new ProjectContext(this.projectDir);
|
|
36
22
|
const npmExtraJson = JSON.parse(
|
|
37
23
|
(await projectContext.gatherFiles()).smartfilesNpmextraJSON.contents.toString()
|
|
@@ -42,50 +28,100 @@ export class Readme {
|
|
|
42
28
|
console.log(error);
|
|
43
29
|
}
|
|
44
30
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
31
|
+
// Use DualAgentOrchestrator with filesystem tool for agent-driven exploration
|
|
32
|
+
const readmeOrchestrator = new plugins.smartagent.DualAgentOrchestrator({
|
|
33
|
+
smartAiInstance: this.aiDocsRef.smartAiInstance,
|
|
34
|
+
defaultProvider: 'openai',
|
|
35
|
+
maxIterations: 25,
|
|
36
|
+
maxResultChars: 15000, // Limit tool output to prevent token explosion
|
|
37
|
+
maxHistoryMessages: 20, // Limit history window
|
|
38
|
+
logPrefix: '[README]',
|
|
39
|
+
onProgress: (event) => logger.log(event.logLevel, event.logMessage),
|
|
40
|
+
guardianPolicyPrompt: `
|
|
41
|
+
You validate README generation tool calls and outputs.
|
|
42
|
+
|
|
43
|
+
APPROVE tool calls for:
|
|
44
|
+
- Reading any files within the project directory (package.json, ts/*.ts, readme.md, etc.)
|
|
45
|
+
- Using tree to see project structure
|
|
46
|
+
- Using glob to find source files
|
|
47
|
+
- Listing directory contents
|
|
48
|
+
|
|
49
|
+
REJECT tool calls for:
|
|
50
|
+
- Reading files outside the project directory
|
|
51
|
+
- Writing, deleting, or modifying any files
|
|
52
|
+
- Any destructive operations
|
|
53
|
+
|
|
54
|
+
For final README output, APPROVE if:
|
|
55
|
+
- README follows proper markdown format
|
|
56
|
+
- Contains Install and Usage sections
|
|
57
|
+
- Code examples are correct TypeScript/ESM syntax
|
|
58
|
+
- Documentation is comprehensive and helpful
|
|
59
|
+
|
|
60
|
+
REJECT final output if:
|
|
61
|
+
- README is incomplete or poorly formatted
|
|
62
|
+
- Contains licensing information (added separately)
|
|
63
|
+
- Uses CommonJS syntax instead of ESM
|
|
64
|
+
- Contains "in conclusion" or similar filler
|
|
65
|
+
`,
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
// Register scoped filesystem tool for agent exploration
|
|
69
|
+
readmeOrchestrator.registerScopedFilesystemTool(this.projectDir);
|
|
70
|
+
|
|
71
|
+
await readmeOrchestrator.start();
|
|
72
|
+
|
|
73
|
+
const readmeTaskPrompt = `
|
|
74
|
+
You create markdown READMEs for npm projects. You only output the markdown readme.
|
|
48
75
|
|
|
49
|
-
|
|
76
|
+
PROJECT DIRECTORY: ${this.projectDir}
|
|
77
|
+
|
|
78
|
+
Use the filesystem tool to explore the project and understand what it does:
|
|
79
|
+
1. First, use tree to see the project structure (maxDepth: 3)
|
|
80
|
+
2. Read package.json to understand the package name, description, and dependencies
|
|
81
|
+
3. Read the existing readme.md if it exists (use it as a base, improve and expand)
|
|
82
|
+
4. Read readme.hints.md if it exists (contains hints for documentation)
|
|
83
|
+
5. Read key source files in ts/ directory to understand the API and implementation
|
|
84
|
+
6. Focus on exported classes, interfaces, and functions
|
|
85
|
+
|
|
86
|
+
Then generate a comprehensive README following this template:
|
|
50
87
|
|
|
51
88
|
# Project Name
|
|
52
|
-
[
|
|
53
|
-
The name is the module name of package.json
|
|
54
|
-
The description is in the description field of package.json
|
|
55
|
-
]
|
|
89
|
+
[The name from package.json and description]
|
|
56
90
|
|
|
57
91
|
## Install
|
|
58
|
-
[
|
|
59
|
-
Write a short text on how to install the project
|
|
60
|
-
]
|
|
92
|
+
[Short text on how to install the project]
|
|
61
93
|
|
|
62
94
|
## Usage
|
|
63
|
-
[
|
|
95
|
+
[
|
|
64
96
|
Give code examples here.
|
|
65
97
|
Construct sensible scenarios for the user.
|
|
66
98
|
Make sure to show a complete set of features of the module.
|
|
67
99
|
Don't omit use cases.
|
|
68
|
-
It does not matter how much time you need.
|
|
69
100
|
ALWAYS USE ESM SYNTAX AND TYPESCRIPT.
|
|
70
|
-
|
|
71
|
-
If there is already a readme, take the Usage section as base. Remove outdated content,
|
|
72
|
-
|
|
73
|
-
Don't include any licensing information. This will be added
|
|
74
|
-
Avoid "in
|
|
75
|
-
|
|
76
|
-
Good to know:
|
|
77
|
-
* npmextra.json contains overall module information.
|
|
78
|
-
* readme.hints.md provides valuable hints about module ideas.
|
|
101
|
+
Write at least 4000 words. More if necessary.
|
|
102
|
+
If there is already a readme, take the Usage section as base. Remove outdated content, expand and improve.
|
|
103
|
+
Check for completeness.
|
|
104
|
+
Don't include any licensing information. This will be added later.
|
|
105
|
+
Avoid "in conclusion" statements.
|
|
79
106
|
]
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
107
|
+
`;
|
|
108
|
+
|
|
109
|
+
const readmeResult = await readmeOrchestrator.run(readmeTaskPrompt);
|
|
110
|
+
await readmeOrchestrator.stop();
|
|
111
|
+
|
|
112
|
+
if (!readmeResult.success) {
|
|
113
|
+
throw new Error(`README generation failed: ${readmeResult.status}`);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Clean up markdown formatting if wrapped in code blocks
|
|
117
|
+
let resultMessage = readmeResult.result
|
|
118
|
+
.replace(/^```markdown\n?/i, '')
|
|
119
|
+
.replace(/\n?```$/i, '');
|
|
84
120
|
|
|
85
|
-
finalReadmeString +=
|
|
121
|
+
finalReadmeString += resultMessage + '\n' + legalInfo;
|
|
86
122
|
|
|
87
123
|
console.log(`\n======================\n`);
|
|
88
|
-
console.log(
|
|
124
|
+
console.log(resultMessage);
|
|
89
125
|
console.log(`\n======================\n`);
|
|
90
126
|
|
|
91
127
|
const readme = (await projectContext.gatherFiles()).smartfilesReadme;
|
|
@@ -96,60 +132,99 @@ The Readme should follow the following template:
|
|
|
96
132
|
const tsPublishInstance = new plugins.tspublish.TsPublish();
|
|
97
133
|
const subModules = await tsPublishInstance.getModuleSubDirs(paths.cwd);
|
|
98
134
|
logger.log('info', `Found ${Object.keys(subModules).length} sub modules`);
|
|
135
|
+
|
|
99
136
|
for (const subModule of Object.keys(subModules)) {
|
|
100
137
|
logger.log('info', `Building readme for ${subModule}`);
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
If there is already a readme, take the Usage section as base. Remove outdated content, and expand and improve upon the valid parts.
|
|
134
|
-
Super important: Check for completenes.
|
|
135
|
-
Don't include any licensing information. This will be added in a later step.
|
|
136
|
-
Avoid "in conclusions".
|
|
137
|
-
|
|
138
|
-
Good to know:
|
|
139
|
-
* npmextra.json contains overall module information.
|
|
140
|
-
* readme.hints.md provides valuable hints about module ideas.
|
|
141
|
-
* Your output lands directly in the readme.md file.
|
|
142
|
-
* Don't use \`\`\` at the beginning or the end. It'll cause problems. Only use it for codeblocks. You are directly writing markdown. No need to introduce it weirdly.
|
|
143
|
-
]
|
|
144
|
-
`,
|
|
145
|
-
messageHistory: [],
|
|
146
|
-
userMessage: subModuleContextString,
|
|
138
|
+
|
|
139
|
+
const subModulePath = plugins.path.join(paths.cwd, subModule);
|
|
140
|
+
const tspublishData = await plugins.fsInstance
|
|
141
|
+
.file(plugins.path.join(subModulePath, 'tspublish.json'))
|
|
142
|
+
.encoding('utf8')
|
|
143
|
+
.read();
|
|
144
|
+
|
|
145
|
+
// Create a new orchestrator with filesystem tool for each submodule
|
|
146
|
+
const subModuleOrchestrator = new plugins.smartagent.DualAgentOrchestrator({
|
|
147
|
+
smartAiInstance: this.aiDocsRef.smartAiInstance,
|
|
148
|
+
defaultProvider: 'openai',
|
|
149
|
+
maxIterations: 20,
|
|
150
|
+
maxResultChars: 12000,
|
|
151
|
+
maxHistoryMessages: 15,
|
|
152
|
+
logPrefix: `[README:${subModule}]`,
|
|
153
|
+
onProgress: (event) => logger.log(event.logLevel, event.logMessage),
|
|
154
|
+
guardianPolicyPrompt: `
|
|
155
|
+
You validate README generation for submodules.
|
|
156
|
+
|
|
157
|
+
APPROVE tool calls for:
|
|
158
|
+
- Reading any files within the submodule directory
|
|
159
|
+
- Using tree to see structure
|
|
160
|
+
- Using glob to find source files
|
|
161
|
+
|
|
162
|
+
REJECT tool calls for:
|
|
163
|
+
- Reading files outside the submodule directory
|
|
164
|
+
- Writing, deleting, or modifying any files
|
|
165
|
+
- Any destructive operations
|
|
166
|
+
|
|
167
|
+
APPROVE final README if comprehensive, well-formatted markdown with ESM TypeScript examples.
|
|
168
|
+
REJECT incomplete READMEs or those with licensing info.
|
|
169
|
+
`,
|
|
147
170
|
});
|
|
148
171
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
172
|
+
// Register scoped filesystem tool for the submodule directory
|
|
173
|
+
subModuleOrchestrator.registerScopedFilesystemTool(subModulePath);
|
|
174
|
+
|
|
175
|
+
await subModuleOrchestrator.start();
|
|
176
|
+
|
|
177
|
+
const subModulePrompt = `
|
|
178
|
+
You create markdown READMEs for npm projects. You only output the markdown readme.
|
|
179
|
+
SUB MODULE: ${subModule}
|
|
180
|
+
SUB MODULE DIRECTORY: ${subModulePath}
|
|
181
|
+
|
|
182
|
+
IMPORTANT: YOU ARE CREATING THE README FOR THIS SUB MODULE: ${subModule}
|
|
183
|
+
The Sub Module will be published with:
|
|
184
|
+
${JSON.stringify(tspublishData, null, 2)}
|
|
185
|
+
|
|
186
|
+
Use the filesystem tool to explore the submodule:
|
|
187
|
+
1. Use tree to see the submodule structure
|
|
188
|
+
2. Read package.json to understand the submodule
|
|
189
|
+
3. Read source files in ts/ directory to understand the implementation
|
|
190
|
+
|
|
191
|
+
Generate a README following the template:
|
|
192
|
+
|
|
193
|
+
# Project Name
|
|
194
|
+
[name and description from package.json]
|
|
195
|
+
|
|
196
|
+
## Install
|
|
197
|
+
[installation instructions]
|
|
198
|
+
|
|
199
|
+
## Usage
|
|
200
|
+
[
|
|
201
|
+
Code examples with complete features.
|
|
202
|
+
ESM TypeScript syntax only.
|
|
203
|
+
Write at least 4000 words.
|
|
204
|
+
No licensing information.
|
|
205
|
+
No "in conclusion".
|
|
206
|
+
]
|
|
207
|
+
|
|
208
|
+
Don't use \`\`\` at the beginning or end. Only for code blocks.
|
|
209
|
+
`;
|
|
210
|
+
|
|
211
|
+
const subModuleResult = await subModuleOrchestrator.run(subModulePrompt);
|
|
212
|
+
await subModuleOrchestrator.stop();
|
|
213
|
+
|
|
214
|
+
if (subModuleResult.success) {
|
|
215
|
+
const subModuleReadmeString = subModuleResult.result
|
|
216
|
+
.replace(/^```markdown\n?/i, '')
|
|
217
|
+
.replace(/\n?```$/i, '') + '\n' + legalInfo;
|
|
218
|
+
await plugins.fsInstance
|
|
219
|
+
.file(plugins.path.join(subModulePath, 'readme.md'))
|
|
220
|
+
.encoding('utf8')
|
|
221
|
+
.write(subModuleReadmeString);
|
|
222
|
+
logger.log('success', `Built readme for ${subModule}`);
|
|
223
|
+
} else {
|
|
224
|
+
logger.log('error', `Failed to build readme for ${subModule}: ${subModuleResult.status}`);
|
|
225
|
+
}
|
|
152
226
|
}
|
|
153
|
-
|
|
227
|
+
|
|
228
|
+
return resultMessage;
|
|
154
229
|
}
|
|
155
230
|
}
|