126 lines
4.6 KiB
TypeScript
126 lines
4.6 KiB
TypeScript
import type { AiDoc } from '../classes.aidoc.js';
|
|
import * as plugins from '../plugins.js';
|
|
import { ProjectContext } from './projectcontext.js';
|
|
import { logger } from '../logging.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() {
|
|
// Use DualAgentOrchestrator with filesystem tool for agent-driven exploration
|
|
const descriptionOrchestrator = new plugins.smartagent.DualAgentOrchestrator({
|
|
smartAiInstance: this.aiDocsRef.smartAiInstance,
|
|
defaultProvider: 'openai',
|
|
maxIterations: 15,
|
|
maxResultChars: 10000, // Limit tool output to prevent token explosion
|
|
maxHistoryMessages: 15, // Limit history window
|
|
logPrefix: '[Description]',
|
|
onProgress: (event) => logger.log(event.logLevel, event.logMessage),
|
|
guardianPolicyPrompt: `
|
|
You validate description generation tool calls and outputs.
|
|
|
|
APPROVE tool calls for:
|
|
- Reading package.json, npmextra.json, or source files in the ts/ directory
|
|
- Listing directory contents to understand project structure
|
|
- Using tree to see project structure
|
|
|
|
REJECT tool calls for:
|
|
- Reading files outside the project directory
|
|
- Writing, deleting, or modifying any files
|
|
- Any destructive operations
|
|
|
|
For final output, 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 final output if:
|
|
- JSON is malformed or wrapped in markdown code blocks
|
|
- Description is too long or vague
|
|
- Keywords are irrelevant or generic
|
|
`,
|
|
});
|
|
|
|
// Register scoped filesystem tool for agent exploration
|
|
descriptionOrchestrator.registerScopedFilesystemTool(this.projectDir);
|
|
|
|
await descriptionOrchestrator.start();
|
|
|
|
const descriptionTaskPrompt = `
|
|
You create a project description and keywords for an npm package.
|
|
|
|
PROJECT DIRECTORY: ${this.projectDir}
|
|
|
|
Use the filesystem tool to explore the project and understand what it does:
|
|
1. First, use tree to see the project structure
|
|
2. Read package.json to understand the package name and current description
|
|
3. Read npmextra.json if it exists for additional metadata
|
|
4. Read key source files in ts/ directory to understand the implementation
|
|
|
|
Then generate a description and keywords based on your exploration.
|
|
|
|
Your FINAL 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.
|
|
`;
|
|
|
|
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 ProjectContext to get file handles for writing
|
|
const projectContext = new ProjectContext(this.projectDir);
|
|
const files = await projectContext.gatherFiles();
|
|
|
|
// Update npmextra.json
|
|
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();
|
|
|
|
// Update package.json
|
|
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;
|
|
}
|
|
}
|