UNPKG

sf-agent-framework

Version:

AI Agent Orchestration Framework for Salesforce Development - Two-phase architecture with 70% context reduction

423 lines (363 loc) • 12.6 kB
#!/usr/bin/env node /** * Template Converter - Converts v1 templates to v2 enhanced format * Part of SF-Agent Framework v4.0 * * Features: * - Automatic LLM instruction generation * - Variable extraction and typing * - Processor attachment * - Validation rules creation */ const fs = require('fs'); const path = require('path'); const yaml = require('js-yaml'); class TemplateConverter { constructor() { this.stats = { processed: 0, converted: 0, skipped: 0, errors: 0, }; } /** * Convert a v1 template to v2 enhanced format */ convertTemplate(inputPath, outputPath) { try { console.log(`Converting: ${path.basename(inputPath)}`); // Read the v1 template const content = fs.readFileSync(inputPath, 'utf8'); const isYaml = inputPath.endsWith('.yaml') || inputPath.endsWith('.yml'); let v1Template; if (isYaml) { v1Template = yaml.load(content); } else { // Parse markdown template v1Template = this.parseMarkdownTemplate(content); } // Convert to v2 format const v2Template = this.transformToV2(v1Template, inputPath); // Write the v2 template const outputContent = yaml.dump(v2Template, { indent: 2, lineWidth: 120, noRefs: true, }); fs.writeFileSync(outputPath, outputContent); this.stats.converted++; console.log(`āœ… Converted successfully: ${path.basename(outputPath)}`); return true; } catch (error) { console.error(`āŒ Error converting ${inputPath}: ${error.message}`); this.stats.errors++; return false; } } /** * Parse a markdown template into structured format */ parseMarkdownTemplate(content) { const template = { title: '', description: '', sections: [], variables: [], }; // Extract title const titleMatch = content.match(/^#\s+(.+)$/m); if (titleMatch) { template.title = titleMatch[1].replace(' Template', ''); } // Extract description const descMatch = content.match(/^(.+?)(?=\n##)/s); if (descMatch) { template.description = descMatch[1].replace(/^#.+\n/, '').trim(); } // Extract variables ({{variable}}) const varMatches = content.matchAll(/\{\{(\w+)\}\}/g); const variables = new Set(); for (const match of varMatches) { variables.add(match[1]); } template.variables = Array.from(variables); // Extract sections const sectionMatches = content.matchAll(/^##\s+(.+)$([\s\S]*?)(?=^##\s+|\Z)/gm); for (const match of sectionMatches) { template.sections.push({ title: match[1], content: match[2].trim(), }); } return template; } /** * Transform v1 template to v2 enhanced format */ transformToV2(v1Template, inputPath) { const baseName = path.basename(inputPath, path.extname(inputPath)); const enhancedName = baseName.replace('-tmpl', '').replace('_tmpl', '') + '-enhanced'; const v2Template = { title: `${v1Template.title} Enhanced`, version: '2.0', type: 'enhanced', description: v1Template.description || `Enhanced version of ${v1Template.title}`, // Generate LLM instructions based on template type instruction: this.generateLLMInstruction(v1Template, baseName), // Convert variables to typed format variables: this.generateVariables(v1Template), // Generate enhanced content content: this.generateEnhancedContent(v1Template), // Add processors processors: this.generateProcessors(baseName), // Output configuration output: { format: 'markdown', filename: `{{projectName}}-${baseName}.md`, additionalFiles: this.generateAdditionalFiles(baseName), }, }; return v2Template; } /** * Generate LLM instructions based on template type */ generateLLMInstruction(template, templateName) { const domainMap = { apex: 'Apex development and Salesforce programming', lwc: 'Lightning Web Components and modern UI development', flow: 'Salesforce Flow automation and process design', integration: 'System integration and API design', security: 'Security architecture and compliance', data: 'Data modeling and migration', test: 'Testing strategies and quality assurance', deployment: 'Release management and deployment', architecture: 'Solution architecture and technical design', }; // Determine domain from template name let domain = 'general Salesforce development'; for (const [key, value] of Object.entries(domainMap)) { if (templateName.toLowerCase().includes(key)) { domain = value; break; } } return `| [[LLM: You are an expert in ${domain}. Your task is to: 1. Analyze the requirements and generate optimal solutions 2. Apply best practices and design patterns 3. Identify potential issues and provide recommendations 4. Create comprehensive documentation 5. Generate test scenarios and validation criteria Focus on: - Technical accuracy and completeness - Performance optimization - Security considerations - Maintainability and scalability - User experience and adoption]]`; } /** * Generate typed variables from v1 template */ generateVariables(template) { const variables = []; const commonVars = { projectName: { type: 'string', required: true, description: 'Project name' }, projectType: { type: 'enum', values: ['new', 'enhancement', 'migration'], default: 'new' }, environment: { type: 'enum', values: ['dev', 'test', 'uat', 'prod'], default: 'dev' }, complexity: { type: 'enum', values: ['simple', 'moderate', 'complex'], default: 'moderate' }, userName: { type: 'string', required: false, description: 'User full name' }, date: { type: 'date', required: false, default: 'today' }, }; // Process template variables if (template.variables && Array.isArray(template.variables)) { template.variables.forEach((varName) => { if (commonVars[varName]) { variables.push({ name: varName, ...commonVars[varName], }); } else { // Generate default variable definition variables.push({ name: varName, type: 'string', required: false, description: `${varName.replace(/([A-Z])/g, ' $1').toLowerCase()}`, }); } }); } // Ensure projectName is always included if (!variables.find((v) => v.name === 'projectName')) { variables.unshift({ name: 'projectName', type: 'string', required: true, description: 'Project name', }); } return variables; } /** * Generate enhanced content with LLM directives */ generateEnhancedContent(template) { let content = '|'; // Add title content += '\n # {{projectName}}'; content += '\n '; content += '\n [[LLM: Generate an executive summary based on the project context]]'; content += '\n '; // Process sections if (template.sections && Array.isArray(template.sections)) { template.sections.forEach((section) => { content += `\n ## ${section.title}`; content += '\n '; // Add LLM enhancement for specific sections if (section.title.toLowerCase().includes('requirement')) { content += '\n [[LLM: Analyze requirements and identify gaps, risks, and dependencies]]'; } else if (section.title.toLowerCase().includes('design')) { content += '\n [[LLM: Generate design recommendations based on best practices]]'; } else if (section.title.toLowerCase().includes('test')) { content += '\n [[LLM: Create comprehensive test scenarios with expected results]]'; } else if (section.title.toLowerCase().includes('security')) { content += '\n [[LLM: Perform security analysis and provide recommendations]]'; } else { content += `\n [[LLM: Enhance this section with relevant insights and recommendations]]`; } content += '\n '; // Include original content if exists if (section.content) { content += '\n ' + section.content.replace(/\n/g, '\n '); } content += '\n '; }); } // Add recommendations section content += '\n ## Recommendations'; content += '\n '; content += '\n [[LLM: Based on the analysis, provide:'; content += '\n 1. Immediate action items'; content += '\n 2. Best practices to implement'; content += '\n 3. Potential risks to mitigate'; content += '\n 4. Future enhancements to consider]]'; return content; } /** * Generate processors based on template type */ generateProcessors(templateName) { const processors = []; // Add validation processor processors.push({ type: 'validation', function: `validate${this.toPascalCase(templateName)}`, }); // Add specific processors based on type if (templateName.includes('test')) { processors.push({ type: 'generation', function: 'generateTestCases', }); } else if (templateName.includes('security')) { processors.push({ type: 'analysis', function: 'performSecurityAnalysis', }); } else if (templateName.includes('integration')) { processors.push({ type: 'generation', function: 'generateAPISpec', }); } return processors; } /** * Generate additional output files */ generateAdditionalFiles(templateName) { const files = []; if (templateName.includes('test')) { files.push({ testCases: '{{projectName}}-test-cases.xlsx' }); } if (templateName.includes('deployment')) { files.push({ checklist: '{{projectName}}-deployment-checklist.pdf' }); } if (templateName.includes('architecture')) { files.push({ diagram: '{{projectName}}-architecture.svg' }); } return files; } /** * Convert string to PascalCase */ toPascalCase(str) { return str .replace(/[-_]/g, ' ') .replace(/\w\S*/g, (txt) => txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase()) .replace(/\s/g, ''); } /** * Convert all templates in a directory */ convertDirectory(inputDir, outputDir) { console.log('šŸ”„ Starting template conversion...\n'); // Create output directory if it doesn't exist if (!fs.existsSync(outputDir)) { fs.mkdirSync(outputDir, { recursive: true }); } // Get all template files const files = fs .readdirSync(inputDir) .filter( (file) => (file.endsWith('.yaml') || file.endsWith('.yml') || file.endsWith('.md')) && !file.includes('-enhanced') ); // Process each file files.forEach((file) => { this.stats.processed++; const inputPath = path.join(inputDir, file); const baseName = path.basename(file, path.extname(file)); const outputName = baseName.replace('-tmpl', '').replace('_tmpl', '') + '-enhanced.yaml'; const outputPath = path.join(outputDir, outputName); // Skip if already exists if (fs.existsSync(outputPath)) { console.log(`ā­ļø Skipping ${file} (already exists)`); this.stats.skipped++; } else { this.convertTemplate(inputPath, outputPath); } }); // Print summary console.log('\nšŸ“Š Conversion Summary:'); console.log(` Processed: ${this.stats.processed}`); console.log(` Converted: ${this.stats.converted}`); console.log(` Skipped: ${this.stats.skipped}`); console.log(` Errors: ${this.stats.errors}`); console.log( ` Success Rate: ${Math.round((this.stats.converted / this.stats.processed) * 100)}%` ); } } // CLI interface if (require.main === module) { const args = process.argv.slice(2); if (args.length < 2) { console.log('Usage: node template-converter.js <input> <output>'); console.log(' input: Template file or directory'); console.log(' output: Output file or directory'); process.exit(1); } const converter = new TemplateConverter(); const inputPath = path.resolve(args[0]); const outputPath = path.resolve(args[1]); if (fs.statSync(inputPath).isDirectory()) { converter.convertDirectory(inputPath, outputPath); } else { converter.convertTemplate(inputPath, outputPath); } } module.exports = TemplateConverter;