
    C4j=B                       S r SSKJr  SSKrSSKrSSKJr  SSKJr  SSKJ	r	  SSK
Jr  SSKJrJr  SS	KJrJrJrJrJrJr  \R,                  " \5      rS
r\R4                  " S\R6                  5      r\R4                  " S5      rS'S jrS(S jrSr S)S jr!S*S jr"S+S jr#S,S jr$S-S jr%S.S jr&S/S jr'S0S jr(S1S jr)S2S jr*S3S jr+S4S jr,S5S jr-S1S jr.S6S jr/        S7S jr0SS .       S8S! jjr1              S9S" jr2 S:           S;S# jjr3            S<S$ jr4SS%.             S=S& jjr5g)>z?Persistir archivos generados por el code interpreter de OpenAI.    )annotationsN)datetime)Path)Any)Session)AgentFileModelAgentResponseFileModel)AgentFileError	agent_dirbuild_response_storage_pathensure_responses_dirRESPONSE_EXTENSIONSsafe_display_name   z&(?:sandbox:)?/mnt/data/([^\s\)\]\"']+)z\[([^\]]+)\]\(([^)]+)\)c                    U R                   U R                  [        U R                  =(       d    S5      U R                  (       a  U R                  R                  5       S.$ S S.$ )Nr   )idnamesize	createdAt)r   display_nameint
size_bytes
created_at	isoformatrows    cC:\Users\jesus\Desktop\proyecto_pie360\backend\app\backend\services\agent_response_files_service.py_response_file_dictr   "   sT    ff  CNN'a(36>>S^^--/	  HL	     c                ~    [        U 5      R                  R                  5       n[        U=(       a	    U[        ;   5      $ N)r   suffixlowerboolr   )filenamer"   s     r   _is_response_documentr&   +   s0    (^""((*F86%8899r   
   c                    [        U 5      R                  R                  5       nU[        ;  a  g[        U 5      R                  R                  5       n[        U5      [        :  a  gg)NFT)r   r"   r#   r   stemstriplen_MIN_MENTIONED_STEM_LEN)r   r"   r)   s      r    _is_plausible_generated_filenamer-   3   sO    $Z$$&F((:??  "D
4y**r   c                6  ^ U  Vs1 s H  n[        U5      (       d  M  UiM     nnU(       d
  [        5       $ [        5       n[        U[        SS9 H@  nUR	                  5       m[        U4S jU 5       5      (       a  M/  UR                  U5        MB     U$ s  snf )zEQuita fragmentos como Diaz.docx dentro de Informe_Isabella_Diaz.docx.Tkeyreversec              3     >#    U  H>  nUR                  5       T:g  =(       a    UR                  5       R                  T5      v   M@     g 7fr!   )r#   endswith).0otherr#   s     r   	<genexpr>-filter_mentioned_filenames.<locals>.<genexpr>F   s<      
  KKMU"Du{{}'='=e'DD s   AA	)r-   setsortedr+   r#   anyadd)namesr   	plausiblemaximalr#   s       @r   filter_mentioned_filenamesr?   =   s    "'R%$+KD+Q%IRuGyc48

 
 
 
 
 D 9 N Ss
   BBc                >    [        U 5      nU(       d  g[        US S9$ )N c                >    [        [        U 5      R                  5      $ r!   )r+   r   r)   )r   s    r   <lambda>)best_mentioned_filename.<locals>.<lambda>S   s    #d4joo*>r   )r0   )r?   max)r<   filtereds     r   best_mentioned_filenamerG   O   s     )%0Hx>??r   c                v   [        5       nU (       d  U$ [        R                  U 5       H6  nUR                  [	        UR                  S5      5      R                  5        M8     [        R                  " SU [        R                  5       H#  nUR                  UR                  S5      5        M%     [        U5      $ )zFNombres de archivo citados en texto del modelo (sandbox, rutas, etc.).r   uD   ([A-Za-z0-9áéíóúÁÉÍÓÚñÑ_\-.]+?\.(?:pdf|docx?|xlsx?|csv)))
r8   _SANDBOX_PATH_REfinditerr;   r   groupr   re
IGNORECASEr?   )textr<   matchs      r   extract_mentioned_filenamesrP   V   s    eE!**40		$u{{1~&++, 1O

 			%++a.! &e,,r   c           	     t   [        5       n[        U SS5      =(       d    / nU Hc  n[        USS5      S:w  a  M  [        USS5      =(       d    /  H3  n[        USS5      =(       d    SnUR                  [        U5      5        M5     Me     UR                  [        [        U SS5      =(       d    S5      5        U$ )	uL   Solo nombres citados en la respuesta al usuario, no en logs/código interno.outputNtypemessagecontentrN   rA   output_text)r8   getattrupdaterP   )responser<   rR   itemblockrN   s         r   &extract_filenames_from_response_outputr\   f   s    eEXx.4"F4&)3T9d39r9E5&$/52DLL4T:; :  
LL,WX}d-S-YWYZ[Lr   c                $  ^ U (       d  U $ U Vs0 s H  o"S   R                  5       US   _M     snmSU4S jjn[        R                  X05      n[        R                  SU5      n[        R                  " SSU5      nUR                  5       $ s  snf )zNQuita enlaces sandbox del texto; el usuario descarga con los botones de la UI.r   c                  > U R                  S5      R                  5       nU R                  S5      R                  5       nUR                  S5      (       d  SU;   d  U R                  S5      $ [        UR	                  S5      R                  S5      S   5      R                  nTR                  UR                  5       U5      nSU S	3$ )
Nr      zsandbox:z
/mnt/data/r   /zArchivo generado: u#    (usa el botón de descarga debajo))	rK   r*   
startswithr   rstripsplitr   getr#   )rO   labelurlr%   visibleby_names        r   replace_markdown_link;sanitize_reply_sandbox_links.<locals>.replace_markdown_link{   s    A$$&kk!n""$z**lc.A;;q>!

3--c2267<<++hnn.9#G9,OPPr   rA   z\n{3,}z

)rO   zre.Match[str]returnstr)r#   _MARKDOWN_LINK_REsubrI   rL   r*   )replyresponse_filesfrj   cleanedri   s        @r   sanitize_reply_sandbox_linksrt   t   s    5CD^y !F)+^DGQ  ##$9AG""2w/GffY0G==? Es    Bc           	     n   / n[        5       n[        U SS 5      =(       d    / nU GH  n/ n[        USS 5      S:X  a   [        [        USS 5      =(       d    / 5      nO0[        USS 5      S:X  a  [        [        USS 5      =(       d    / 5      nU H  n[        USS 5      =(       d    /  H  n[        USS 5      S:w  a  M  [        US	S 5      n[        US
S 5      n	[        USS 5      =(       d    Sn
U(       a  U	(       a  X;   a  M[  UR                  U5        UR	                  U	UU
S.5        M     M     GM     U$ )NrR   rS   rT   rU   code_interpreter_calloutputsr   container_file_citationfile_idcontainer_idr%   archivo)rz   ry   r%   )r8   rW   listr;   append)rY   	citationsseenrR   rZ   blocksr[   annry   rz   r%   s              r   _extract_container_citationsr      s)   &(IUDXx.4"F4&)3'$	48>B?FT64(,CC'$	48>B?FEumT:@b@3-1JJ!#y$7&sNDA"3
D9FYlgo!  (4#*$, A  . r   c                    [        U SS 5      =(       d    / nU H.  n[        USS 5      S:X  d  M  [        USS 5      nU(       d  M,  Us  $    [        U 5       H   nUR                  S5      (       d  M  US   s  $    g )NrR   rS   rv   rz   )rW   r   re   )rY   rR   rZ   rz   cites        r   #_extract_container_id_from_responser      sz    Xx.4"F4&*AA"4>L|##	 
 -X688N##'' 7 r   c                    U R                  [        R                  5      R                  [        R                  U:H  5      R                  5       nU Vs1 s H  o3S   (       d  M  US   iM     sn$ s  snf Nr   )queryr   r   filteragent_idalldbr   rowsr   s       r   _user_upload_display_namesr      sY    
,,-	''83	4	 	
 #-ds!fFCFd---s   A/#	A/c                N    [         R                  " SSU R                  5       5      $ )Nz
[^a-z0-9]+rA   )rL   ro   r#   )values    r   _normalize_name_tokenr      s    66-U[[]33r   c                   U R                  5       n[        [        U5      R                  5      nUR	                  S5      (       a?  U H9  n[        [        U5      R                  5      n[        U5      S:  d  M2  XS;   d  M9    g   U Hd  nUR                  5       U:X  a    g[        U5      R                  R                  5       nU(       d  ME  UR	                  S5      (       d  M]  Xb;   d  Md    g   g)uE   Detecta copias en el contenedor de archivos que el usuario ya subió.file-   TF)r#   r   r   r)   rb   r+   )r%   
user_namesr#   
normalizeddisplaytokenr)   s          r   _is_user_upload_mirrorr      s    NNE&tE{'7'78J  !G)$w-*<*<=E5zQ5#6 " ==?e#G}!!'')4E$$W--$-  r   c                $   U(       d  gU R                  5       n[        U5      R                  nU H]  nUR                  5       n[        U5      R                  nX%:X  d  UR                  SU 35      (       a    gU(       d  MQ  Xc;   d  X6;   d  M]    g   g)NF_T)r#   r   r)   r3   )r%   	mentionedr#   r)   r   nn_stems          r   _filename_matches_mentionr      sv    NNE;DJJLa:!A3006v~  r   c                \   U R                  5       nSnUR                  S5      (       a  US-  nOUR                  S5      (       a  US-  n[        X5      (       a  US-  nUR                  S5      (       a  US-  nUR                  S	5      (       a  US
-  nSU;   d  SU;   d  SU;   a  US-  nU$ )Nr   z.docx   z.pdfr'   (   informer   r      formatocuestionariocartilla2   )r#   r3   r   rb   )r%   r   r#   scores       r   _candidate_scorer      s    NNEE~~g			 55	""
  E^u4
e8KLr   c                $   U R                  [        R                  5      R                  [        R                  U:H  [        R                  R                  S 5      5      R                  5       nU Vs1 s H  o3S   (       d  M  US   iM     sn$ s  snf r   )r   r	   openai_file_idr   r   isnotr   r   s       r   _known_openai_file_idsr      ss    
'667	"++x7"1177=

 
 	 #-ds!fFCFd---s   0B	Bc                    U R                   R                  R                  R                  UUSS9nUR	                  5       $ )Ng      ^@)rz   timeout)
containersfilesrU   retrieveread)clientrz   ry   rU   s       r   _download_container_filer     s@    %%--66! 7 G
 <<>r   c               .    U R                   R                  R                  USS9n/ n[        5       n[        USS5      =(       d    /  GH  n[        USS5      nU(       a
  X;   d  X;   a  M$  [        USS5      =(       d    SR                  5       n	U	S	:X  a  MP  [        US
S5      =(       d    [        USS5      =(       d    Sn
U
(       a  [        [        U
5      5      R                  OSnU(       a  [        U5      (       d  M  UR                  U5        UR                  UUU[        [        USS5      =(       d    S5      U	=(       d    SS.5        GM     UR!                  S SS9  U$ ! [         a"  n[        R                  SX5        / s SnA$ SnAff = f)zALista archivos del contenedor que no son los uploads del usuario.d   )rz   limitz0No se pudo listar archivos del contenedor %s: %sNdatar   sourcerA   userpathr%   r   r   	generated)rz   ry   r%   r   r   c                &    U R                  SS5      $ )Nr   r   )re   r   s    r   rC   5_list_container_generated_citations.<locals>.<lambda>.  s    377<#;r   Tr/   )r   r   r|   	Exceptionloggerwarningr8   rW   r#   r   rm   r   r&   r;   r}   r   sort)r   rz   user_idspageexcr~   r   r   ry   r   r   r%   s               r   #_list_container_generated_citationsr   
  sc     &&++S+Q
 ')IUDtVT*0b0#tT*'/W-@#x.4";;=VsFD)QWS*d-KQr+/4D	?''R4X>> ,"$!'#|Q"?"D1E /K	
 1* NN;TNJ9  I<]	s   $E( (
F2F	FFr   c               :    [        U UU=(       d
    [        5       S9$ )zKFallback cuando el modelo no incluye container_file_citation en el mensaje.r   )r   r8   )r   rz   r   s      r   #_list_assistant_container_citationsr   2  s!     /"SU r   c          
        U(       d  g  [        U5      u  pg[	        U5        [        U5      U-  n	U	R                  R                  SSS9  U	R                  U5        [        R                  " 5       n
[        UUU[        U5      UUU
S9nU R                  U5        U R                  5         [        U5      $ ! [         a   n[        R                  SX85         S nAg S nAff = f)Nu$   Nombre de respuesta inválido %s: %sT)parentsexist_ok)r   r   r   r   openai_container_idr   r   )r   r
   r   r   r   r   parentmkdirwrite_bytesr   utcnowr	   r+   r;   flushr   )r   r   rU   r   rz   ry   storage_pathvisible_namer   destinationnowr   s               r   _save_response_bytesr   @  s     %@%N"
 "H%4KTD9G$
//
C
 !w<(C FF3KHHJs##+  =|Qs   B4 4
C>CCc           
     r   SSK Jn  U(       d  / $ U" 5       n[        U5      n[        X5      n[	        X5      n	U=(       d
    [        5       n
[        XbUS9n[        UUUU	U
S9nU(       d  U(       a	  US[         n/ nU Hb  nUS   nUS   n[        US   5      n [        UUU5      n[        U UUUUUS
9nU(       d  M@  UR                  U5        UR                  U5          O   U(       a  [        R!                  SUS   S   U5        U$ ! [         a#  n[        R                  S	UUU5         SnAM  SnAff = f)zHDescarga y guarda el archivo generado en cuanto existe en el contenedor.r   get_openai_clientr   r   	known_idsr   r   Nry   rz   r%   z?Captura temprana: no se pudo descargar %s del contenedor %s: %srU   r   rz   ry   u*   Captura temprana guardó %s para agente %sr   ))app.backend.services.openai_agent_servicer   r8   r   r   r   _pick_candidatesMAX_SAVED_FILES_PER_CHATr   r   r   r   r   r   r;   r}   info)r   r   rz   user_openai_file_idsr   r   r   r   r   r   mention_setr~   pickssavedmetary   cite_containerr   rU   r   r   s                        r   try_capture_from_containerr   e  s[    L	 F'(H&r4I+B9J$suK3FS[\IE Y334"$Ey/n-(j)9:		.v~wOG #%'
 3MM'"LL3 4 8!HV	

 L5  	NNQ	 	s   D		
D6D11D6c               T  ^ / nU  Hc  nUS   nUR                  S5      =(       d    SnXq;   d  Xr;   a  M.  [        X5      (       a  M@  [        U5      (       d  MR  UR                  U5        Me     U(       d  U (       a	  U S [         nU(       d  / $ UR                  U4S jSS9  US [         $ )Nry   r%   r{   c                L   > [        U R                  S5      =(       d    ST5      $ )Nr%   rA   )r   re   )r   r   s    r   rC   "_pick_candidates.<locals>.<lambda>  s    .swwz/B/Hb)Tr   Tr/   )re   r   r&   r}   r   r   )	r~   r   r   r   r   poolr   ry   r%   s	       `    r   r   r     s     "$Dy/88J'49'"6!(77$X..D  I223	IIT^bIc))**r   )early_savedc          
     8   U(       a	  US[          $ SSKJn  U=(       d    [        U5      nU(       d  [        R                  SU5        / $ U" 5       n[        X5      n[        U5      n	[        X5      n
[        U5      n[        U5      nU(       d1  [        XsU	S9nU(       a   [        R                  SU[        U5      5        [        UU	UU
US9nU(       d,  [        R                  SU[        U5      [        U5      5        / $ / nU Hc  nUS	   nUS
   n[!        US   5      n [#        UUU5      n['        U UUUUUS9nU(       d  M@  UR)                  U5        UR+                  U5          U$    U$ ! [$         a"  n[        R                  SUU5         SnAM  SnAff = f)u=   Guarda solo el archivo nuevo que el modelo generó (máx. 1).Nr   r   zApersist_code_interpreter_outputs: sin container_id para agente %sr   zQpersist_code_interpreter_outputs: usando listado del contenedor (agente=%s, n=%s)r   z]persist_code_interpreter_outputs: sin archivo guardable (agente=%s, mencionados=%s, citas=%s)ry   rz   r%   z2No se pudo descargar archivo %s del contenedor: %sr   )r   r   r   r   r   r   r   r8   r   r\   r   r   r   r+   r   r9   r   r   r   r   r;   r}   )r   r   rY   rz   r   r   r   r   r   r   r   r   r~   r   r   r   ry   r   r   rU   r   r   s                         r    persist_code_interpreter_outputsr     s    4455KP#Fx#PLZ\de	 F&r4I'(H+B9J6x@I,X6I7W_`	KKcI E k9	N		
 	"$Ey/n-(j)9:	.v~wOG
 #%'
 3MM'"LLL/ . L#  	NNOQXZ]^	s    E--
F7FF)r   r	   rl   zdict[str, Any])r%   rm   rl   r$   )r   rm   rl   r$   )r<   set[str]rl   r   )r<   r   rl   rm   )rN   rm   rl   r   )rY   r   rl   r   )rp   rm   rq   list[dict[str, Any]]rl   rm   )rY   r   rl   list[dict[str, str]])rY   r   rl   
str | None)r   r   r   rm   rl   r   )r   rm   rl   rm   )r%   rm   r   r   rl   r$   )r%   rm   r   r   rl   r$   )r%   rm   r   r   rl   r   )r   r   rz   rm   ry   rm   rl   bytes)r   r   rz   rm   r   r   rl   r   )r   r   rz   rm   r   set[str] | Nonerl   r   )r   r   r   rm   rU   r   r   rm   rz   rm   ry   rm   rl   zdict[str, Any] | Noner!   )r   r   r   rm   rz   rm   r   	list[str]r   r   rl   r   )r~   r   r   r   r   r   r   r   r   r   rl   r   )r   r   r   rm   rY   r   rz   r   r   r   r   zlist[dict[str, Any]] | Nonerl   r   )6__doc__
__future__r   loggingrL   r   pathlibr   typingr   sqlalchemy.ormr   app.backend.db.modelsr   r	   app.backend.utils.agent_filesr
   r   r   r   r   r   	getLogger__name__r   r   compilerM   rI   rn   r   r&   r,   r-   r?   rG   rP   r\   rt   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r    r   r   <module>r     sB   E "  	    " H  
		8	$ ::-MM  JJ9: :
  $@- ,<
.4$$	.%%% 	%
 %X !%	 	
 "$"$"$ 	"$
 "$ "$ "$ "$T "&??? ? $	?
 ? ?D+#+ + 	+
 + + +J 04MMM M 	M
 $M -M Mr   