import type { AiDoc } from '../classes.aidoc.js'; import * as plugins from '../plugins.js'; import { ProjectContext } from './projectcontext.js'; interface IDescriptionInterface { description: string; keywords: string[]; } export class Description { // INSTANCE private aiDocsRef: AiDoc; private projectDir: string; constructor(aiDocsRef: AiDoc, projectDirArg: string) { this.aiDocsRef = aiDocsRef; this.projectDir = projectDirArg; } public async build() { // Gather project context upfront to avoid token explosion from filesystem tool const projectContext = new ProjectContext(this.projectDir); const files = await projectContext.gatherFiles(); const contextString = await projectContext.convertFilesToContext([ files.smartfilePackageJSON, files.smartfilesNpmextraJSON, ...files.smartfilesMod.slice(0, 10), // Limit to first 10 source files for description ]); // Use DualAgentOrchestrator for description generation const descriptionOrchestrator = new plugins.smartagent.DualAgentOrchestrator({ smartAiInstance: this.aiDocsRef.smartAiInstance, defaultProvider: 'openai', guardianPolicyPrompt: ` You validate description generation. APPROVE if: - JSON is valid and parseable - Description is a clear, concise one-sentence summary - Keywords are relevant to the project's use cases - Both description and keywords fields are present REJECT if: - JSON is malformed or wrapped in markdown code blocks - Description is too long or vague - Keywords are irrelevant or generic `, }); await descriptionOrchestrator.start(); const descriptionTaskPrompt = ` You create a project description and keywords for an npm package. Analyze the project files provided below to understand the codebase, then generate a description and keywords. Your response must be valid JSON adhering to this interface: { description: string; // a sensible short, one sentence description of the project keywords: string[]; // an array of tags that describe the project based on use cases } Important: Answer only in valid JSON. Your answer should be parseable with JSON.parse() without modifying anything. Don't wrap the JSON in \`\`\`json\`\`\` - just return the raw JSON object. Here are the project files: ${contextString} Generate the description based on these files. `; const descriptionResult = await descriptionOrchestrator.run(descriptionTaskPrompt); await descriptionOrchestrator.stop(); if (!descriptionResult.success) { throw new Error(`Description generation failed: ${descriptionResult.status}`); } console.log(descriptionResult.result); const resultObject: IDescriptionInterface = JSON.parse( descriptionResult.result.replace('```json', '').replace('```', ''), ); // Use the already gathered files for updates const npmextraJson = files.smartfilesNpmextraJSON; const npmextraJsonContent = JSON.parse(npmextraJson.contents.toString()); npmextraJsonContent['@git.zone/cli'].module.description = resultObject.description; npmextraJsonContent['@git.zone/cli'].module.keywords = resultObject.keywords; npmextraJson.contents = Buffer.from(JSON.stringify(npmextraJsonContent, null, 2)); await npmextraJson.write(); // do the same with packageJson const packageJson = files.smartfilePackageJSON; const packageJsonContent = JSON.parse(packageJson.contents.toString()); packageJsonContent.description = resultObject.description; packageJsonContent.keywords = resultObject.keywords; packageJson.contents = Buffer.from(JSON.stringify(packageJsonContent, null, 2)); await packageJson.write(); console.log(`\n======================\n`); console.log(JSON.stringify(resultObject, null, 2)); console.log(`\n======================\n`); return descriptionResult.result; } }