
    	gig0                     T   d dl Z d dlZd dlZd dlZd dlZd dlmZ d dlmZ d dl	m
Z
mZ d dlmZmZ ddlmZ ddlmZmZ dd	lmZ dd
lmZ ddlmZ ddlmZ ddlmZmZmZ d dl m!Z!  ee!jD                  d e!jF                        Z$d Z%defdZ&deded   fdZ'defdZ(defdZ)defdZ*defdZ+deded   fdZ, ee      Z-e-j]                  de&       e-j]                  de(       e-j]                  de)       e-j]                  de       e-j]                  d e       e-j]                  d!e       e-j]                  d"e       e-j]                  d#e*       e-j]                  d$e+       e-j_                  d       e-ja                  de'ded       e-jc                  dd       dd d!d"d$dZ2e-ja                  de,e2       e-ja                  de,e2       e-ja                  d e,e2       e-ja                  d!e,e2       e-ja                  d"e,e2       e-jc                  d$e       e-jg                         Z4y)%    N)Literal)
ChatOpenAI)SystemMessage	AIMessage)
StateGraphEND   )
AgentState)SYSTEM_PROMPTget_classification_prompt)ub_presupuesto_skill_node)cartera_skill_node)talento_humano_skill_node)resumen_pdf_skill_node)get_active_archetypesget_cached_resultsave_archetype_to_backend)settings)modeltemperatureapi_keyc                     | j                   j                  di       }|j                  dd      |j                  dd      |j                  dd      dS )zExtrae el consumo de tokens.token_usageprompt_tokensr   completion_tokenstotal_tokens)prompt
completiontotal)response_metadataget)messageusages     -/opt/agrota/powerbi/client-mcp/agent/graph.pyextract_usager%      sO    %%))-<E))OQ/ii 3Q7>1-     statec                   K   | j                  dg       }|sddiS |d   j                  }t        j                         }| j                  d      }| j                  dd      }|r||z
  dk  rddiS |rct        j                  d|j                               }|r-t        d       |dd	|j                  d
      t        d      gdS dt        d      gdS t        d       dt        d      gdS w)uU   Verifica si la sesión de 12 horas ha caducado y solicita la cédula si es necesario.messagesis_authenticatingFauth_validated_ati  z^\d{10}$u;   🔒 [SECURITY] Cédula validada. Sesión iniciada por 12h.securityr   u@   ✅ Acceso validado correctamente. ¿En qué puedo ayudarte hoy?content)r,   r*   	intencionuser_cedular)   Tuk   ⚠️ El número de cédula ingresado no es válido (debe tener 10 dígitos). Por favor, intenta de nuevo.)r*   r)   uD   🔒 [SECURITY] Sesión expirada o inexistente. Solicitando cédula.uu   Hola, por motivos de seguridad tu sesión ha expirado (12h). Por favor, ingresa tu número de cédula para continuar.)	r!   r/   timerematchstripprintgroupr   )r'   r)   last_msgnowlast_valis_authcedula_matchs          r$   security_check_noder=   &   s    yyR(H#U++|##H
))+Cyy,-Hii+U3G S8^e+#U++ xxX^^-=>OP%(%*'+11!4&/qrs  &*&  0]  ^  _  

PQ!  (_  `  a s   C-C/return)classifyr   c                 J    | j                  d      s| j                  d      syy)uB   Decide si continuar con el flujo o detenerse a esperar la cédula.r*   r,   r   r?   )r!   )r'   s    r$   security_routerrA   O   s!    yy$%UYY7J-Kr&   c                   K   | d   }|sdddS t                d{   }|r+dj                  |D cg c]  }d|d    d|d	     c}      nd
}|dd }t        j                  t	        t        |            g|       d{   }	 |j                  j                         }t        j                  d|t        j                        }|r$t        j                  |j                  d            ni }	t        t        |	j!                  dg                   }
|
s#|	j!                  d      r|	j!                  d      g}
|	j!                  di       }|
|
j#                         |
r|
d   nd|	j!                  d      ||j!                  d      xs | j!                  d      |j!                  d      xs | j!                  d      t%        |      dg dddddS 7 c c}w 7 R# t&        $ r'}t)        d|        ddt%        |      dcY d}~S d}~ww xY ww)uH   Nodo para clasificar la intención y detectar arquetipos pre-calculados.r)   GENERAL_CHATN)r0   archetype_key
z- archetypeKeyz: sampleQuestionzNinguno disponibler.   z\{.*\}r   intencionesr0   entitiesUNKNOWNrD   	user_nameuser_positionF )rI   intenciones_pendientesr0   rD   last_entitiesrL   rM   r#   is_precalculatedresultados_tecnicosmensaje_skill	dashboard	dax_queryinteractive_datau   ⚠️ Error clasificación: )r0   rD   r#   )r   joinllmainvoker   r   r/   r5   r3   searchDOTALLjsonloadsr7   listsetr!   copyr%   	Exceptionr6   )r'   r)   
archetypesaarchetypes_txtrecent_messagesresponser/   
json_matchdatarI   rJ   es                r$   classify_intent_noderj   U   s    Z H+dCC -..JisTYYYcdTU"Q~%6$7r!<L:M9N Ode  zNNrsmO[[7GH"	"  H
a""((*YYy'299=
2<tzz***1-."3txxr:;<txx488K01K88J+ '&1&6&6&8+6QI!XXo6%!k2Leii6L%\\/:Xeii>X"8, %#% $
 	
+ /dB  a-aS12&V^H_``as]   HGHG<HGH	EG HH	H!H=H>HHHc                 
  K   | j                  d      }|sddiS t        d|        t        |       d{   }|r5t        d       t        j                  |d      d| j                  d	      d
S t        d       ddiS 7 Jw)zRVerifica si existe un resultado pre-calculado en Java para el arquetipo detectado.rD   rQ   Fu0   🔍 [CACHE] Buscando resultado para arquetipo: Nu8   ✅ [CACHE] Hit! Usando resultado pre-calculado de Java.)ensure_asciiTr0   )ultimo_resultadorQ   r0   u1   ❌ [CACHE] Miss. Procediendo a consulta en vivo.)r!   r6   r   r\   dumps)r'   rD   cache_results      r$   check_cache_noderp      s     IIo.M"E**	<]O
LM*=99LHI !%

<e L $;/
 	
 

=>&& :s   4BBABc                   K   | j                  d      s| j                  d      r| j                  d      rg d}| j                  d      |vri S d| j                  dd      j                         v ri S | d   d	   j                  }| j                  d      }| j                  d      }t        d
|dd  d       t	        |||       d{    i S 7 w)u[   Nodo que registra automáticamente consultas exitosas como nuevos arquetipos en el backend.rQ   rm   rU   )UB_PRESUPUESTOCARTERATALENTO_HUMANOr0   u   ¡HOLArN   r)   r+   u@   🧠 [LEARNING] Auto-registrando nueva consulta como arquetipo: N2   z...)r!   upperr/   r6   r   )r'   allowed_intentsquestiondaxcategorys        r$   register_archetype_noder{      s      99'(UYY7I-JuyyYdOe J99[!8I uyyb17799I$R(00ii$99[)PQYZ][]Q^P__bcd'#x@@@I 	As   CC	C
Cc                   K   | d   }t        j                  d      }t        j                  j                  |      j	                  d      }t        j                  |      }d| j                  d       d}| j                  d      r|d	| j                  d       dz  }| j                  d
      r|d| j                  d
       dz  }| j                  dg       }|r(|dz  }t        |      D ]  \  }}|d|dz    d| dz  } n(| j                  d      r|d| j                  d       z  }t        j                  t        |      g|dd t        d|              d{   }	t        |	j                        gt        |	      dS 7 'w)z@Genera la respuesta final persuasiva y ejecutiva usando Felizia.r)   zAmerica/Guayaquilz%Y-%m-%d)current_dateu   Intención Detectada: r0   rE   rL   z	Usuario: rM   zCargo: rR   u$   Datos Técnicos Consolidados (MCP):
z--- Resultado r	   z ---
rm   u   Dato Técnico (MCP): r.   iNu   Contexto técnico actual:
)r)   r#   )pytztimezonedatetimer9   strftimer   formatr!   	enumeraterX   rY   r   r   r/   r%   )
r'   r)   tzr}   
sys_promptcontext
resultadosiresresponse_objs
             r$   response_noder      s    Z H	*	+B$$((,55jAL%%<@J&uyy'=&>bAGyyYuyy56b99yy!WUYY78;; 0"5J::
+ 	;FAs!uF3%r::G	;	%	&*5995G+H*IJJj)&
34.& 	 ;G9EF&  L |';';<=|, s   E!F#F$(F)ub_presupuesto_skillcartera_skilltalento_humano_skillresumen_pdf_skillr   c                     | j                  d      ry| j                  dg       }|st        d       y|d   }t        d| d|        |dk(  ry	|d
k(  ry|dk(  ry|dk(  ryy)zARouter secuencial que maneja la cola de intenciones (Dashboards).rQ   r   rO   uE   🏁 [ROUTER] No hay más tareas pendientes. Yendo a respuesta final.r   u!   🔄 [ROUTER] Tareas pendientes: z. Ejecutando: rr   r   rs   r   rt   r   RESUMEN_EJECUTIVO_PDFr   )r!   r6   )r'   
pendientesproximas      r$   unified_routerr      s     yy#$ 3R8JUV mG	-j\y
QR""%	I		$	$%	+	+"r&   security_checkr?   check_cacher   r   r   r   register_archetyper   )5r\   r   r~   r3   r2   typingr   langchain_openair   langchain_core.messagesr   r   langgraph.graphr   r   r'   r
   promptsr   r   skills.ub_presupuesto_skillr   skills.cartera_skillr   skills.talento_humano_skillr   skills.resumen_pdf_skillr   utils.precalc_helperr   r   r   config.settingsr   
MODEL_NAMEOPENAI_API_KEYrX   r%   r=   rA   rj   rp   r{   r   r   workflow_builderadd_nodeset_entry_pointadd_conditional_edgesadd_edgedestinos_routercompileworkflow_compiled r&   r$   <module>r      s\      	   ' < +  = B 4 B < e e $ 


##'Z 'R: '2C*D .aj .a`'* ', . z  F*   2W  *X < j)    *,? @   *&: ;   -)9 :   02K L   /+= >   02K L   -/E F   .0G H   /= 9     !1 2  & &'7K    *m 4 3$2,$  & &}no V  & &'=~ _  & & X  & &'=~ _  & &':NO \   /3 /$,,. r&   