@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.
Files changed (62) hide show
  1. package/dist_ts/aidocs_classes/commit.js +65 -42
  2. package/dist_ts/aidocs_classes/description.js +68 -29
  3. package/dist_ts/aidocs_classes/projectcontext.d.ts +5 -5
  4. package/dist_ts/aidocs_classes/projectcontext.js +8 -16
  5. package/dist_ts/aidocs_classes/readme.js +156 -88
  6. package/dist_ts/classes.aidoc.d.ts +10 -6
  7. package/dist_ts/classes.aidoc.js +17 -11
  8. package/dist_ts/classes.diffprocessor.js +284 -0
  9. package/dist_ts/cli.js +21 -92
  10. package/dist_ts/plugins.d.ts +1 -2
  11. package/dist_ts/plugins.js +2 -3
  12. package/package.json +2 -3
  13. package/ts/aidocs_classes/commit.ts +67 -51
  14. package/ts/aidocs_classes/description.ts +72 -34
  15. package/ts/aidocs_classes/projectcontext.ts +7 -14
  16. package/ts/aidocs_classes/readme.ts +168 -93
  17. package/ts/classes.aidoc.ts +18 -11
  18. package/ts/cli.ts +20 -100
  19. package/ts/plugins.ts +1 -2
  20. package/dist_ts/context/config-manager.d.ts +0 -83
  21. package/dist_ts/context/config-manager.js +0 -318
  22. package/dist_ts/context/context-analyzer.d.ts +0 -73
  23. package/dist_ts/context/context-analyzer.js +0 -311
  24. package/dist_ts/context/context-cache.d.ts +0 -73
  25. package/dist_ts/context/context-cache.js +0 -239
  26. package/dist_ts/context/context-trimmer.d.ts +0 -60
  27. package/dist_ts/context/context-trimmer.js +0 -258
  28. package/dist_ts/context/diff-processor.js +0 -284
  29. package/dist_ts/context/enhanced-context.d.ts +0 -73
  30. package/dist_ts/context/enhanced-context.js +0 -275
  31. package/dist_ts/context/index.d.ts +0 -11
  32. package/dist_ts/context/index.js +0 -12
  33. package/dist_ts/context/iterative-context-builder.d.ts +0 -62
  34. package/dist_ts/context/iterative-context-builder.js +0 -395
  35. package/dist_ts/context/lazy-file-loader.d.ts +0 -60
  36. package/dist_ts/context/lazy-file-loader.js +0 -182
  37. package/dist_ts/context/task-context-factory.d.ts +0 -48
  38. package/dist_ts/context/task-context-factory.js +0 -86
  39. package/dist_ts/context/types.d.ts +0 -301
  40. package/dist_ts/context/types.js +0 -2
  41. package/dist_ts/tsdoc.classes.typedoc.d.ts +0 -10
  42. package/dist_ts/tsdoc.classes.typedoc.js +0 -48
  43. package/dist_ts/tsdoc.cli.d.ts +0 -1
  44. package/dist_ts/tsdoc.cli.js +0 -32
  45. package/dist_ts/tsdoc.logging.d.ts +0 -2
  46. package/dist_ts/tsdoc.logging.js +0 -14
  47. package/dist_ts/tsdoc.paths.d.ts +0 -8
  48. package/dist_ts/tsdoc.paths.js +0 -12
  49. package/dist_ts/tsdoc.plugins.d.ts +0 -11
  50. package/dist_ts/tsdoc.plugins.js +0 -15
  51. package/ts/context/config-manager.ts +0 -369
  52. package/ts/context/context-analyzer.ts +0 -391
  53. package/ts/context/context-cache.ts +0 -286
  54. package/ts/context/context-trimmer.ts +0 -310
  55. package/ts/context/enhanced-context.ts +0 -332
  56. package/ts/context/index.ts +0 -70
  57. package/ts/context/iterative-context-builder.ts +0 -512
  58. package/ts/context/lazy-file-loader.ts +0 -207
  59. package/ts/context/task-context-factory.ts +0 -120
  60. package/ts/context/types.ts +0 -324
  61. /package/dist_ts/{context/diff-processor.d.ts → classes.diffprocessor.d.ts} +0 -0
  62. /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 '../context/diff-processor.js';
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 the new TaskContextFactory for optimized context
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
- openaiToken: this.aiDocsRef.getOpenaiToken(),
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 if:
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 with specific feedback if:
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 (recommendedNextVersionLevel, recommendedNextVersionScope, recommendedNextVersionMessage, recommendedNextVersionDetails, recommendedNextVersion)
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
- The commit message should be based on the files in the project.
166
- You should not include any licensing information.
167
- You should not include any personal information.
164
+ Project directory: ${this.projectDir}
168
165
 
169
- Important: Answer only in valid JSON.
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
- Your answer should be parseable with JSON.parse() without modifying anything.
170
+ Analyze the git diff below to understand what changed and generate a commit message.
172
171
 
173
- Here is the structure of the JSON you should return:
172
+ You should not include any licensing information or personal information.
173
+ Never mention CLAUDE code, or codex.
174
174
 
175
- interface {
176
- recommendedNextVersionLevel: 'fix' | 'feat' | 'BREAKING CHANGE'; // the recommended next version level of the project
177
- recommendedNextVersionScope: string; // the recommended scope name of the next version, like "core" or "cli", or specific class names.
178
- recommendedNextVersionMessage: string; // the commit message. Don't put fix() feat() or BREAKING CHANGE in the message. Please just the message itself.
179
- recommendedNextVersionDetails: string[]; // detailed bullet points for the changelog
180
- recommendedNextVersion: string; // the recommended next version of the project, x.x.x
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 the recommendedNextVersionDetails, please only add a detail entries to the array if it has an obvious value to the reader.
188
+ For recommendedNextVersionDetails, only add entries that have obvious value to the reader.
184
189
 
185
- You are being given the files of the project. You should use them to create the commit message.
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
- Project context and diff:
190
- ${contextString}
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
- const resultObject: INextCommitObject = JSON.parse(
201
- commitResult.result.replace('```json', '').replace('```', '')
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
- openaiToken: this.aiDocsRef.getOpenaiToken(),
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 the new TaskContextFactory for optimized context
22
- const taskContextFactory = new (await import('../context/index.js')).TaskContextFactory(
23
- this.projectDir,
24
- this.aiDocsRef.openaiInstance
25
- );
26
- await taskContextFactory.initialize();
27
-
28
- // Generate context specifically for description task
29
- const contextResult = await taskContextFactory.createContextForDescription();
30
- const contextString = contextResult.context;
31
-
32
- // Log token usage statistics
33
- console.log(`Token usage - Context: ${contextResult.tokenCount}, Files: ${contextResult.includedFiles.length + contextResult.trimmedFiles.length}, Savings: ${contextResult.tokenSavings}`);
34
-
35
- let result = await this.aiDocsRef.openaiInstance.chat({
36
- systemMessage: `
37
- You create a json adhering the following interface:
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
- You answer should be parseable with JSON.parse() without modifying anything.
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
- Don't wrap the JSON in three ticks json!!!
51
- `,
52
- messageHistory: [],
53
- userMessage: contextString,
54
- });
86
+ const descriptionResult = await descriptionOrchestrator.run(descriptionTaskPrompt);
87
+ await descriptionOrchestrator.stop();
55
88
 
56
- console.log(result.message);
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.message.replace('```json', '').replace('```', ''),
95
+ descriptionResult.result.replace('```json', '').replace('```', ''),
59
96
  );
60
97
 
61
- // Create a standard ProjectContext instance for file operations
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
- // do the same with packageJson
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.message;
123
+ return descriptionResult.result;
86
124
  }
87
125
  }
@@ -64,21 +64,14 @@ ${smartfile.contents.toString()}
64
64
  }
65
65
 
66
66
  /**
67
- * Calculate the token count for a string using the GPT tokenizer
68
- * @param text The text to count tokens for
69
- * @param model The model to use for token counting (default: gpt-3.5-turbo)
70
- * @returns The number of tokens in the text
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, model: string = 'gpt-3.5-turbo'): number {
73
- try {
74
- // Use the gpt-tokenizer library to count tokens
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
- // Use the new TaskContextFactory for optimized context
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
- let result = await this.aiDocsRef.openaiInstance.chat({
46
- systemMessage: `
47
- You create markdown readmes for npm projects. You only output the markdown readme.
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
- The Readme should follow the following template:
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
- DON'T CHICKEN OUT. Write at least 4000 words. More if necessary.
71
- If there is already a readme, take the Usage section as base. Remove outdated content, and expand and improve upon the valid parts.
72
- Super important: Check for completenes.
73
- Don't include any licensing information. This will be added in a later step.
74
- Avoid "in conclusions".
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
- messageHistory: [],
82
- userMessage: contextString,
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 += result.message + '\n' + legalInfo;
121
+ finalReadmeString += resultMessage + '\n' + legalInfo;
86
122
 
87
123
  console.log(`\n======================\n`);
88
- console.log(result.message);
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
- const subModuleContextString = await projectContext.update();
102
- let result = await this.aiDocsRef.openaiInstance.chat({
103
- systemMessage: `
104
- You create markdown readmes for npm projects. You only output the markdown readme.
105
-
106
- IMPORTANT: YOU ARE NOW CREATING THE README FOR THE FOLLOWING SUB MODULE: ${subModule} !!!!!!!!!!!
107
- The Sub Module will be published with the following data:
108
- ${JSON.stringify(await plugins.fsInstance.file(plugins.path.join(paths.cwd, subModule, 'tspublish.json')).encoding('utf8').read(), null, 2)}
109
-
110
-
111
- The Readme should follow the following template:
112
-
113
- # Project Name
114
- [
115
- The name is the module name of package.json
116
- The description is in the description field of package.json
117
- ]
118
-
119
- ## Install
120
- [
121
- Write a short text on how to install the project
122
- ]
123
-
124
- ## Usage
125
- [
126
- Give code examples here.
127
- Construct sensible scenarios for the user.
128
- Make sure to show a complete set of features of the module.
129
- Don't omit use cases.
130
- It does not matter how much time you need.
131
- ALWAYS USE ESM SYNTAX AND TYPESCRIPT.
132
- DON'T CHICKEN OUT. Write at least 4000 words. More if necessary.
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
- const subModuleReadmeString = result.message + '\n' + legalInfo;
150
- await plugins.fsInstance.file(plugins.path.join(paths.cwd, subModule, 'readme.md')).encoding('utf8').write(subModuleReadmeString);
151
- logger.log('success', `Built readme for ${subModule}`);
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
- return result.message;
227
+
228
+ return resultMessage;
154
229
  }
155
230
  }