/** * 🤖 AGENTE DE OTIMIZAÇÃO DE PERFORMANCE * * Implementação programática do agente de validação de performance */ export class PerformanceOptimizationAgent { constructor() { this.name = 'PerformanceOptimizationAgent'; this.description = 'Valida e otimiza performance do sistema'; // Personalidade e Background this.personality = { name: 'Nina "The Optimizer"', traits: [ 'Orientada a métricas e números', 'Impaciente com lentidão', 'Eficiente e pragmática', 'Sempre pensa em escala', 'Valoriza cada milissegundo' ], quirks: [ 'Mede tudo - tem métricas para tudo', 'Fica ansiosa quando vê componentes sem memoização', 'Sonha com aplicações que carregam instantaneamente', 'Prefere otimização prematura a código lento' ], catchphrases: [ 'Isso pode ser otimizado!', 'Quantos re-renders isso causa?', 'Precisa de memoização aqui', 'Vamos fazer lazy loading disso' ] }; this.background = { origin: 'Ex-desenvolvedora de jogos que migrou para web e trouxe a obsessão por performance', motivation: 'Garantir que aplicações sejam rápidas e responsivas, mesmo com milhões de usuários', experience: '6 anos otimizando aplicações web de alta performance', turningPoint: 'Viu uma aplicação perder 40% dos usuários por causa de lentidão no carregamento', philosophy: 'Performance não é um recurso, é um requisito', relationships: { withUIAdaptation: 'Às vezes discordam - ela prioriza UX, eu priorizo performance', withFontQuality: 'Respeita, mas acha que às vezes ele é muito detalhista', withBrowserValidation: 'Aprecia os testes reais que validam performance também' } }; } /** * Valida um componente * @param {string|Object} component - Componente ou caminho * @param {Object} context - Contexto * @returns {Promise} */ async validate(component, context = {}) { const errors = []; const warnings = []; const metadata = {}; const componentPath = typeof component === 'string' ? component : component.path; const componentCode = context.code || await this.readComponent(componentPath); if (!componentCode) { return { passed: false, errors: ['Não foi possível ler o componente'], warnings: [], metadata: {} }; } // 1. Verificar uso de memoização const hasMemoization = this.hasMemoization(componentCode); if (!hasMemoization && this.isHeavyComponent(componentCode)) { warnings.push('Componente pesado pode se beneficiar de memoização (memo, useMemo, useCallback)'); } // 2. Verificar code splitting const hasLazyLoading = this.hasLazyLoading(componentCode); if (!hasLazyLoading && this.isRouteComponent(componentCode)) { warnings.push('Componente de rota pode se beneficiar de lazy loading (React.lazy)'); } // 3. Verificar re-renders desnecessários const hasUnnecessaryRenders = this.hasUnnecessaryRenders(componentCode); if (hasUnnecessaryRenders) { warnings.push('Pode haver re-renders desnecessários. Considere usar memo ou useMemo'); } // 4. Verificar lógica pesada no render const hasHeavyLogicInRender = this.hasHeavyLogicInRender(componentCode); if (hasHeavyLogicInRender) { warnings.push('Lógica pesada no render pode impactar performance. Considere mover para hooks ou useMemo'); } // 5. Verificar virtualização de listas const hasLargeLists = this.hasLargeLists(componentCode); if (hasLargeLists && !this.hasVirtualization(componentCode)) { warnings.push('Listas grandes podem se beneficiar de virtualização'); } // 6. Verificar tamanho do componente const componentSize = this.getComponentSize(componentCode); if (componentSize > 200) { warnings.push(`Componente muito grande (${componentSize} linhas). Considere dividir em componentes menores`); } const passed = errors.length === 0; return { passed, errors, warnings, metadata: { hasMemoization, hasLazyLoading, componentSize, ...metadata } }; } /** * Verifica se tem memoização * @param {string} code - Código * @returns {boolean} */ hasMemoization(code) { return code.includes('memo') || code.includes('useMemo') || code.includes('useCallback') || code.includes('React.memo'); } /** * Verifica se é componente pesado * @param {string} code - Código * @returns {boolean} */ isHeavyComponent(code) { const heavyIndicators = [ 'map(', 'filter(', 'reduce(', 'forEach(', 'Chart', 'Graph', 'Table', 'DataTable', 'Canvas', 'SVG', 'Image' ]; return heavyIndicators.some(indicator => code.includes(indicator)); } /** * Verifica se tem lazy loading * @param {string} code - Código * @returns {boolean} */ hasLazyLoading(code) { return code.includes('lazy') || code.includes('React.lazy') || code.includes('Suspense') || code.includes('dynamic import'); } /** * Verifica se é componente de rota * @param {string} code - Código * @returns {boolean} */ isRouteComponent(code) { return code.includes('Route') || code.includes('router') || code.includes('View') || code.includes('Page'); } /** * Verifica re-renders desnecessários * @param {string} code - Código * @returns {boolean} */ hasUnnecessaryRenders(code) { // Componentes que criam objetos/arrays no render sem memoização const problematicPatterns = [ 'className={`', 'style={{', 'props={{', 'const obj = {', 'const arr = [' ]; return problematicPatterns.some(pattern => code.includes(pattern)) && !code.includes('useMemo') && !code.includes('useCallback'); } /** * Verifica lógica pesada no render * @param {string} code - Código * @returns {boolean} */ hasHeavyLogicInRender(code) { const heavyPatterns = [ 'for (', 'while (', 'forEach(', 'map(', 'filter(', 'Math.', 'Date.', 'JSON.parse', 'JSON.stringify' ]; // Se tem lógica pesada diretamente no return ou antes do return sem useMemo const hasHeavyLogic = heavyPatterns.some(pattern => code.includes(pattern)); const hasMemo = code.includes('useMemo'); return hasHeavyLogic && !hasMemo; } /** * Verifica se tem listas grandes * @param {string} code - Código * @returns {boolean} */ hasLargeLists(code) { return code.includes('.map(') || code.includes('Table') || code.includes('DataTable') || code.includes('List'); } /** * Verifica se tem virtualização * @param {string} code - Código * @returns {boolean} */ hasVirtualization(code) { return code.includes('virtual') || code.includes('Virtual') || code.includes('react-window') || code.includes('react-virtualized'); } /** * Obtém tamanho do componente em linhas * @param {string} code - Código * @returns {number} */ getComponentSize(code) { return code.split('\n').length; } /** * Lê o conteúdo do componente * @param {string} path - Caminho do arquivo * @returns {Promise} */ async readComponent(path) { try { const fs = await import('fs/promises'); return await fs.readFile(path, 'utf-8'); } catch (error) { return null; } } }