mega-minds
Version:
Enhanced multi-agent workflow system for Claude Code projects with automated handoff management and Claude Code hooks integration
1,060 lines (908 loc) • 38.8 kB
JavaScript
/**
* Template Adapter for Mega-Minds Variable-Driven Agent System
* Bridges Variable Engine with existing agent templates
* Enhances templates with dynamic context and intelligent path resolution
*/
const path = require('path');
const { ContextualVariableEngine } = require('./variable-engine');
const { AgentSectionManager } = require('./section-manager');
const { ProjectContextAnalyzer } = require('./project-context-analyzer');
const { StackProfileManager } = require('./stack-profile-manager');
const fs = require('fs').promises;
class TemplateAdapter {
constructor(projectPath, config = {}) {
this.projectPath = projectPath;
this.config = {
enablePathResolution: config.enablePathResolution !== false,
enableContextEnhancement: config.enableContextEnhancement !== false,
enableStackDetection: config.enableStackDetection !== false,
cacheTimeout: config.cacheTimeout || 60000, // 1 minute
...config
};
this.variableEngine = new ContextualVariableEngine(projectPath, config);
// Use mega-minds package templates directory, not project directory
const megaMindsTemplatesPath = path.join(__dirname, '..', 'templates');
this.sectionManager = new AgentSectionManager(megaMindsTemplatesPath, this.variableEngine);
this.projectAnalyzer = new ProjectContextAnalyzer(projectPath, config);
this.stackProfileManager = new StackProfileManager(config);
this.adaptationCache = new Map();
this.projectAnalysis = null; // Cached project analysis
// Enhanced variables for agent templates
this.templateVariables = {
// Path resolution variables
'{{RULES_PATH}}': 'templates/RULES.md',
'{{QUICKREF_PATH}}': 'templates/QUICKREF.md',
'{{WORKFLOWS_PATH}}': 'workflows/',
'{{EXAMPLES_PATH}}': 'workflows/examples.md',
'{{BOUNDARIES_PATH}}': 'workflows/agent-boundaries.md',
'{{COMMUNICATION_PROTOCOL}}': 'workflows/communication-protocol.md',
'{{QUALITY_GATES_PATH}}': 'workflows/quality-gates.md',
// Agent context variables
'{{AGENT_WORKLOAD}}': 'moderate',
'{{AGENT_PRIORITY}}': 'normal',
'{{QUALITY_STATUS}}': 'pending',
'{{DEPENDENCIES}}': 'none',
'{{COORDINATION_MODE}}': 'collaborative',
// System integration
'{{CLI_AVAILABLE}}': true,
'{{MCP_ENABLED}}': true,
'{{STREAMING_ENABLED}}': true,
'{{PERFORMANCE_MONITORING}}': true
};
}
/**
* Adapt an agent template with enhanced variables and dynamic content
* @param {string} agentName - Name of agent template to adapt
* @param {Object} sessionContext - Current session context
* @param {Object} options - Adaptation options
* @returns {string} Enhanced template content
*/
async adaptAgentTemplate(agentName, sessionContext, options = {}) {
try {
const cacheKey = `${agentName}_${sessionContext.session?.id}_${options.stackProfile || 'auto'}`;
// Check cache first
if (this.adaptationCache.has(cacheKey) && !options.forceRefresh) {
const cached = this.adaptationCache.get(cacheKey);
if (!this.isCacheExpired(cached)) {
console.log(`📋 Using cached template for ${agentName}`);
return cached.content;
}
}
console.log(`🔄 Adapting template for ${agentName} with stack detection...`);
// Analyze project context if not cached or if forced refresh
if (!this.projectAnalysis || options.forceRefresh) {
this.projectAnalysis = await this.analyzeProjectContext(options);
}
// Load base template
const baseTemplate = await this.loadAgentTemplate(agentName);
// Generate stack-aware enhanced variables
const enhancedVariables = await this.generateStackAwareVariables(
agentName,
sessionContext,
this.projectAnalysis,
options
);
// Apply template enhancements
let adaptedTemplate = baseTemplate;
if (this.config.enablePathResolution) {
adaptedTemplate = this.resolveStaticPaths(adaptedTemplate, this.projectAnalysis.structure);
}
if (this.config.enableContextEnhancement) {
adaptedTemplate = this.enhanceWithStackContext(adaptedTemplate, sessionContext, this.projectAnalysis);
}
// Apply variable substitution
adaptedTemplate = this.applyVariableSubstitution(adaptedTemplate, enhancedVariables);
// Add dynamic sections
adaptedTemplate = await this.addStackAwareDynamicSections(adaptedTemplate, agentName, sessionContext, this.projectAnalysis);
// Cache the result
this.cacheAdaptedTemplate(cacheKey, adaptedTemplate);
console.log(`✅ Template adapted for ${agentName} (${this.projectAnalysis.stackProfile?.name || 'Custom Stack'})`);
return adaptedTemplate;
} catch (error) {
console.error(`Failed to adapt template for ${agentName}:`, error.message);
return this.getFallbackTemplate(agentName, sessionContext);
}
}
/**
* Generate enhanced variables combining Variable Engine with template-specific vars
* @param {string} agentName - Agent name
* @param {Object} sessionContext - Session context
* @param {Object} options - Generation options
* @returns {Object} Enhanced variables object
*/
async generateEnhancedVariables(agentName, sessionContext, options) {
// Get base variables from Variable Engine
const baseVariables = await this.variableEngine.generateVariables(
agentName,
'full',
sessionContext
);
// Generate template-specific variables
const templateVars = await this.generateTemplateVariables(agentName, sessionContext);
// Generate dynamic path variables
const pathVars = this.generatePathVariables();
// Generate agent-specific context
const agentVars = await this.generateAgentContextVariables(agentName, sessionContext);
// Combine all variables with precedence
return {
...this.templateVariables, // Base template variables
...pathVars, // Dynamic paths
...baseVariables, // Variable Engine variables
...templateVars, // Template-specific
...agentVars, // Agent context
...options.customVariables // User overrides
};
}
/**
* Analyze project context using ProjectContextAnalyzer
* @param {Object} options - Analysis options
* @returns {Object} Project analysis result
*/
async analyzeProjectContext(options = {}) {
try {
console.log('🔍 Analyzing project context and tech stack...');
const analysis = await this.projectAnalyzer.analyzeProject({
enableDeepAnalysis: options.enableDeepAnalysis !== false,
customProfile: options.stackProfile
});
console.log(`📊 Stack detected: ${analysis.stackProfile?.name || 'Custom'} (${analysis.techStack.confidence} confidence)`);
return analysis;
} catch (error) {
console.error('Project analysis failed:', error.message);
return this.getFallbackAnalysis();
}
}
/**
* Generate stack-aware variables using project analysis
* @param {string} agentName - Agent name
* @param {Object} sessionContext - Session context
* @param {Object} projectAnalysis - Project analysis result
* @param {Object} options - Generation options
* @returns {Object} Stack-aware variables
*/
async generateStackAwareVariables(agentName, sessionContext, projectAnalysis, options = {}) {
// Start with base template variables
const baseVariables = await this.generateEnhancedVariables(agentName, sessionContext, options);
// Get stack-specific variables from project analysis
const stackVariables = projectAnalysis.variables || {};
// Generate agent-specific specializations
const agentSpecializations = this.generateAgentSpecializations(agentName, projectAnalysis);
// Combine all variables with proper precedence
const combinedVariables = {
...baseVariables, // Base template variables
...stackVariables, // Stack profile variables (override base)
...agentSpecializations, // Agent-specific variables
...options.customVariables // User overrides (highest priority)
};
// Add analysis metadata
combinedVariables['{{STACK_PROFILE}}'] = projectAnalysis.stackProfile?.name || 'Custom Stack';
combinedVariables['{{STACK_CONFIDENCE}}'] = projectAnalysis.techStack.confidence;
combinedVariables['{{ANALYSIS_TIMESTAMP}}'] = projectAnalysis.analyzedAt;
return combinedVariables;
}
/**
* Generate agent-specific specializations based on tech stack
* @param {string} agentName - Agent name
* @param {Object} projectAnalysis - Project analysis
* @returns {Object} Agent specialization variables
*/
generateAgentSpecializations(agentName, projectAnalysis) {
const specializations = {};
const stackProfile = projectAnalysis.stackProfile;
const techStack = projectAnalysis.techStack;
// Get predefined specializations from stack profile
if (stackProfile?.agentSpecializations?.[agentName]) {
specializations['{{AGENT_SPECIALIZATION}}'] = stackProfile.agentSpecializations[agentName];
} else {
// Generate dynamic specializations based on detected tech stack
specializations['{{AGENT_SPECIALIZATION}}'] = this.generateDynamicSpecialization(agentName, techStack);
}
// Add tech-specific patterns and best practices
if (agentName === 'frontend-development-agent') {
specializations['{{FRONTEND_PATTERNS}}'] = this.getFrontendPatterns(techStack);
specializations['{{FRONTEND_TOOLS}}'] = this.getFrontendTools(techStack);
} else if (agentName === 'backend-development-agent') {
specializations['{{BACKEND_PATTERNS}}'] = this.getBackendPatterns(techStack);
specializations['{{API_PATTERNS}}'] = this.getApiPatterns(techStack);
} else if (agentName === 'testing-agent') {
specializations['{{TESTING_STRATEGIES}}'] = this.getTestingStrategies(techStack);
specializations['{{TESTING_TOOLS}}'] = this.getTestingTools(techStack);
}
return specializations;
}
/**
* Enhanced path resolution with project structure awareness
* @param {string} template - Template content
* @param {Object} projectStructure - Project structure information
* @returns {string} Template with resolved paths
*/
resolveStaticPaths(template, projectStructure = {}) {
const pathReplacements = {
// Dynamic path replacement based on project structure
'templates/RULES.md': projectStructure.directories?.config ?
`${projectStructure.directories.config}/RULES.md` : '{{RULES_PATH}}',
'templates/QUICKREF.md': '{{QUICKREF_PATH}}',
'workflows/examples.md': '{{EXAMPLES_PATH}}',
'workflows/agent-boundaries.md': '{{BOUNDARIES_PATH}}',
'workflows/communication-protocol.md': '{{COMMUNICATION_PROTOCOL}}',
'workflows/quality-gates.md': '{{QUALITY_GATES_PATH}}',
'../workflows/': '{{WORKFLOWS_PATH}}',
'templates/workflows/': '{{WORKFLOWS_PATH}}',
// Project structure specific
'components/': '{{COMPONENTS_DIR}}/',
'src/components/': '{{COMPONENTS_DIR}}/',
'lib/': '{{UTILS_DIR}}/',
'utils/': '{{UTILS_DIR}}/',
'pages/': '{{FRONTEND_DIR}}/',
'app/': '{{FRONTEND_DIR}}/'
};
let resolved = template;
for (const [staticPath, variable] of Object.entries(pathReplacements)) {
const regex = new RegExp(this.escapeRegExp(staticPath), 'g');
resolved = resolved.replace(regex, variable);
}
return resolved;
}
/**
* Enhanced context enhancement with stack awareness
* @param {string} template - Base template
* @param {Object} sessionContext - Session context
* @param {Object} projectAnalysis - Project analysis
* @returns {string} Enhanced template
*/
enhanceWithStackContext(template, sessionContext, projectAnalysis) {
// Add stack-specific context section if not present
if (!template.includes('## Tech Stack Context')) {
const stackContextSection = this.generateStackContextSection(projectAnalysis);
// Insert after main context section or before last section
const contextIndex = template.indexOf('## Current Context');
if (contextIndex > 0) {
const nextSectionIndex = template.indexOf('##', contextIndex + 1);
if (nextSectionIndex > 0) {
template = template.slice(0, nextSectionIndex) +
stackContextSection + '\n\n' +
template.slice(nextSectionIndex);
} else {
template += '\n\n' + stackContextSection;
}
} else {
// Original context enhancement
template = this.enhanceWithContext(template, sessionContext);
template += '\n\n' + stackContextSection;
}
}
return template;
}
/**
* Generate stack-specific context section
* @param {Object} projectAnalysis - Project analysis
* @returns {string} Stack context section
*/
generateStackContextSection(projectAnalysis) {
const techStack = projectAnalysis.techStack;
const stackProfile = projectAnalysis.stackProfile;
return `## 🏗️ Tech Stack Context
**Stack Profile**: {{STACK_PROFILE}} ({{STACK_CONFIDENCE}} confidence)
**Primary Language**: {{LANGUAGE_PRIMARY}}
**Frontend**: {{FRONTEND_FRAMEWORK}} ${techStack.frameworks.frontendVersion || ''}
**Backend**: {{BACKEND_FRAMEWORK}} ${techStack.frameworks.backendVersion || ''}
**Database**: {{DATABASE_TYPE}} via {{DATABASE_SERVICE}}
**Build Tool**: {{BUILD_TOOL}}
**Testing**: {{TESTING_FRAMEWORK}} + {{E2E_FRAMEWORK}}
**Project Structure**: {{PROJECT_TYPE}}
**File Extensions**: {{FILE_EXTENSION}} (primary)
**Package Manager**: ${this.detectPackageManager(projectAnalysis)}
**Agent Specialization**: {{AGENT_SPECIALIZATION}}`;
}
/**
* Add stack-aware dynamic sections
* @param {string} template - Base template
* @param {string} agentName - Agent name
* @param {Object} sessionContext - Session context
* @param {Object} projectAnalysis - Project analysis
* @returns {string} Template with dynamic sections
*/
async addStackAwareDynamicSections(template, agentName, sessionContext, projectAnalysis) {
// Add stack-specific best practices section
if (!template.includes('## Stack-Specific Patterns')) {
const patternsSection = await this.generateStackPatternsSection(agentName, projectAnalysis);
template += '\n\n' + patternsSection;
}
// Add integration recommendations
if (!template.includes('## Integration Recommendations')) {
const integrationSection = this.generateIntegrationRecommendations(agentName, projectAnalysis);
template += '\n\n' + integrationSection;
}
// Original dynamic sections
template = await this.addDynamicSections(template, agentName, sessionContext);
return template;
}
/**
* Generate dynamic path variables based on project structure
* @returns {Object} Path variables
*/
generatePathVariables() {
const baseDir = this.projectPath;
return {
'{{RULES_PATH}}': this.resolvePath('templates/RULES.md'),
'{{QUICKREF_PATH}}': this.resolvePath('templates/QUICKREF.md'),
'{{WORKFLOWS_PATH}}': this.resolvePath('workflows/'),
'{{EXAMPLES_PATH}}': this.resolvePath('workflows/examples.md'),
'{{BOUNDARIES_PATH}}': this.resolvePath('workflows/agent-boundaries.md'),
'{{COMMUNICATION_PROTOCOL}}': this.resolvePath('workflows/communication-protocol.md'),
'{{QUALITY_GATES_PATH}}': this.resolvePath('workflows/quality-gates.md'),
'{{TEMPLATE_DIR}}': this.resolvePath('templates/'),
'{{LIB_DIR}}': this.resolvePath('lib/'),
'{{PROJECT_ROOT}}': baseDir
};
}
/**
* Generate agent-specific context variables
* @param {string} agentName - Agent name
* @param {Object} sessionContext - Session context
* @returns {Object} Agent context variables
*/
async generateAgentContextVariables(agentName, sessionContext) {
const agentType = this.determineAgentType(agentName);
const workload = await this.calculateAgentWorkload(agentName, sessionContext);
const qualityStatus = await this.getQualityStatus(agentName, sessionContext);
return {
'{{AGENT_TYPE}}': agentType,
'{{AGENT_WORKLOAD}}': workload,
'{{AGENT_PRIORITY}}': this.determineAgentPriority(agentName, sessionContext),
'{{QUALITY_STATUS}}': qualityStatus,
'{{DEPENDENCIES}}': await this.getAgentDependencies(agentName),
'{{COORDINATION_MODE}}': this.getCoordinationMode(sessionContext),
'{{SPECIALIZATION}}': this.getAgentSpecialization(agentName),
'{{RECOMMENDED_HANDOFFS}}': await this.getRecommendedHandoffs(agentName)
};
}
/**
* Generate template-specific variables
* @param {string} agentName - Agent name
* @param {Object} sessionContext - Session context
* @returns {Object} Template variables
*/
async generateTemplateVariables(agentName, sessionContext) {
return {
'{{TEMPLATE_VERSION}}': '2.1.0',
'{{ADAPTATION_TIME}}': new Date().toISOString(),
'{{CONTEXT_ID}}': sessionContext.session?.id || 'unknown',
'{{VARIABLE_ENGINE_VERSION}}': '2.1.0',
'{{MCP_STATUS}}': 'active',
'{{CACHE_STATUS}}': 'enabled'
};
}
/**
* Replace static file paths with dynamic variables
* @param {string} template - Template content
* @returns {string} Template with resolved paths
*/
resolveStaticPaths(template) {
const pathReplacements = {
'templates/RULES.md': '{{RULES_PATH}}',
'templates/QUICKREF.md': '{{QUICKREF_PATH}}',
'workflows/examples.md': '{{EXAMPLES_PATH}}',
'workflows/agent-boundaries.md': '{{BOUNDARIES_PATH}}',
'workflows/communication-protocol.md': '{{COMMUNICATION_PROTOCOL}}',
'workflows/quality-gates.md': '{{QUALITY_GATES_PATH}}',
'../workflows/': '{{WORKFLOWS_PATH}}',
'templates/workflows/': '{{WORKFLOWS_PATH}}'
};
let resolved = template;
for (const [staticPath, variable] of Object.entries(pathReplacements)) {
const regex = new RegExp(this.escapeRegExp(staticPath), 'g');
resolved = resolved.replace(regex, variable);
}
return resolved;
}
/**
* Enhance template with contextual information
* @param {string} template - Base template
* @param {Object} sessionContext - Session context
* @returns {string} Enhanced template
*/
enhanceWithContext(template, sessionContext) {
// Add dynamic context section if not present
if (!template.includes('## Current Context')) {
const contextSection = this.generateContextSection(sessionContext);
// Insert before the last section (usually "Example Workflow")
const lastSectionIndex = template.lastIndexOf('## ');
if (lastSectionIndex > 0) {
template = template.slice(0, lastSectionIndex) +
contextSection + '\n\n' +
template.slice(lastSectionIndex);
} else {
template += '\n\n' + contextSection;
}
}
return template;
}
/**
* Generate dynamic context section
* @param {Object} sessionContext - Session context
* @returns {string} Context section content
*/
generateContextSection(sessionContext) {
return `## 📊 Current Context
**Session**: {{SESSION_ID}}
**Memory Status**: {{MEMORY_STATUS}} ({{MEMORY_PRESSURE_LEVEL}})
**Active Agents**: {{ACTIVE_AGENT_COUNT}}/{{CONCURRENT_LIMIT}}
**System Health**: {{SYSTEM_HEALTH_STATUS}}
**Quality Status**: {{QUALITY_STATUS}}
**Agent Workload**: {{AGENT_WORKLOAD}}
**Coordination**: {{COORDINATION_MODE}} mode
**Performance**:
- Load Time: {{SECTION_LOAD_TIME}}ms
- Cache Hit Rate: {{CACHE_HIT_RATE}}%
- Optimization Score: {{OPTIMIZATION_SCORE}}/10`;
}
/**
* Apply variable substitution to template
* @param {string} template - Template content
* @param {Object} variables - Variables to substitute
* @returns {string} Template with variables substituted
*/
applyVariableSubstitution(template, variables) {
let result = template;
for (const [key, value] of Object.entries(variables)) {
const regex = new RegExp(this.escapeRegExp(key), 'g');
result = result.replace(regex, this.formatVariableValue(value));
}
return result;
}
/**
* Add dynamic sections to template
* @param {string} template - Base template
* @param {string} agentName - Agent name
* @param {Object} sessionContext - Session context
* @returns {string} Template with dynamic sections
*/
async addDynamicSections(template, agentName, sessionContext) {
// Add performance monitoring section if not present
if (!template.includes('## Performance Monitoring')) {
const perfSection = await this.generatePerformanceSection(agentName, sessionContext);
template += '\n\n' + perfSection;
}
// Add integration status section
if (!template.includes('## System Integration')) {
const integrationSection = this.generateIntegrationSection();
template += '\n\n' + integrationSection;
}
return template;
}
/**
* Generate performance monitoring section
* @param {string} agentName - Agent name
* @param {Object} sessionContext - Session context
* @returns {string} Performance section
*/
async generatePerformanceSection(agentName, sessionContext) {
return `## 📊 Performance Monitoring
**Template Adaptation**: {{ADAPTATION_TIME}}
**Variable Engine**: {{VARIABLE_ENGINE_VERSION}}
**MCP Status**: {{MCP_STATUS}}
**Cache**: {{CACHE_STATUS}}
**Real-Time Metrics**:
- Context Generation: <50ms target
- Section Loading: <100ms target
- Memory Efficiency: {{CONTEXT_USAGE}}%
- Agent Coordination: {{COORDINATION_SUCCESS_RATE}}%`;
}
/**
* Generate integration status section
* @returns {string} Integration section
*/
generateIntegrationSection() {
return `## 🔗 System Integration Status
**CLI Integration**: {{CLI_AVAILABLE}}
**MCP Protocol**: {{MCP_ENABLED}}
**Streaming Updates**: {{STREAMING_ENABLED}}
**Performance Monitor**: {{PERFORMANCE_MONITORING}}
**Available Commands**:
- \`npx mega-minds variable-status\` - Check variable state
- \`npx mega-minds performance-metrics\` - View performance data
- \`npx mega-minds cache-status\` - Cache statistics`;
}
// Helper methods
async loadAgentTemplate(agentName) {
return await this.sectionManager.templateLoader.loadAgentTemplate(agentName);
}
resolvePath(relativePath) {
return path.join(this.projectPath, relativePath);
}
determineAgentType(agentName) {
const typeMap = {
'project-orchestrator': 'coordination',
'frontend-development': 'implementation',
'backend-development': 'implementation',
'database': 'infrastructure',
'testing': 'validation',
'security': 'validation',
'devops': 'infrastructure'
};
for (const [key, type] of Object.entries(typeMap)) {
if (agentName.includes(key)) {
return type;
}
}
return 'specialized';
}
async calculateAgentWorkload(agentName, sessionContext) {
const activeAgents = sessionContext.activeAgents?.count || 0;
const memoryPressure = sessionContext.memory?.pressure || 'normal';
if (memoryPressure === 'critical') return 'light';
if (activeAgents >= 2) return 'shared';
return 'moderate';
}
determineAgentPriority(agentName, sessionContext) {
if (agentName.includes('orchestrator')) return 'high';
if (agentName.includes('security') || agentName.includes('testing')) return 'high';
return 'normal';
}
async getQualityStatus(agentName, sessionContext) {
// This would integrate with actual quality gates
return 'monitoring';
}
async getAgentDependencies(agentName) {
const dependencyMap = {
'frontend-development-agent': 'backend-development-agent',
'testing-agent': 'implementation-complete',
'security-testing-agent': 'testing-agent',
'deployment-agent': 'all-validation-complete'
};
return dependencyMap[agentName] || 'none';
}
getCoordinationMode(sessionContext) {
const activeCount = sessionContext.activeAgents?.count || 0;
return activeCount > 1 ? 'collaborative' : 'focused';
}
getAgentSpecialization(agentName) {
const specializations = {
'project-orchestrator': 'Multi-agent coordination and project management',
'frontend-development': 'User interface and client-side development',
'backend-development': 'Server-side logic and API development',
'database': 'Data modeling and database optimization',
'testing': 'Quality assurance and automated testing',
'security': 'Security analysis and vulnerability assessment'
};
for (const [key, spec] of Object.entries(specializations)) {
if (agentName.includes(key)) {
return spec;
}
}
return 'Domain-specific development tasks';
}
async getRecommendedHandoffs(agentName) {
const handoffMap = {
'project-orchestrator-agent': 'requirements → architecture → implementation',
'requirements-analysis-agent': 'technical-architecture-agent',
'frontend-development-agent': 'testing-agent → security-testing-agent',
'backend-development-agent': 'database-agent → testing-agent',
'testing-agent': 'security-testing-agent → deployment-agent'
};
return handoffMap[agentName] || 'project-orchestrator-agent';
}
formatVariableValue(value) {
if (value === null || value === undefined) return '';
if (Array.isArray(value)) return value.join(', ');
if (typeof value === 'object') return JSON.stringify(value, null, 2);
return String(value);
}
escapeRegExp(string) {
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
}
cacheAdaptedTemplate(key, content) {
this.adaptationCache.set(key, {
content: content,
timestamp: Date.now()
});
// Cleanup old entries
if (this.adaptationCache.size > 50) {
const oldestKey = this.adaptationCache.keys().next().value;
this.adaptationCache.delete(oldestKey);
}
}
isCacheExpired(cached) {
return (Date.now() - cached.timestamp) > this.config.cacheTimeout;
}
getFallbackTemplate(agentName, sessionContext) {
return `## ${agentName}
**Status**: Fallback mode - enhanced template unavailable
**Basic Coordination**:
- Use Task tool for all agent interactions
- Follow standard handoff protocols
- Check memory status before activation
**Session Context**: {{SESSION_ID}}
**Memory Status**: {{MEMORY_STATUS}}
*Enhanced template features degraded - using basic functionality*`;
}
/**
* Validate enhanced template
* @param {string} agentName - Agent name
* @returns {Object} Validation results
*/
async validateEnhancedTemplate(agentName) {
const validation = {
hasVariables: false,
hasDynamicSections: false,
hasPathResolution: false,
errors: []
};
try {
const template = await this.adaptAgentTemplate(agentName, {
session: { id: 'validation-test' },
memory: { pressure: 'normal' },
activeAgents: { count: 1 }
});
validation.hasVariables = template.includes('{{') && template.includes('}}');
validation.hasDynamicSections = template.includes('## Current Context');
validation.hasPathResolution = template.includes('{{RULES_PATH}}');
} catch (error) {
validation.errors.push(`Validation error: ${error.message}`);
}
return validation;
}
/**
* Get adaptation statistics
* @returns {Object} Adapter statistics
*/
getAdapterStats() {
return {
cacheSize: this.adaptationCache.size,
cacheTimeout: this.config.cacheTimeout,
pathResolutionEnabled: this.config.enablePathResolution,
contextEnhancementEnabled: this.config.enableContextEnhancement,
templateVariableCount: Object.keys(this.templateVariables).length
};
}
// Helper methods for stack-aware functionality
/**
* Generate dynamic specialization for agent based on tech stack
* @param {string} agentName - Agent name
* @param {Object} techStack - Technology stack
* @returns {string} Dynamic specialization description
*/
generateDynamicSpecialization(agentName, techStack) {
const language = techStack.languages[0] || 'JavaScript';
const frontend = techStack.frameworks.frontend || 'React';
const backend = techStack.frameworks.backend || 'Express';
const specializationMap = {
'frontend-development-agent': `${frontend} development with ${language}, modern component patterns and best practices`,
'backend-development-agent': `${backend} server development with ${language}, API design and business logic`,
'database-agent': `${techStack.databases[0] || 'PostgreSQL'} database design, optimization and integration`,
'testing-agent': `${techStack.frameworks.testing || 'Jest'} testing strategies and quality assurance`,
'project-orchestrator-agent': `Multi-agent coordination for ${frontend}/${backend} stack development`
};
return specializationMap[agentName] || `${language} development with modern practices and patterns`;
}
/**
* Get frontend patterns for tech stack
* @param {Object} techStack - Technology stack
* @returns {string} Frontend patterns description
*/
getFrontendPatterns(techStack) {
const frontend = techStack.frameworks.frontend || 'React';
const patternMap = {
'React': 'Hooks, Context API, component composition, custom hooks',
'Vue': 'Composition API, composables, reactive patterns, template refs',
'Angular': 'Services, dependency injection, RxJS, component lifecycle',
'Svelte': 'Stores, reactivity, component communication, actions'
};
return patternMap[frontend] || 'Modern component patterns and state management';
}
/**
* Get frontend tools for tech stack
* @param {Object} techStack - Technology stack
* @returns {string} Frontend tools description
*/
getFrontendTools(techStack) {
const tools = [];
if (techStack.frameworks.css) tools.push(techStack.frameworks.css);
if (techStack.frameworks.stateManagement) tools.push(techStack.frameworks.stateManagement);
if (techStack.frameworks.buildTool) tools.push(techStack.frameworks.buildTool);
if (techStack.frameworks.testing) tools.push(techStack.frameworks.testing);
return tools.length > 0 ? tools.join(', ') : 'Modern frontend toolchain';
}
/**
* Get backend patterns for tech stack
* @param {Object} techStack - Technology stack
* @returns {string} Backend patterns description
*/
getBackendPatterns(techStack) {
const backend = techStack.frameworks.backend || 'Express';
const patternMap = {
'Express': 'Middleware, routing, error handling, async/await patterns',
'Django': 'Models, views, templates, ORM patterns, middleware',
'FastAPI': 'Async/await, dependency injection, Pydantic models, automatic docs',
'Spring Boot': 'Dependency injection, annotations, Spring Data, REST controllers',
'Next.js': 'API routes, server actions, middleware, edge functions'
};
return patternMap[backend] || 'Modern server-side architecture patterns';
}
/**
* Get API patterns for tech stack
* @param {Object} techStack - Technology stack
* @returns {string} API patterns description
*/
getApiPatterns(techStack) {
const backend = techStack.frameworks.backend || 'Express';
if (backend.includes('GraphQL')) return 'GraphQL schemas, resolvers, subscriptions';
if (backend === 'FastAPI') return 'OpenAPI/Swagger, async endpoints, dependency injection';
if (backend === 'Django') return 'Django REST Framework, serializers, viewsets';
return 'RESTful APIs, proper HTTP semantics, error handling';
}
/**
* Get testing strategies for tech stack
* @param {Object} techStack - Technology stack
* @returns {string} Testing strategies description
*/
getTestingStrategies(techStack) {
const testing = techStack.frameworks.testing || 'Jest';
const e2e = techStack.frameworks.e2e || 'Playwright';
return `${testing} unit testing, ${e2e} E2E testing, test-driven development`;
}
/**
* Get testing tools for tech stack
* @param {Object} techStack - Technology stack
* @returns {string} Testing tools description
*/
getTestingTools(techStack) {
const tools = [];
if (techStack.frameworks.testing) tools.push(techStack.frameworks.testing);
if (techStack.frameworks.e2e) tools.push(techStack.frameworks.e2e);
if (techStack.languages.includes('TypeScript')) tools.push('TypeScript testing utilities');
return tools.length > 0 ? tools.join(', ') : 'Modern testing framework';
}
/**
* Generate stack-specific patterns section
* @param {string} agentName - Agent name
* @param {Object} projectAnalysis - Project analysis
* @returns {string} Stack patterns section
*/
async generateStackPatternsSection(agentName, projectAnalysis) {
const techStack = projectAnalysis.techStack;
const language = techStack.languages[0] || 'JavaScript';
return `## 🏗️ Stack-Specific Patterns & Best Practices
**${language} Best Practices:**
- Follow ${language} coding standards and conventions
- Use modern language features and patterns
- Implement proper error handling and logging
**Framework Patterns:**
{{FRONTEND_PATTERNS}}
{{BACKEND_PATTERNS}}
{{TESTING_STRATEGIES}}
**Architecture Guidelines:**
- Follow {{PROJECT_TYPE}} project structure
- Use {{FILE_EXTENSION}} file extensions consistently
- Organize code in {{COMPONENTS_DIR}}, {{UTILS_DIR}}, {{TESTS_DIR}}
**Performance Considerations:**
- Optimize for {{BUILD_TOOL}} build process
- Follow {{FRONTEND_FRAMEWORK}} performance patterns
- Implement caching strategies appropriate for {{BACKEND_FRAMEWORK}}`;
}
/**
* Generate integration recommendations
* @param {string} agentName - Agent name
* @param {Object} projectAnalysis - Project analysis
* @returns {string} Integration recommendations section
*/
generateIntegrationRecommendations(agentName, projectAnalysis) {
const stackProfile = projectAnalysis.stackProfile;
const techStack = projectAnalysis.techStack;
return `## 🔗 Integration Recommendations
**Recommended Agent Handoffs:**
{{HANDOFF_PATTERN}}
**Stack Integration Points:**
- **Frontend ↔ Backend**: ${this.getIntegrationPattern(techStack)}
- **Database Integration**: Use {{ORM_TOOL}} for data layer
- **Testing Integration**: {{TESTING_FRAMEWORK}} + {{E2E_FRAMEWORK}} pipeline
- **Deployment**: Optimize for {{DEPLOYMENT_TARGET}} platform
**Quality Gates:**
- Maintain {{TEST_COVERAGE_MIN}}% minimum test coverage
- Ensure {{CRITICAL_COVERAGE}}% coverage for business logic
- Follow {{ACCESSIBILITY_LEVEL}} accessibility standards
- Meet performance budget: {{PERFORMANCE_BUDGET}}`;
}
/**
* Get integration pattern for tech stack
* @param {Object} techStack - Technology stack
* @returns {string} Integration pattern description
*/
getIntegrationPattern(techStack) {
const frontend = techStack.frameworks.frontend;
const backend = techStack.frameworks.backend;
if (frontend === 'React' && backend === 'Next.js') return 'Next.js API routes with React components';
if (frontend === 'Vue' && backend === 'Nuxt') return 'Nuxt server API with Vue components';
if (backend === 'Django') return 'Django REST API with SPA frontend';
if (backend === 'FastAPI') return 'FastAPI with async endpoints';
return 'RESTful API with modern SPA frontend';
}
/**
* Detect package manager from project analysis
* @param {Object} projectAnalysis - Project analysis
* @returns {string} Package manager name
*/
detectPackageManager(projectAnalysis) {
// This would check for yarn.lock, pnpm-lock.yaml, etc.
return 'npm'; // Default fallback
}
/**
* Get fallback analysis for error cases
* @returns {Object} Fallback analysis
*/
getFallbackAnalysis() {
return {
techStack: {
languages: ['JavaScript'],
frameworks: { frontend: 'React', backend: 'Express' },
databases: ['PostgreSQL'],
confidence: 'low'
},
structure: { type: 'unknown', directories: {} },
variables: {
'{{LANGUAGE_PRIMARY}}': 'JavaScript',
'{{FRONTEND_FRAMEWORK}}': 'React',
'{{BACKEND_FRAMEWORK}}': 'Express',
'{{STACK_PROFILE}}': 'Fallback Stack'
},
stackProfile: {
name: 'Fallback Stack',
variables: {}
}
};
}
/**
* Get project context summary for CLI display
* @returns {Object} Project context summary
*/
async getProjectSummary() {
try {
if (!this.projectAnalysis) {
this.projectAnalysis = await this.analyzeProjectContext();
}
return {
projectName: this.projectAnalysis.metadata?.name,
stackProfile: this.projectAnalysis.stackProfile?.name || 'Custom Stack',
primaryLanguage: this.projectAnalysis.techStack.languages[0],
confidence: this.projectAnalysis.techStack.confidence,
variableCount: Object.keys(this.projectAnalysis.variables || {}).length,
lastAnalyzed: this.projectAnalysis.analyzedAt
};
} catch (error) {
return {
error: error.message,
status: 'analysis-failed'
};
}
}
/**
* Force refresh of project analysis
* @returns {Object} Fresh project analysis
*/
async refreshProjectAnalysis() {
this.projectAnalysis = null;
this.clearCache();
return await this.analyzeProjectContext({ forceRefresh: true });
}
/**
* Set stack profile for template adaptation
* @param {Object} stackProfile - Stack profile to use
*/
setStackProfile(stackProfile) {
if (this.stackProfileManager && stackProfile) {
this.stackProfileManager.setProfile(stackProfile);
// Clear caches to force re-adaptation with new profile
this.clearCache();
}
}
/**
* Clear adaptation cache
*/
clearCache() {
this.adaptationCache.clear();
this.sectionManager.clearCache();
this.projectAnalysis = null; // Clear cached analysis
}
}
module.exports = { TemplateAdapter };