Spaces:
Running
Running
| """ | |
| βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| PATCH ESPECΓFICO PARA api.py β APLICAR LINHA POR LINHA | |
| βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| Este arquivo mostra as MODIFICAΓΓES EXATAS no api.py existente. | |
| Arquivo: i:\\Isaac Quarenta\\ProgramaΓ§Γ£o\\AKIRA-SOFTEDGE\\modules\\api.py | |
| MODIFICATIONS: | |
| 1. Adicionar imports (top do arquivo) | |
| 2. Modificar _get_user_context() (line 2311) | |
| 3. Modificar _get_history_for_llm() (line 2320+) | |
| 4. Modificar akira_endpoint() - parte de obtΓ©m histΓ³rico | |
| βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| """ | |
| # βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| # MODIFICATION 1: ADICIONAR IMPORTS (TOP DO ARQUIVO) | |
| # βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| """ | |
| LocalizaΓ§Γ£o: PrΓ³ximo aos outros imports do modules/ | |
| ANTES: | |
| ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| import json | |
| import hashlib | |
| import logging | |
| from skills_registry import SkillsRegistry | |
| ... | |
| DEPOIS (ADICIONAR ESTAS LINHAS): | |
| ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| import json | |
| import hashlib | |
| import logging | |
| from skills_registry import SkillsRegistry | |
| # β NOVOS IMPORTS PARA CONTEXT V2 | |
| from modules.context_manager_v2 import ( | |
| ContextManagerV2, | |
| get_context_manager, | |
| MessageType, | |
| ContextType | |
| ) | |
| from modules.listen_stream_processor import ( | |
| ListenStreamProcessor, | |
| get_listen_processor | |
| ) | |
| # Inicializa singletons | |
| ctx_manager = get_context_manager() | |
| listen_processor = get_listen_processor() | |
| ... | |
| """ | |
| # βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| # MODIFICATION 2: ATUALIZAR _get_user_context (line 2311) | |
| # βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| """ | |
| LocalizaΓ§Γ£o: api.py::_get_user_context (line 2311) | |
| ANTES: | |
| ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| def _get_user_context(self, usuario, conversation_id=None): | |
| # π§ FIX: Usa conversation_id como chave primΓ‘ria para isolamento total | |
| cache_key = conversation_id if conversation_id else usuario | |
| if cache_key not in self.contexto_cache: | |
| db_path = getattr(self.config, 'DB_PATH', 'akira.db') | |
| db = Database(db_path) | |
| # Passa conversation_id para o objeto Contexto para persistΓͺncia isolada | |
| self.contexto_cache[cache_key] = Contexto(db, usuario=usuario, conversation_id=conversation_id) | |
| return self.contexto_cache[cache_key] | |
| DEPOIS: | |
| ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| def _get_user_context(self, usuario, numero, conversation_id=None, | |
| tipo_conversa='pv', grupo_id=None): | |
| # π§ FIX V2: Usa novo ContextManagerV2 para isolamento robusto | |
| # Legacy: mantΓ©m cache para compatibilidade | |
| cache_key = conversation_id if conversation_id else usuario | |
| if cache_key not in self.contexto_cache: | |
| db_path = getattr(self.config, 'DB_PATH', 'akira.db') | |
| db = Database(db_path) | |
| self.contexto_cache[cache_key] = Contexto(db, usuario=usuario, conversation_id=conversation_id) | |
| # NOVO: Retorna contexto isolado via ContextManagerV2 | |
| contexto_isolado = ctx_manager.obter_ou_criar_contexto( | |
| numero=numero, | |
| tipo_conversa=tipo_conversa, | |
| grupo_id=grupo_id, | |
| usuario=usuario | |
| ) | |
| # Retorna ambos para compatibilidade backward | |
| return { | |
| 'legacy_contexto': self.contexto_cache[cache_key], # Compatibilidade | |
| 'novo_contexto_manager': contexto_isolado, | |
| 'numero': numero, | |
| 'tipo_conversa': tipo_conversa, | |
| 'grupo_id': grupo_id, | |
| } | |
| NOTA: A assinatura da funΓ§Γ£o MUDA. Precisa ser atualizada | |
| em TODOS os lugares que chamam _get_user_context() | |
| """ | |
| # βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| # MODIFICATION 3: INTEGRAR LISTEN STREAM EM akira_endpoint | |
| # βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| """ | |
| LocalizaΓ§Γ£o: api.py::akira_endpoint() - apΓ³s extrair dados (line ~1250) | |
| ANTES (buggy): | |
| ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| usuario = validate_sender_name(usuario, numero, "usuario_principal") | |
| ... | |
| # Captura contexto aqui (BUGGY - sem isolaΓ§Γ£o) | |
| contexto = self._get_user_context(usuario) | |
| # HistΓ³rico SEM FILTRO (PROBLEMA!) | |
| historico = contexto.obter_historico() | |
| # Process LLM... | |
| DEPOIS (robusto): | |
| ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| usuario = validate_sender_name(usuario, numero, "usuario_principal") | |
| ... | |
| # β NOVO: PROCESSA VIA LISTEN STREAM | |
| evento = { | |
| 'usuario': usuario, | |
| 'numero': numero, | |
| 'texto': mensagem, | |
| 'tipo_conversa': tipo_conversa, | |
| 'grupo_id': grupo_id, | |
| 'referenced_message_author': quoted_author_name, | |
| 'referenced_message_texto': mensagem_citada, | |
| 'referenced_message_id': data.get('message_id_citada', ''), | |
| } | |
| resultado_processamento = listen_processor.processar_mensagem_chegando(evento) | |
| self.logger.info( | |
| f"π ClassificaΓ§Γ£o Listen: {resultado_processamento['tipo_message']} | " | |
| f"Deve processar: {resultado_processamento['deve_processar']}" | |
| ) | |
| # β SE NΓO FOR DIRETO, NΓO PROCESSA | |
| if not resultado_processamento['deve_processar']: | |
| self.logger.info(f"π Mensagem contextual (escuta). NΓ£o respondendo.") | |
| return jsonify({ | |
| 'resposta': '', | |
| 'status': 'context_registered', | |
| 'tipo': 'contextual', | |
| 'modelo_usado': 'listen_stream', | |
| 'conversation_id': resultado_processamento['conversation_id'] | |
| }) | |
| # β Γ DIRETO: ObtΓ©m contexto ISOLADO | |
| conversation_id = resultado_processamento['conversation_id'] | |
| contexto_data = listen_processor.obter_contexto_para_resposta( | |
| numero=numero, | |
| tipo_conversa=tipo_conversa, | |
| grupo_id=grupo_id, | |
| include_contextual=True | |
| ) | |
| # Extrai histΓ³rico ISOLADO | |
| historico = contexto_data['direct_messages'] | |
| # Context enriquecido com fluxo do grupo | |
| contexto_grupo_info = contexto_data.get('grupo_flow', {}) | |
| participants = contexto_data.get('participants', []) | |
| # Se em grupo, inclui info de participantes | |
| if tipo_conversa == "grupo": | |
| self.logger.info(f"π₯ Contexto grupo: {len(participants)} participantes") | |
| # LEGACY: obtΓ©m tambΓ©m via contexto_cache para compatibilidade | |
| contexto = self._get_user_context( | |
| usuario=usuario, | |
| numero=numero, | |
| conversation_id=conversation_id, | |
| tipo_conversa=tipo_conversa, | |
| grupo_id=grupo_id | |
| ) | |
| # Process LLM... | |
| """ | |
| # βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| # MODIFICATION 4: ACEITAR NOVOS CAMPOS NO PAYLOAD | |
| # βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| """ | |
| LocalizaΓ§Γ£o: api.py::akira_endpoint() - seΓ§Γ£o data extraction (line ~1240) | |
| ANTES: | |
| ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| usuario = data.get('usuario', 'anonimo') | |
| numero = data.get('numero', '') | |
| mensagem = data.get('mensagem', '') | |
| message_id = data.get('message_id', '') | |
| tipo_conversa = data.get('tipo_conversa', 'pv') | |
| grupo_id = data.get('grupo_id') or data.get('contexto_grupo') or '' | |
| imagem_dados = data.get('imagem', {}) | |
| ... | |
| DEPOIS (adiciona suporte): | |
| ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| usuario = data.get('usuario', 'anonimo') | |
| numero = data.get('numero', '') | |
| mensagem = data.get('mensagem', '') | |
| message_id = data.get('message_id', '') | |
| tipo_conversa = data.get('tipo_conversa', 'pv') | |
| grupo_id = data.get('grupo_id') or data.get('contexto_grupo') or '' | |
| # β NOVOS CAMPOS PARA LISTEN STREAM | |
| # ReferΓͺncia a outra mensagem (reply) | |
| referenced_message_author = data.get('referenced_message_author', | |
| data.get('quoted_author_name', '')) | |
| referenced_message_texto = data.get('referenced_message_texto', | |
| data.get('mensagem_citada', '')) | |
| referenced_message_id = data.get('referenced_message_id', | |
| data.get('message_id_citada', '')) | |
| imagem_dados = data.get('imagem', {}) | |
| ... | |
| """ | |
| # βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| # MODIFICATION 5: ATUALIZAR PAYLOAD DO RESPOSTA | |
| # βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| """ | |
| LocalizaΓ§Γ£o: api.py::akira_endpoint() - retorno jsonify (line ~1400+) | |
| ADICIONAR CAMPO: | |
| ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| return jsonify({ | |
| 'resposta': resposta, | |
| 'modelo_usado': modelo, | |
| 'confidence': confidence, | |
| 'conversation_id': conversation_id, # β NOVO | |
| 'tipo_message': resultado_processamento['tipo_message'], # β NOVO | |
| 'participants': participants if tipo_conversa == 'grupo' else [], # β NOVO | |
| ... | |
| }) | |
| """ | |
| # βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| # QUICK CHECKLIST | |
| # βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| """ | |
| ANTES DE APLICAR ESTAS MUDANΓAS: | |
| β‘ Verificar que context_manager_v2.py existe e estΓ‘ correto | |
| β‘ Verificar que listen_stream_processor.py existe e estΓ‘ correto | |
| β‘ Fazer BACKUP do api.py ANTES DE MODIFICAR | |
| β‘ Testar com um grupo de teste (nΓ£o produΓ§Γ£o) | |
| APΓS APLICAR: | |
| β‘ Testar endpoint POST /akira com payload novo | |
| β‘ Testar com tipo_conversa='pv' (deve ser DIRECT) | |
| β‘ Testar com tipo_conversa='grupo' sem @AKIRA (deve ser CONTEXTUAL) | |
| β‘ Testar com tipo_conversa='grupo' com @AKIRA (deve ser DIRECT) | |
| β‘ Verificar logs para "π ClassificaΓ§Γ£o Listen" | |
| β‘ Verificar que histΓ³rico Γ© isolado por conversation_id | |
| β‘ Monitorar para memory leaks no context_manager (stats) | |
| TROUBLESHOOTING: | |
| β ImportError: context_manager_v2 | |
| β Verificar que arquivo estΓ‘ em modules/ | |
| β Verificar import path | |
| β NameError: ctx_manager not defined | |
| β Verificar que get_context_manager() foi chamado no top | |
| β Verificar que imports foram adicionados | |
| β Contexto ainda estΓ‘ misturado | |
| β Verificar que listen_processor.processar_mensagem_chegando() foi integrado | |
| β Verificar que resultado_processamento['deve_processar'] Γ© respeitado | |
| β Verificar conversation_id estΓ‘ sendo passado corretamente | |
| """ | |
| __all__ = [ | |
| 'PATCH_INSTRUCTIONS' | |
| ] | |