
     uhj                        S r SSKJr  SSKrSSKrSSKrSSKJr  SSKJrJ	r	J
r
  SSKJr  SSKJrJrJr  SS	KJr  SS
 jrSS jrSS jrSS jr\ " S S5      5       r " S S5      rg)z8Storage utilities for writing conversation logs to disk.    )annotationsN)	dataclass)datetimetimezone	timedelta)Path)DictListOptional   )LoggerConfigc                $    U R                  SSS9  g )NT)parentsexist_ok)mkdir)paths    )/root/racknerd_01/codex_logger/storage.py_ensure_dirr      s    JJtdJ+    c                 J    [         R                  " [        R                  5      $ N)r   nowr   utc r   r   _utc_nowr      s    <<%%r   c                    [        U R                  5       5      nX"U-  -
  n[        R                  " U[        R
                  S9$ )N)tz)int	timestampr   fromtimestampr   r   )tsseconds	epoch_sec
window_secs       r   _window_startr%      s6    BLLN#I'12J!!*>>r   c                $    U R                  U5      $ r   )strftime)r!   fmts     r   _stampr)      s    ;;sr   c                      \ rS rSr% S\S'   S\S'   S\S'   S\S'   SrS	\S
'   SrS	\S'   SrS	\S'   SrS\S'   Sr	S\S'   SS jr
Srg)LogEntry"   r   
turn_indexstrr   roletextNzOptional[str]
session_idconversation_idchannelzOptional[Dict[str, object]]metadatazOptional[Dict[str, int]]token_usagec                   U R                   U R                  U R                  U R                  S.nU R                  b  U R                  US'   U R
                  b  U R
                  US'   U R                  b  U R                  US'   U R                  (       a  U R                  US'   U R                  b  U R                  US'   U$ )N)r-   r   r/   r0   r1   r2   r3   r4   r5   )	r-   r   r/   r0   r1   r2   r3   r4   r5   )selfdatas     r   to_dictLogEntry.to_dict.   s    //IIII	#
 ??&!%D+&*&:&:D"#<<#"llDO==#}}D'"&"2"2Dr   r   )returnDict[str, object])__name__
__module____qualname____firstlineno____annotations__r1   r2   r3   r4   r5   r9   __static_attributes__r   r   r   r+   r+   "   sO    ON
I
I $J$%)O])!G]!,0H)0,0K)0r   r+   c                  r    \ rS rS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SS
 jrSS jrSrg)ConversationStorageB   zABuffers conversation entries and writes them to daily JSON files.c                    Xl         / U l        SU l        SU l        [        R
                  " 5       U l        [        R                  " 5       U l	        S U l
        g )Nr   )config_buffer_buffer_bytes_turn_counter	threadingLock_locktime	monotonic_last_flush_current_window_start)r7   rG   s     r   __init__ConversationStorage.__init__E   sC    02^^%
>>+9="r   c                   U R                      U =R                  S-  sl        U R                  Ul        UR                  5       n[        R
                  " USS9R                  S5      nU R                  R                  U5        U =R                  [        U5      -  sl	        U R                  5         S S S 5        g ! , (       d  f       g = f)Nr   F)ensure_asciiutf-8)rM   rJ   r-   r9   jsondumpsencoderH   appendrI   len_maybe_flush_locked)r7   entrypayloadencodeds       r   	add_entryConversationStorage.add_entryN   s    ZZ!##11EmmoGjju=DDWMGLL(#g,.$$& ZZs   B$B::
Cc                    [         R                  " 5       nU R                  R                  nU R                  UR
                  :  d  XR                  -
  UR                  :  a  U R                  5         g g r   )	rN   rO   rG   flushrI   max_buffer_bytesrP   max_interval_seconds_flush_locked)r7   r   flush_policys      r   r\   'ConversationStorage._maybe_flush_lockedX   sZ    nn{{((,"?"??%%%)J)JJ  Kr   c                p    U R                      U R                  5         S S S 5        g ! , (       d  f       g = fr   )rM   rf   )r7   s    r   rc   ConversationStorage.flusha   s    ZZ  ZZs   '
5c                b   U R                   (       d  [        R                  " 5       U l        g [	        5       nU R
                  R                  n[        XR                  5      nU R                  b  X0R                  :w  a  X0l	        SU l
        U R                  U5      nU R                  U5      n[        UR                  5        UR                  UR                   U R
                  R"                  -   5      nUR%                  SSS9 n[&        R(                  " XWSSS9  UR+                  S5        S S S 5        UR-                  U5        U R                   R/                  5         SU l        [        R                  " 5       U l        UR2                  b  U R5                  U5        g g ! , (       d  f       Nz= f)	Nr   wrV   encodingF   )rU   indent
)rH   rN   rO   rP   r   rG   rotationr%   window_secondsrQ   rJ   _current_file_path_build_payloadr   parentwith_suffixsuffix
tmp_suffixopenrW   dumpwritereplaceclearrI   retention_days_cleanup_old_files)r7   r   rr   window_start	file_pathr^   	temp_pathhandles           r   rf   !ConversationStorage._flush_lockede   sK   ||#~~/Dj;;''$S*A*AB%%-A[A[1[)5&!"D++L9	%%l3I$$%)))*:*:T[[=S=S*ST	^^C'^2fIIgE!DLL 3 	)$>>+"".##C( / 32s   (F  
F.c                    [        XR                  R                  5      nU R                  R                  R	                  US9nU R                  R
                  U-  $ )N)stamp)r)   rG   stamp_formatfilename_templateformatlog_dir_path)r7   r   r   filenames       r   rt   &ConversationStorage._current_file_path~   sH    |[[%=%=>;;0077e7D{{''(22r   c                    U R                  U5      nU R                  U5      nUR                  U R                  5        UR                  UR                  5       U R                  R                  R                  US.nU$ )N)file_idcreated_utcrotation_window_secentries)	rt   _load_existing_entriesextendrH   stem	isoformatrG   rr   rs   )r7   r   r   r   r^   s        r   ru   "ConversationStorage._build_payload   si    ++L9	--i8t||$ ~~'113#';;#7#7#F#F	&
 r   c                *   UR                  5       (       d  / $  UR                  SSS9 n[        R                  " U5      nS S S 5        WR	                  S5      n[        U[        5      (       a  U$  / $ ! , (       d  f       N9= f! [         a     / $ f = f)NrrV   rm   r   )existsrz   rW   loadget
isinstancelist	Exception)r7   r   r   r8   r   s        r   r   *ConversationStorage._load_existing_entries   s    !!I	g6&yy( 7hhy)G'4(( ) 	 76
  			s(   B A3 /B 3
B=B 
BBc                Z   U R                   R                  R                  nUc  g U[        US9-
  nU R                   R                  R                  S5       HA  n UR                  5       R                  UR                  5       :  a  UR                  SS9  MA  MC     g ! [         a     MS  f = f)N)daysz*.jsonT)
missing_ok)rG   rr   r   r   r   globstatst_mtimer   unlinkr   )r7   r   r   cutoffr   s        r   r   &ConversationStorage._cleanup_old_files   s    --<<!yn55KK,,11(;D99;''&*:*:*<<KK4K0 = <  s   ;B
B*)B*)rH   rI   rQ   rP   rM   rJ   rG   N)rG   r   r;   None)r]   r+   r;   r   )r;   r   )r   r   r;   r   )r   r   r;   r<   )r   r   r;   zList[Dict[str, object]])r   r   r;   r   )r=   r>   r?   r@   __doc__rR   r`   r\   rc   rf   rt   ru   r   r   rB   r   r   r   rD   rD   B   s2    K>'!!)23


r   rD   )r   r   r;   r   )r;   r   )r!   r   r"   r   r;   r   )r!   r   r(   r.   r;   r.   )r   
__future__r   rW   rK   rN   dataclassesr   r   r   r   pathlibr   typingr	   r
   r   rG   r   r   r   r%   r)   r+   rD   r   r   r   <module>r      sb    > "    ! 2 2  ' '  ,&?   >d dr   