akira / modules /API_PATCH_DETAILED.md
akra35567's picture
Upload 55 files
bbbdd24 verified
|
Raw
History Blame Contribute Delete
15.6 kB

""" ═══════════════════════════════════════════════════════════════════════ 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' ]