
    i/                         d Z ddlZ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m	Z	 ddl
mZ ddlmZmZmZ ddlmZmZmZ dZe G d d	             Z G d
 d      ZdedefdZdededefdZdee   defdZy)z-Attachment storage and serialization helpers.    N)	dataclassfield)Path)AnyDictOptional)AttachmentRefMessageBlockMessageBlockTypei   c                       e Zd ZU dZeed<   ej                  Zeed<   dZ	e
e   ed<    ee      Zeeef   ed<   deeef   fd	Zed
eeef   dd fd       ZdefdZy)AttachmentRecordzBStores metadata about an attachment tracked inside a workflow run.refkindNdescription)default_factoryextrareturnc                     | j                   j                         | j                  j                  | j                  | j
                  dS )Nr   r   r   r   )r   to_dictr   valuer   r   selfs    >/Users/bowang/.openclaw/workspace/ChatDev/utils/attachments.pyr   zAttachmentRecord.to_dict   s7    88##%IIOO++ZZ	
 	
    datac                 X   |j                  d      xs i }|j                  dt        j                  j                        }	 t        |      } | t        j                  |      ||j                  d      |j                  d      xs i       S # t        $ r t        j                  }Y \w xY w)Nr   r   r   r   r   )getr   FILEr   
ValueErrorr	   	from_dict)clsr   ref_dataraw_kindr   s        r   r!   zAttachmentRecord.from_dict#   s    88E?(b88F$4$9$9$?$?@	)#H-D ''1/((7#)r	
 	
  	)#((D	)s   B B)(B)c                     t        | j                  | j                  j                         t	        | j
                              S )z6Convert to a MessageBlock referencing this attachment.)type
attachmentr   )r
   r   r   copydictr   r   s    r   as_message_blockz!AttachmentRecord.as_message_block2   s/    xx}}djj!
 	
r   )__name__
__module____qualname____doc__r	   __annotations__r   r   r   r   r   strr   r)   r   r   r   r   classmethodr!   r
   r*    r   r   r   r      s    L	-22D
2!%K#%!$7E4S>7
c3h 
 
T#s(^ 
0B 
 

, 
r   r   c                   x   e Zd ZdZefdeez  deddfdZe	j                  ddddddddd		d
eez  de	dee   dee   dee   dedee   deeeef      dededefdZe	j                  ddddddddeez  de	dee   dee   dee   dee   deeeef      dedefdZdde	j                  ddddddededee   dee   de	dee   dee   deeeef      dedefdZdededdfdZdededz  fdZdedefdZdeeef   fd Zdeeef   fd!Zd"ee   ded#ee   dee   fd$Zddd%d&edededefd'Zd*d(Zd*d)Zy)+AttachmentStorez?Filesystem-backed attachment manifest for a workflow execution.root_dirinline_size_limitr   Nc                     t        |      | _        || _        | j                  j                  dd       | j                  dz  | _        i | _        t               | _        i | _        | j                          y )NTparentsexist_okzattachments_manifest.json)
r   rootr6   mkdirmanifest_path_recordsset_persistent_ids_hash_index_load_manifest)r   r5   r6   s      r   __init__zAttachmentStore.__init__>   s`    N	!2		t4!YY)DD57),+-r   TF)	r   display_name	mime_typeattachment_id	copy_filer   r   persistdeduplicate	file_pathr   rD   rE   rF   rG   r   r   rH   rI   c       	   
         t        |      }|j                         st        d|       |xs& t        j                  |j
                        d   xs d}|xs t        j                         j                  }t        |      }|
r| j                  |||      }|r|S |rH| j                  |z  }|j                  dd       ||j
                  z  }t        j                  ||       n|j                         }|j!                         j"                  }|xs t        |      }d}t%        |||xs |j
                  ||t'        |      |      }t)        ||||rt+        |      ni 	      }|| j,                  |<   |r|| j.                  |<   |	r-| j0                  j3                  |       | j5                          |S | j0                  j7                  |       |S )
z7Register a local file and return its attachment record.zAttachment source not found: r   zapplication/octet-stream)rG   source_pathTr8   N)rF   rE   namesizesha256
local_pathdata_urir   )r   existsFileNotFoundError	mimetypes
guess_typerM   uuiduuid4hex_sha256_file_find_duplicate_by_hashr;   r<   shutilcopy2resolvestatst_sizer	   r0   r   r)   r>   rA   r@   add_save_manifestdiscard)r   rJ   r   rD   rE   rF   rG   r   r   rH   rI   sourceguessed_mimesha256_sourceexisting
target_dirtarget_pathrN   rO   rQ   r   records                         r   register_filezAttachmentStore.register_fileH   s    i}}#&CF8$LMM hY%9%9&++%Fq%I%gMg%9)9)9$V,33#" 4 H
 ]2JTD9$v{{2KLL- ..*K!));,{"; '",;'
 "#!&$u+B	
 (.m$'4DV$  $$]3!    ((7r   )r   rE   rD   rF   r   r   rH   r   c                   t        |t        t        f      st        d      |xs t	        j
                         j                  }|xs t        |      }	| j                  |z  }
|
j                  dd       |
|	z  }|j                  d      5 }|j                  t        |             ddd       | j                  |||xs |	||d|||	      S # 1 sw Y   'xY w)z/Register an in-memory payload as an attachment.z.register_bytes expects bytes or bytearray dataTr8   wbNF)r   rD   rE   rF   rG   r   r   rH   )
isinstancebytes	bytearray	TypeErrorrV   rW   rX   _default_filename_for_mimer;   r<   openwriterj   )r   r   r   rE   rD   rF   r   r   rH   filenamerg   rh   handles                r   register_byteszAttachmentStore.register_bytes   s     $	 23LMM%9)9)9H#=i#HYY.
5 8+d#vLLt% $ !!%1'# " 

 
	
 $#s   CC)rE   rN   r   rF   r   r   rH   remote_file_idrM   rN   c       	            |xs t        j                         j                  }t        |||||      }
t	        |
|||xs i       }|| j
                  |<   |	r,| j                  j                  |       | j                          n| j                  j                  |       |
j                  r|| j                  |
j                  <   |S )z9Register an already-uploaded file (e.g., OpenAI file ID).)rF   rE   rM   rN   rw   r   )rV   rW   rX   r	   r   r>   r@   r`   ra   rb   rO   rA   )r   rw   rM   rE   rN   r   rF   r   r   rH   r   ri   s               r   register_remote_filez$AttachmentStore.register_remote_file   s     &9)9)9')
 "c+UZU`^`a'-m$  $$]3!  ((7::+8DSZZ(r   c                     | j                   j                  |      }|st        d| d      ||j                  _        || j
                  v r| j                          yy)z?Attach a provider file_id to an existing record (after upload).Attachment '' not foundN)r>   r   KeyErrorr   rw   r@   ra   )r   rF   rw   ri   s       r   update_remote_file_idz%AttachmentStore.update_remote_file_id   sX    ""=1\-DEE$2

!D000! 1r   c                 8    | j                   j                  |      S N)r>   r   )r   rF   s     r   r   zAttachmentStore.get   s    }}  //r   c                 z    | j                   j                  |      }|st        d| d      |j                         S )Nr{   r|   )r>   r   r}   r*   r   rF   ri   s      r   to_message_blockz AttachmentStore.to_message_block   s<    ""=1\-DEE&&((r   c                 ,    t        | j                        S r   )r)   r>   r   s    r   list_recordszAttachmentStore.list_records   s    DMM""r   c                     | j                   j                         D ci c]$  \  }}|| j                  v r||j                         & c}}S c c}}w r   )r>   itemsr@   r   r   s      r   export_manifestzAttachmentStore.export_manifest   sU     *.)<)<)>
)>%v 4 44 6>>++)>
 	
 
s   )ArO   rL   c                r   |sy | j                   j                  |      }|sy | j                  j                  |      }|s| j                   j                  |d        y |sJ|H|j                  j
                  }|sy 	 t        |      j                         |j                         k7  ry 	 |S |S # t        $ r Y y w xY wr   )	rA   r   r>   popr   rP   r   r]   rS   )r   rO   rG   rL   existing_idri   existing_paths          r   rZ   z'AttachmentStore._find_duplicate_by_hash   s     &&**62"";/  .[4"JJ11M &..0K4G4G4II J v % s   :*B* *	B65B6)rG   rH   ri   c                $   |j                   }|j                  xs t        j                         j                  }|j                         }||_        |j                  }|rt|rrt        |      }|j                         rW| j                  |z  }	|	j                  dd       |	|j                  z  }
t        j                  ||
       t        |
      |_        t        ||j                   |j"                  t%        |j&                              | j(                  |<   |r,| j*                  j-                  |       | j/                          n| j*                  j1                  |       |j2                  r|| j4                  |j2                  <   | j(                  |   S )z
        Import an existing attachment record (e.g., from a session upload) into this store.
        Optionally copies the underlying file into the store directory.
        Tr8   r   )r   rF   rV   rW   rX   r(   rP   r   rR   r;   r<   rM   r[   r\   r0   r   r   r   r)   r   r>   r@   r`   ra   rb   rO   rA   )r   ri   rG   rH   
source_refrF   new_refrP   rL   rg   rh   s              r   ingest_recordzAttachmentStore.ingest_record  sD    ZZ
"00DDJJL4D4D//# -**
)z*K!!#!YY6
   =(;+;+;;[+6%(%5"'7**v||$	(
m$   $$]3!  ((7>>/<DW^^,}}]++r   c                    | j                   j                         sy 	 t        j                  | j                   j	                  d            }|j                         D ]  \  }}	 t        j                  |      }|| j                  |<   | j                  j                  |       |j                  j                  s]|| j                  |j                  j                  <    y # t        j
                  $ r Y y w xY w# t        $ r Y w xY w)Nutf-8encoding)r=   rR   jsonloads	read_textJSONDecodeErrorr   r   r!   	Exceptionr>   r@   r`   r   rO   rA   )r   r   rF   record_datari   s        r   rB   zAttachmentStore._load_manifest4  s    !!((*	::d00::G:LMD +/**,&M;)33K@ ,2DMM-(  $$]3zz  6C  !2!23 +7 ## 		
  s#   /C #C8C54C58	DDc                     | j                         }| j                  j                  t        j                  |dd      d       y )NF   )ensure_asciiindentr   r   )r   r=   
write_textr   dumps)r   
serializeds     r   ra   zAttachmentStore._save_manifestE  s8    ))+
%%djj%XY&Zel%mr   )r   N)r+   r,   r-   r.   DEFAULT_INLINE_LIMITr   r0   intrC   r   r   r   boolr   r   r   rj   rn   ro   rv   ry   r~   r   r
   r   r   r   rZ   r   rB   ra   r2   r   r   r4   r4   ;   s   IFZ   _c  "2!6!6&*#''+%)*.!D#:D 	D
 smD C=D  }D D c]D S#X'D D D 
DT "2!6!6#'&*'+%)*.$
i$
 	$

 C=$
 sm$
  }$
 c]$
 S#X'$
 $
 
$
V $("!1!6!6'+%)*.  	
 C= sm   } c] S#X'  
B"3 " "PT "0 0)9D)@ 0)c )l )#d3(8#89 #
c3h 
 	
 d^ 
"	#> &, &, 	&,
 &, 
&,PD"nr   r4   pathr   c                    t        j                         }| j                  d      5 t        fdd      D ]  }|j	                  |        	 d d d        |j                         S # 1 sw Y   |j                         S xY w)Nrbc                  &     j                  d      S )Ni   )read)ru   s   r   <lambda>z_sha256_file.<locals>.<lambda>M  s    &++k":r   r   )hashlibrO   rr   iterupdate	hexdigest)r   hasherchunkru   s      @r   rY   rY   J  sh    ^^F	4F:C@EMM%  A 
  
 s   &A&&A>rE   c                 z    | j                         }t        j                  |      j                  d      }d| d| S )Nr   zdata:z;base64,)
read_bytesbase64	b64encodedecode)r   rE   r   encodeds       r   encode_file_to_data_urir   R  s<    ??Dt$++G4G9+XgY//r   c                 @    | rt        j                  |       }|rd| S y)Nr'   zattachment.bin)rT   guess_extension)rE   exts     r   rq   rq   X  s(    ''	2u%%r   )r.   r   r   r   rT   r[   rV   dataclassesr   r   pathlibr   typingr   r   r   entity.messagesr	   r
   r   r   r   r4   r0   rY   r   rq   r2   r   r   <module>r      s    3       (  & & I I!  %
 %
 %
PLn Ln^t  0$ 03 03 0(3- C r   