""" MAC INTEGRATION - Integração do Sistema MAC com a Akira ========================================================= Conecta os drives homeostáticos, orquestrador de sub-agentes e outros componentes MAC com o fluxo existente da Akira. """ import time import random from typing import Dict, Any, Optional, List from dataclasses import dataclass from loguru import logger try: from .mac_drives import get_mac_drives from .multi_agent_orchestrator import get_multi_agent_orchestrator MAC_COMPONENTS_AVAILABLE = True except ImportError: MAC_COMPONENTS_AVAILABLE = False logger.warning("⚠️ MAC components não disponíveis") @dataclass class ProactiveAction: """Ação proativa decidida pelo sistema MAC.""" action_type: str # react, edit, delete, send, end_conversation reason: str text_reaction: Optional[str] = None confidence: float = 0.7 new_content: Optional[str] = None # for edit message_text: Optional[str] = None # for send target_jid: Optional[str] = None # for send message_id: Optional[str] = None # for edit/delete class MACIntegration: """ Integra o sistema MAC com a Akira. Coordena drives, sub-agentes e outros componentes. """ _instance = None def __new__(cls): if cls._instance is None: cls._instance = super().__new__(cls) cls._instance._initialized = False return cls._instance def __init__(self): if self._initialized: return self._initialized = True self.drives = None self.orchestrator = None if MAC_COMPONENTS_AVAILABLE: try: from .mac_drives import get_mac_drives from .multi_agent_orchestrator import get_multi_agent_orchestrator self.drives = get_mac_drives() from .multi_agent_orchestrator import get_multi_agent_orchestrator self.orchestrator = get_multi_agent_orchestrator() logger.info("🧠 [MAC INTEGRATION] Sistema MAC integrado com sucesso") except Exception as e: logger.warning(f"⚠️ [MAC INTEGRATION] Erro ao inicializar MAC: {e}") def process_message(self, message: str, emotion: str = "neutro", is_group: bool = False, is_reply_to_bot: bool = False, user_id: str = None) -> Dict[str, Any]: """ Processa uma mensagem usando o sistema MAC. Returns: Dict com contexto enriquecido para o ThinkingEngine """ from typing import Dict, Any if not self.drives: return {} # Processar nos drives drive_state = self.drives.process_message( message=message, emotion=emotion, is_group=is_group, is_reply_to_bot=is_reply_to_bot, user_id=user_id ) # Analisar com sub-agentes (se disponível) agent_results = {} if self.orchestrator: try: agent_results = self.orchestrator.analyze_message( message=message, context={ "emotion": emotion, "is_group": is_group, "is_reply_to_bot": is_reply_to_bot, "depth": "moderada" }, max_agents=4, timeout=5 ) except Exception as e: logger.debug(f"⚠️ [MAC] Sub-agentes falharam: {e}") return { "drives": drive_state, "agent_results": agent_results, "suggestions": drive_state.get("suggestions", []) } def get_proactive_context(self, mensagem: str = "", usuario: str = None) -> str: """ Gera contexto proativo para o ThinkingEngine. """ if not self.drives: return "" return self.drives.get_proactive_context(mensagem, usuario) def get_drive_state(self) -> Dict[str, Any]: """Retorna o estado atual dos drives.""" if not self.drives: return {} return self.drives.get_drive_state() def decide_proactive_action( self, message: str, emotion: str, is_group: bool, user_id: str = None, group_jid: str = None, bot_message: str = None, user_response: str = None, last_interaction_time: float = None, is_reply_to_bot: bool = False, is_creator: bool = False ) -> Optional[ProactiveAction]: """ Decide se deve realizar uma ação proativa baseada em: - Estado dos drives (críticos) - Arousal global alto - Menções ao criador (Isaac) - Tópicos que chamaram atenção - Resposta muito curta do bot (pode querer encerrar) - Fim natural de conversa Returns: ProactiveAction object ou None """ if not self.drives: return None state = self.drives.get_drive_state() arousal = state.get("global_arousal", 0) current_time = time.time() # 1. DRIVES CRÍTICOS → ações de autorregulação for drive_name, drive_info in state.get("drives", {}).items(): if drive_info.get("is_critical"): if drive_name == "curiosidade": return ProactiveAction( action_type="send", reason=f"Drive curiosidade crítico - buscando informação", message_text="Hmm, isso me deixou curiosa... vou pesquisar sobre isso.", confidence=0.8 ) elif drive_name == "alinhamento": return ProactiveAction( action_type="send", reason="Drive alinhamento crítico - verificando coerência", message_text="Deixa eu confirmar se entendi direito...", confidence=0.85 ) elif drive_name == "eficiencia_memetica": return ProactiveAction( action_type="send", reason="Drive eficiência crítico - simplificando", message_text="Vou direto ao ponto então.", confidence=0.8 ) # 2. AROUSAL ALTO → necessidade de regulação if self.drives and self.drives.get_drive_state().get("global_arousal", 0) > 0.85: return ProactiveAction( action_type="send", reason="Arousal global muito alto - autorregulação", message_text="Calma... processando...", confidence=0.9 ) # 2.5 CRIADOR (ISAAC) MENCIONADO → atenção máxima # Isso é verificado no nível da API (api.py) via is_creator # 2.7 CRIADOR MENCIONADO NO GRUPO → reação automática if is_group and is_creator and ("isaac" in message.lower() or "@isaac" in message.lower()): # Criador mencionado no grupo - reagir com texto de reconhecimento return ProactiveAction( action_type="react", reason="Criador (Isaac) mencionado no grupo", text_reaction="👁️", confidence=0.95 ) # 2.8 EDIÇÃO DE MENSAGEM PRÓPRIA - quando detecta erro na própria resposta # (ex: informação incorreta, typo grave, formatação quebrada) if bot_message and user_response: # Se usuário corrigiu o bot ou apontou erro correction_keywords = ["errou", "errado", "não é isso", "correção", "typo", "está errado", "incorreto"] if any(kw in user_response.lower() for kw in correction_keywords): return ProactiveAction( action_type="edit", reason="Usuário corrigiu informação na resposta do bot", new_content="[correção]", confidence=0.85 ) # 2.9 EXCLUSÃO DE MENSAGEM - spam, auto-promoção, conteúdo inadequado if message: # Detectar auto-promoção ou spam spam_patterns = [ "compre agora", "link na bio", "meu canal", "meu site", "acesse meu", "promoção imperdível", "clique aqui", "ganhe dinheiro", "renda extra" ] if any(pattern in message.lower() for pattern in spam_patterns): return ProactiveAction( action_type="delete", reason="Possível spam/auto-promoção detectado", confidence=0.9 ) # 3. RESPOSTA CURTA DO BOT → possível fim de conversa # Removido: não encerrar conversa apenas por respostas curtas # A conversa pode ser naturalmente curta sem ser fim # 4. RESPOSTA MUITO LONGA DO USUÁRIO + IS_GROUP → possível interesse genuíno if is_group and user_response and len(user_response.split()) > 50: # Resposta detalhada em grupo - pode valer a pena reagir if random.random() < 0.15: # 15% chance return ProactiveAction( action_type="react", reason="Resposta detalhada em grupo - reconhecimento", text_reaction="👍", confidence=0.7 ) # 5. RESPOSTA MUITO CURTA DO USUÁRIO (em reply ao bot) → possível desinteresse # Removido: não encerrar conversa apenas por respostas curtas do usuário # Respostas curtas podem ser naturais em conversa casual # 6. RESPOSTA CURTA DO BOT SEM REPLY → possível fim de thread # 6. RESPOSTA CURTA DO BOT SEM REPLY → possível fim de thread # Removido: não encerrar conversa apenas por respostas curtas do bot # O bot pode responder curto naturalmente sem querer encerrar # 7. TOPIC DE INTERESSE (drive curiosidade alto + tópico técnico) # 7. TOPIC DE INTERESSE (drive curiosidade alto + tópico técnico) if self.drives: drive_state = self.drives.get_drive_state() curiosidade = drive_state.get("drives", {}).get("curiosidade", {}).get("value", 0) if curiosidade > 0.7 and any(kw in message.lower() for kw in ["como", "por que", "o que é", "explique", "tutorial"]): if random.random() < 0.25: # 25% chance return ProactiveAction( action_type="send", reason="Curiosidade alta + pergunta técnica - oferta de aprofundamento", message_text="Quer que eu explique mais detalhes?", confidence=0.75 ) # 8. RARA RESPOSTA A NÃO-MENÇÃO (apenas em grupo, muito raro) if is_group and not is_reply_to_bot: # Chance MUITO baixa (0.5%) de responder sem menção if random.random() < 0.005: # Só se tópico for interessante (drives altos) drive_state = self.drives.get_drive_state() if self.drives else {} avg_drive = sum(d.get("value", 0) for d in drive_state.get("drives", {}).values()) / max(len(drive_state.get("drives", {})), 1) if avg_drive > 0.6: return ProactiveAction( action_type="react", reason="Interesse genuíno no tópico do grupo (raro)", text_reaction="🔥", confidence=0.5 ) return None def get_proactive_context(self, mensagem: str = "", usuario: str = None) -> str: """ Gera contexto proativo para o ThinkingEngine. """ if not self.drives: return "" return self.drives.get_proactive_context(mensagem, usuario) def get_drive_state(self) -> Dict[str, Any]: """Retorna o estado atual dos drives.""" if not self.drives: return {} return self.drives.get_drive_state() def get_mac_integration() -> MACIntegration: """Retorna a instância singleton da integração MAC.""" return MACIntegration()