
    *j!'                       U d Z ddlm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	 ddl
mZ dZ ej        d          Zi Zded	<    ej                    Zh d
ZdZdZdZd?dZd@dZdAdBdZdCdZdDdZdEd ZdFd#ZdGd$ZdHd'ZdId)Z 	 dAdddd*dJd0Z! G d1 d2          Z"ddd3dKd5Z#dLd8Z$dd9dMd:Z%dd9dNd<Z&dd=dOd>Z'dS )PzAppend-only WebUI run event journal helpers.

This is the first #1925 journal/replay slice.  It mirrors SSE events emitted by
the existing in-process streaming path without changing execution ownership.
    )annotationsN)Path)Iterable_run_journalz^[A-Za-z0-9_.-]+$z*dict[tuple[str, str, str], threading.Lock]_WRITER_LOCKS>   doneerrorcancelapperror
stream_endHERMES_WEBUI_RUN_JOURNAL_FSYNCeagerzterminal-onlyreturnr   c                 ,    ddl m}  t          |           S )Nr   SESSION_DIR)
api.modelsr   r   r   s    2/Users/bertmahoney/hermes-webui/api/run_journal.py_default_session_dirr      s"    &&&&&&    valuestrfieldc                    t          | pd                                          }|r"d|v sd|v st                              |          st	          d|           |S )N /\zinvalid )r   strip_SAFE_ID_RE	fullmatch
ValueError)r   r   cleaneds      r   _validate_idr#       sf    %+2$$&&G -cWnn{?T?TU\?]?]+E++,,,Nr   
session_idrun_idsession_dirPath | Nonec                    t          | d          }t          |d          }|t          |          nt                      }|t          z  |z  | dz  S )Nr$   r%   .jsonl)r#   r   r   RUN_JOURNAL_DIR_NAME)r$   r%   r&   sidridroots         r   	_run_pathr.   '   sZ    
z<
0
0C
vx
(
(C + 74=Q=S=SD&&,#~~~==r   paththreading.Lockc                .   t          | j                  | j        t          t          j                              f}t
          5  t                              |          }|t          j	                    }|t          |<   |cd d d            S # 1 swxY w Y   d S N)
r   parentnameosgetpid_WRITER_LOCKS_GUARDr   get	threadingLock)r/   keylocks      r   	_lock_forr=   .   s    t{TYBIKK(8(8
9C	    %%<>##D!%M#                 s   ;B

BBtuple[list[dict], list[dict]]c                   g }g }	 |                      d                                          }n# t          $ r ||fcY S w xY wt          |d          D ]\  }}|                                s	 t          j        |          }n-# t
          j        $ r |                    ||d           Y Yw xY wt          |t                    r|                    |           |                    ||d           ||fS )Nutf-8encoding   )start)lineraw)	read_text
splitlinesFileNotFoundError	enumerater   jsonloadsJSONDecodeErrorappend
isinstancedict)r/   events	malformedlinesline_norF   parseds          r   _read_jsonlrV   8   s7   FI!00;;== ! ! !y    !!%q111 < <yy{{ 		Z__FF# 	 	 	gc::;;;H	 fd## 	<MM&!!!!gc::;;;;9s    (/ A A /B'B.-B.intc                j    t          |           \  }}d |D             }|rt          |          dz   ndS )Nc                    g | ]N}t          |                    d           t                    *t          |                    d           pd          OS seqr   )rO   r8   rW   .0events     r   
<listcomp>z_next_seq.<locals>.<listcomp>P   sN    ```5jSXIYIY[^>_>_`C		%  %A&&```r   rC   )rV   max)r/   rQ   
_malformedseqss       r   	_next_seqrc   N   s@    $T**FJ``F```D")CIIMM)r   
event_name
str | Nonec                >   t          | pd          }|dk    s|dk    rdS |dk    rdS |dv rqt          |t                    rJt          |pi                     d          pd                                                                          nd}|d	v rdS |d
k    rdS dS d S )Nr   r   r   	completedr
   zinterrupted-by-user>   r	   r   type>   canceled	cancelledinterruptedzinterrupted-by-crasherrored)r   rO   rP   r8   r   lower)rd   payloadr4   err_types       r   _terminal_state_for_eventrp   T   s    zR  Dv~~--{x$$$$$MWX_aeMfMfn32**6228b99??AAGGIIIln000((}$$))y4r   c                     t           j                            t          t                    } t          | pd                                                                          }|t          t          hv r|S t          S )Nr   )	r5   environr8   _FSYNC_MODE_ENV_FSYNC_MODE_TERMINAL_ONLYr   r   rm   _FSYNC_MODE_EAGER)rF   modes     r   _run_journal_fsync_moderw   d   s\    
*..*C
D
DCsyb>>!!''))D!#<===$$r   terminal_stateboolc                R    t                      t          k    rdS t          |           S )NT)rw   ru   ry   )rx   s    r   _should_fsync_eventr{   l   s'      $555tr   Nonec                
   	 t          j        | j        t          t           dd                    }	 t          j        |           t          j        |           d S # t          j        |           w xY w# t          $ r Y d S w xY w)NO_DIRECTORYr   )r5   openr3   getattrfsynccloseOSError)r/   dir_fds     r   _fsync_parent_dirr   r   s    gb-&C&CDD	HVHVBHV   s(   .A4 A A4 A11A4 4
BB)r&   r[   
created_atr[   
int | Noner   float | NonerP   c               N   t          | ||          }||ni }t          |pd                                          }|st          d          t	          |          5  |t          |          nt          |          }t          ||          }	d| d| |t          |          t          |           ||t          ||nt          j	                              t          |	          |	|d}
|j                            dd	           |                                 }t          j        |
d
d          dz   }t!          j        |t           j        t           j        z  t           j        z  d          }t!          j        |dd          5 }|                    |           |                                 t1          |	          r&t!          j        |                                           ddd           n# 1 swxY w Y   |rt7          |           |
cddd           S # 1 swxY w Y   dS )zJAppend one durable run event and fsync it according to the journal policy.r&   Nr   zevent_name is requiredrC   :)versionevent_idr[   r%   r$   r^   rh   r   terminalrx   rn   T)parentsexist_okF),r   )ensure_ascii
separators
i  ar@   rA   )r.   r   r   r!   r=   rW   rc   rp   floattimery   r3   mkdirexistsrK   dumpsr5   r   O_CREATO_APPENDO_WRONLYfdopenwriteflushr{   r   filenor   )r$   r%   rd   rn   r&   r[   r   r/   assigned_seqrx   r^   created_filerE   fdfhs                  r   append_run_eventr   }   s    Z[AAAD ,gg"GZ%2&&,,..J 31222	4  #&?s3xxx	$2:wGG!22L22&kkj//j.D

$)++VV^,,,
 
 	$666;;==(z%e
KKKdRWT2:3bkA5IIYr3111 	&RHHTNNNHHJJJ">22 &%%%		& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	&
  	$d###7                 s8   D)HAG0$H0G4	4H7G4	8HH!Hc                  *    e Zd ZdZdddd	ZdddZdS )RunJournalWriterz)Stateful writer for one WebUI stream/run.Nr   r$   r   r%   r&   r'   c               z   t          |d          | _        t          |d          | _        |t          |          nd | _        t          | j        | j        | j                  | _        t          | j                  | _        | j        5  t          | j                  | _	        d d d            d S # 1 swxY w Y   d S )Nr$   r%   r   )
r#   r$   r%   r   r&   r.   _pathr=   _lockrc   )selfr$   r%   r&   s       r   __init__zRunJournalWriter.__init__   s    &z<@@"68440;0G4,,,TtIYZZZ
tz**
Z 	3 	3&tz22DN	3 	3 	3 	3 	3 	3 	3 	3 	3 	3 	3 	3 	3 	3 	3 	3 	3 	3s   	B00B47B4rd   r   rP   c                    | j         5  | j        }| xj        dz  c_        d d d            n# 1 swxY w Y   t          | j        | j        ||pi | j        |          S )NrC   )r&   r[   )r   rc   r   r$   r%   r&   )r   rd   rn   r[   s       r   append_sse_eventz!RunJournalWriter.append_sse_event   s    Z 	  	 .CNNaNN	  	  	  	  	  	  	  	  	  	  	  	  	  	  	   OKMr(
 
 
 	
s   ,00)r$   r   r%   r   r&   r'   r2   )rd   r   r   rP   )__name__
__module____qualname____doc__r   r    r   r   r   r      sT        33SW 3 3 3 3 3 3
 
 
 
 
 
 
r   r   )	after_seqr&   r   c                   t          | ||          }t          |          \  }}fd|D             }t          |           t          |          ||dS )Nr   c                ~    g | ]9}t          |                    d           pd          t                    k    7|:S rZ   )rW   r8   )r]   r^   r   s     r   r_   z#read_run_events.<locals>.<listcomp>   sC    [[[Es599U3C3C3Hq/I/ICPYNN/Z/Z%/Z/Z/Zr   )r$   r%   rQ   rR   )r.   rV   r   )r$   r%   r   r&   r/   rQ   rR   s     `    r   read_run_eventsr      sq     Z[AAAD#D))FI[[[[V[[[*oof++	  r   rQ   Iterable[dict]c                   d |D             }|r|d         nd }d |D             }t          d t          |          D             |r|d         nd           }|r|                    d          n|rdnd}t          |           t          |          t          |          t	          |          t          |pi                     d          pd	          |pi                     d
          t          |          ||pi                     d          d	S )Nc                <    g | ]}t          |t                    |S r   )rO   rP   r\   s     r   r_   z(_summary_from_events.<locals>.<listcomp>   s'    DDDJud,C,CDuDDDr   c                <    g | ]}|                     d           |S )r   r8   r\   s     r   r_   z(_summary_from_events.<locals>.<listcomp>   s)    KKKUYYz5J5JKuKKKr   c              3  L   K   | ]}|                     d           dk    |V   dS )r^   r   Nr   r\   s     r   	<genexpr>z'_summary_from_events.<locals>.<genexpr>   s8      \\579K9K|9[9[9[9[9[9[\\r   rx   runningunknownr[   r   r   r^   )	r$   r%   	stream_idevent_countlast_seqlast_event_idr   rx   
last_event)nextreversedr8   r   lenrW   ry   )r$   r%   rQ   orderedlastterminal_eventsr   statuss           r   _summary_from_eventsr      s'   DD&DDDG!+72;;tDKK'KKKO\\H_55\\\.8D H 08bX\\*+++7>aiiXaF*oof++[[7||((//4155*"))*55NN zr&&w//
 
 
r   r   c               r    t          | ||          }t          | ||                    d          pg           S )Nr   rQ   )r   r   r8   )r$   r%   r&   journals       r   latest_run_summaryr      s9    j&kJJJG
FGKK4I4I4ORPPPr   dict | Nonec               8   t          | d          }|t          |          nt                      }|t          z  }|                    d| d          D ]F}|j        j        }t          |          \  }}t          |||          }	t          |          |	d<   |	c S d S )Nr%   z*/r)   r/   )
r#   r   r   r*   globr3   r4   rV   r   r   )
r%   r&   r,   r-   journal_rootr/   r$   rQ   ra   summarys
             r   find_run_summaryr      s    
vx
(
(C + 74=Q=S=SD..L!!"2s"2"2"233  [%
(..
&z3??d))4r   )r   c               x   t          | |          }|                    d          s|                    d          sd S t          |                    d          pd          dz   }||t          |          k    rd S ddd| ||                    d          d	}d| d
| ||| ddt          j                    dd|ddS )Nr   r   r   r   rC   rk   z1The live worker stopped before this run finished.zqThe transcript was restored to the last journaled event. Start a new turn if you still need the task to continue.)rh   messagehintr$   r   journal_last_seqr   r   Tzlost-worker-bookkeeping)r   r   r[   r%   r$   r^   rh   r   r   rx   rn   	synthetic)r   r8   rW   r   )r$   r%   r   r   r[   rn   s         r   stale_interrupted_eventr      s     V44G{{: gkk-&@&@ t
gkk*%%*
+
+a
/CI!6!6tF D #KK
33 G %%%% ikk3  r   )r   r   )r   r   r   r   r   r   r2   )r$   r   r%   r   r&   r'   r   r   )r/   r   r   r0   )r/   r   r   r>   )r/   r   r   rW   )rd   r   r   re   )r   r   )rx   re   r   ry   )r/   r   r   r|   )r$   r   r%   r   rd   r   r&   r'   r[   r   r   r   r   rP   )
r$   r   r%   r   r   r   r&   r'   r   rP   )r$   r   r%   r   rQ   r   r   rP   )r$   r   r%   r   r&   r'   r   rP   )r%   r   r&   r'   r   r   )r$   r   r%   r   r   r   r   r   )(r   
__future__r   rK   r5   rer9   r   pathlibr   typingr   r*   compiler   r   __annotations__r:   r7   _TERMINAL_SSE_EVENTSrs   ru   rt   r   r#   r.   r=   rV   rc   rp   rw   r{   r   r   r   r   r   r   r   r   r   r   r   <module>r      s    
 # " " " " "  				 				                 % bj-..<> > > > >$in&& LLL 2 +       > > > > >      ,* * * *    % % % %           	+  $#+ + + + + +\
 
 
 
 
 
 
 
< !#     &   , TX Q Q Q Q Q Q
 AE 
 
 
 
 
 
 VZ        r   