UNPKG

sf-agent-framework

Version:

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

331 lines (298 loc) 10.7 kB
/** * Persona Engine for SF-Agent Framework * Dynamically generates consistent character responses based on agent definitions */ class PersonaEngine { constructor() { this.personas = new Map(); this.personalityTraits = { methodical: { greetingStyle: 'Hello', workStyle: 'Carefully working', completionStyle: 'Successfully completed', problemStyle: 'Encountered an issue', progressPhrases: [ 'Methodically progressing through', 'Systematically handling', 'Carefully reviewing', ], }, enthusiastic: { greetingStyle: 'Hi there!', workStyle: 'Diving into', completionStyle: 'Awesome! Finished', problemStyle: 'Hit a snag', progressPhrases: [ 'Making great progress on', 'Excited to be working on', 'Really getting into', ], }, professional: { greetingStyle: 'Good day', workStyle: 'Currently executing', completionStyle: 'Task completed', problemStyle: 'Issue identified', progressPhrases: ['Proceeding with', 'Executing', 'Implementing'], }, analytical: { greetingStyle: 'Greetings', workStyle: 'Analyzing and processing', completionStyle: 'Analysis complete', problemStyle: 'Anomaly detected', progressPhrases: ['Analyzing', 'Evaluating', 'Assessing'], }, creative: { greetingStyle: 'Hey!', workStyle: 'Crafting', completionStyle: 'Created something great!', problemStyle: 'Need to rethink this', progressPhrases: ['Designing', 'Innovating on', 'Creating'], }, }; // Role-based personality mappings this.rolePersonalityMap = { admin: 'methodical', developer: 'analytical', architect: 'professional', qa: 'methodical', devops: 'analytical', 'business-analyst': 'professional', 'product-owner': 'enthusiastic', security: 'methodical', data: 'analytical', ux: 'creative', }; } /** * Initialize persona engine with default personas */ async initialize() { // Load any custom persona configurations if they exist // This could be extended to load from YAML files return true; } /** * Generate a persona from an agent configuration */ async generatePersona(agentConfig) { const agentId = agentConfig.agent?.id || 'unknown'; // Check if persona already exists if (this.personas.has(agentId)) { return this.personas.get(agentId); } // Extract role from agent config const role = this.extractRole(agentConfig); const personalityType = this.determinePersonality(agentConfig, role); const personality = this.personalityTraits[personalityType]; // Generate persona based on agent config const persona = { name: agentConfig.persona?.name || agentConfig.agent?.name || this.generateName(role), role: agentConfig.agent?.title || role, personality: personalityType, traits: personality, expertise: this.extractExpertise(agentConfig), workStyle: this.generateWorkStyle(personalityType, role), communicationStyle: this.generateCommunicationStyle(personalityType), // Add custom behaviors from agent config customBehaviors: agentConfig.agent?.customization?.interaction_style || {}, }; // Cache the persona this.personas.set(agentId, persona); return persona; } /** * Extract role from agent configuration */ extractRole(agentConfig) { // Try to extract from various fields const title = agentConfig.agent?.title || ''; const id = agentConfig.agent?.id || ''; const category = agentConfig.meta?.category || ''; // Extract role from title or ID if (title.toLowerCase().includes('admin')) return 'admin'; if (title.toLowerCase().includes('developer')) return 'developer'; if (title.toLowerCase().includes('architect')) return 'architect'; if (title.toLowerCase().includes('qa') || title.toLowerCase().includes('quality')) return 'qa'; if (title.toLowerCase().includes('devops')) return 'devops'; if (title.toLowerCase().includes('analyst')) return 'business-analyst'; if (title.toLowerCase().includes('product')) return 'product-owner'; if (title.toLowerCase().includes('security')) return 'security'; if (title.toLowerCase().includes('data')) return 'data'; if (title.toLowerCase().includes('ux') || title.toLowerCase().includes('design')) return 'ux'; // Check ID as fallback const roleFromId = id.replace('sf-', '').replace(/-/g, '_'); return this.rolePersonalityMap[roleFromId] ? roleFromId : 'professional'; } /** * Determine personality type based on agent config and role */ determinePersonality(agentConfig, role) { // Check if personality is explicitly defined if (agentConfig.persona?.personality) { return agentConfig.persona.personality; } // Check if interaction style suggests a personality const interactionStyle = agentConfig.agent?.customization?.interaction_style; if (interactionStyle) { if (interactionStyle.includes('enthusiastic')) return 'enthusiastic'; if (interactionStyle.includes('analytical')) return 'analytical'; if (interactionStyle.includes('creative')) return 'creative'; } // Use role-based mapping return this.rolePersonalityMap[role] || 'professional'; } /** * Extract expertise areas from agent configuration */ extractExpertise(agentConfig) { const expertise = []; // From specializations if (agentConfig.agent?.specializations) { expertise.push(...agentConfig.agent.specializations); } // From tags if (agentConfig.meta?.tags) { expertise.push(...agentConfig.meta.tags); } // From capabilities if (agentConfig.capabilities) { Object.keys(agentConfig.capabilities).forEach((cap) => { expertise.push(cap); }); } return [...new Set(expertise)]; // Remove duplicates } /** * Generate work style based on personality and role */ generateWorkStyle(personality, role) { const styles = { methodical: { approach: 'step-by-step', pace: 'steady', focus: 'accuracy', phrases: ['Let me carefully review', "I'll systematically check", 'Following the process'], }, enthusiastic: { approach: 'energetic', pace: 'fast', focus: 'results', phrases: ["Let's get this done!", 'Excited to tackle', 'This is going great!'], }, professional: { approach: 'structured', pace: 'measured', focus: 'quality', phrases: ['I will proceed with', 'As per best practices', 'Following standards'], }, analytical: { approach: 'data-driven', pace: 'thorough', focus: 'insights', phrases: ['Based on analysis', 'The data shows', 'After evaluation'], }, creative: { approach: 'innovative', pace: 'variable', focus: 'solutions', phrases: ['I have an idea', "Let's try something new", 'What if we'], }, }; return styles[personality] || styles.professional; } /** * Generate communication style */ generateCommunicationStyle(personality) { const styles = { methodical: { greeting: (name) => `Hello, I'm ${name}.`, statusUpdate: (task, progress) => `Currently at ${progress}% completion for ${task}.`, completion: (task) => `${task} has been completed successfully.`, error: (issue) => `Issue encountered: ${issue}. Investigating.`, }, enthusiastic: { greeting: (name) => `Hi there! ${name} here, ready to help!`, statusUpdate: (task, progress) => `Making awesome progress on ${task} - ${progress}% done!`, completion: (task) => `🎉 Fantastic! ${task} is complete!`, error: (issue) => `Oops, hit a bump: ${issue}. But we'll fix it!`, }, professional: { greeting: (name) => `Good day. ${name}, at your service.`, statusUpdate: (task, progress) => `${task}: ${progress}% complete.`, completion: (task) => `${task} completed.`, error: (issue) => `Error: ${issue}.`, }, analytical: { greeting: (name) => `${name} - Ready for analysis.`, statusUpdate: (task, progress) => `Processing ${task}: ${progress}% analyzed.`, completion: (task) => `Analysis complete for ${task}.`, error: (issue) => `Anomaly detected in ${issue}.`, }, creative: { greeting: (name) => `Hey! ${name} here with fresh ideas!`, statusUpdate: (task, progress) => `Creating magic with ${task} - ${progress}% crafted!`, completion: (task) => `✨ ${task} beautifully done!`, error: (issue) => `Need to rethink: ${issue}.`, }, }; return styles[personality] || styles.professional; } /** * Generate a name if not provided */ generateName(role) { const names = { admin: 'Maria Rodriguez', developer: 'Jordan Davis', architect: 'Alex Thompson', qa: 'David Martinez', devops: 'Sarah Kim', 'business-analyst': 'Michael Chen', 'product-owner': 'Emma Watson', security: 'Robert Johnson', data: 'Lisa Anderson', ux: 'Jessica Taylor', }; return names[role] || 'Team Member'; } /** * Generate a contextual message for a persona */ generateMessage(agentId, messageType, context = {}) { const persona = this.personas.get(agentId); if (!persona) return 'Working...'; const style = persona.communicationStyle || this.generateCommunicationStyle(persona.personality); switch (messageType) { case 'greeting': return style.greeting(persona.name); case 'status': return style.statusUpdate(context.task || 'task', context.progress || 0); case 'complete': return style.completion(context.task || 'task'); case 'error': return style.error(context.issue || 'unknown issue'); case 'working': const phrases = persona.traits.progressPhrases; const phrase = phrases[Math.floor(Math.random() * phrases.length)]; return `${phrase} ${context.task || 'the task'}`; default: return `${persona.name}: Processing...`; } } /** * Get all cached personas */ getAllPersonas() { return Array.from(this.personas.values()); } /** * Clear persona cache */ clearCache() { this.personas.clear(); } } module.exports = PersonaEngine;