+
    iD[                     2   R t ^ RIt^ RIt^ RIt^ RIt^ RIt^ RIt^ RIHt ^ RI	H
t
 ^ RIHtHtHtHtHtHtHtHtHtHtHtHt ]P0                  ! 4       t ^ RIHt ^ RIHtHtH t  ^ RI!H"t" 0 Rmt#R t$RR	 lt%R
 t&R t'RR lt(R R lt)R#   ] d    Rt L:i ; i)zt
Hermes Web UI -- SSE streaming engine and agent thread runner.
Includes Sprint 10 cancel support via CANCEL_FLAGS.
N)Path)parse_reasoning_effort)STREAMSSTREAMS_LOCKCANCEL_FLAGSCLI_TOOLSETSLOCKSESSIONSSESSION_DIR_get_session_agent_lock_set_thread_env_clear_thread_envclamp_reasoning_effortresolve_model_provider)AIAgent)Sessionget_session
title_from)set_last_workspacec                   . pV  Fu  p\        V\        4      '       g   K  VP                  4        UUu/ uF  w  r4V\        9   g   K  W4bK  	  pppVP	                  R4      '       g   Kd  VP                  V4       Kw  	  V# u uppi )a  Return a deep copy of messages with only API-safe fields.

The webui stores extra metadata on messages (attachments, timestamp, _ts)
for display purposes. Some providers (e.g. Z.AI/GLM) reject unknown fields
instead of ignoring them, causing HTTP 400 errors on subsequent messages.
role)
isinstancedictitems_API_SAFE_MSG_KEYSgetappend)messagescleanmsgkv	sanitizeds   &     */home/ubuntu/hermes-webui/api/streaming.py_sanitize_messages_for_apir$   *   ss     E#t$$&)iikMkdaQ:L5LTQTk	M==  LL#  L Ns   B B c                   Rp \        V 4      p \        P                  ! V 4      pV'       dR   V'       dJ   \	        \        VR. 4      ;'       g    . 4      \	        \        VR. 4      ;'       g    . 4      8  d   TpMTpMT;'       g    TpVf   R# VR8H  pV'       d   RMRpV'       d   RMRp	RV R	V	 R
V 2p
V'       d   V
RV R2,          p
VP                  '       d   VP                  R,          MRp\        V\        4      '       dG   VP                  R4      R8X  d1   \        VP                  RR4      4      P                  4       V
8X  d   R# VP                  P                  RRRV
R\        \        P                  ! 4       4      /4       \        VP                  VP                   4      Vn        VP#                  4        \$        ;_uu_ 4        V\&        V &   \)        \&        R4      '       d   \&        P*                  ! V 4       RRR4       R#   \         d    Rp ELi ; i  \         d    Rp ELi ; i  + '       g   i     R# ; i)zIAppend a visible assistant error to the session so reloads don't lose it.Nr   
rate_limitu   ⏱️u   ⚠️zRate limit reachedErrorz** z:** z

**r   	assistantcontent 	timestampmove_to_end)r   	Exceptionr   loadlengetattrr   r   r   r   strstripr   inttimer   titlesaver   r	   hasattrr.   )
session_id
error_typemessagehintcached	persistedsis_rate_limiticonlabelr+   lasts   &&&&        r#   _persist_stream_errorrF   ;   s   FZ(LL,	 Vwy*b177R8CPZ\^@_@e@ece<ffAAy,.M$8(D$1 wE4&%WI.GU4&?"ZZZ1::b>TD$$((6"2k"Ac$((S\^`JaFbFhFhFjnuFuJJ7S% 
 QWW-AGFFH	 8]++  , 
K  
  	@ 
s.   H H% 6H9H"!H"%H65H69I
	c                   \        T;'       g    R4      P                  4       pV'       g   \        T ;'       g    . 4      # \        T ;'       g    . 4      p\        R \	        V4       4       R4      pV'       d;   \        VP                  RR4      ;'       g    R4      P                  4       V8X  d   V# VP                  RRRVR\        \        P                  ! 4       4      /4       V# )zEEnsure a returned final_response exists in persisted message history.r,   c              3      "   T F7  p\        V\        4      '       g   K  VP                  R 4      R8X  g   K3  Vx  K9  	  R# 5i)r   r*   N)r   r   r   ).0r   s   & r#   	<genexpr>1_ensure_final_response_message.<locals>.<genexpr>s   s8      	
+C#t$ ),K)G C+s   AA
ANr+   r   r*   r-   )	r4   r5   listnextreversedr   r   r6   r7   )r   final_response
normalizedresultlast_assistants   &&   r#   _ensure_final_response_messagerS   k   s    ^))r*002JHNN##(..b!F	
#F+	
 	N #n00B?EE2FLLNR\\
MM:S% 
 M    c                    RV R\         P                  ! VRR7       R2pV P                  P                  VP	                  R4      4       V P                  P                  4        R# )z+Write one SSE event to the response stream.zevent: z
data: F)ensure_asciiz

zutf-8N)jsondumpswfilewriteencodeflush)handlereventdatapayloads   &&& r#   _ssera      sM    whtzz$U'K&LDQGMMw/0MMrT   c                "  a aRaSaT \         P                  ! V4      oTSTf   R# \        P                  ! 4       oR\        ;_uu_ 4        SR\
        V&   RRR4       VRVT3R loS \        S 4      p\        \        V4      P                  4       P                  4       4      Vn        W'n        \        TT;'       g    \        VRR4      4      Vn        \!        S 4      pSRP#                  4       '       d^   SS! RRR/4        \%        4        \        ;_uu_ 4        \         P&                  ! VR4       \
        P&                  ! VR4       RRR4       R#  ^ RIHp	 \        V	! 4       4      p
\3        \        VP                  4      R
S V
R7       \4        ;_uu_ 4        \.        P0                  P                  R4      p\.        P0                  P                  R4      p\.        P0                  P                  R4      p\.        P0                  P                  R	4      p\        VP                  4      \.        P0                  R&   R
\.        P0                  R&   S \.        P0                  R&   V
'       d   V
\.        P0                  R	&    VS3R lpVSV 3R lp\6        f   \-        R4      h\9        V4      w  pppRp ^ RIHp V! VR7      pVP                  R4      pV'       g   VP                  R4      pV'       g   VP                  R4      p^ RI!H"p T! 4       pTP                  R/ 4      p\G        T\H        4      '       d   TP                  R\J        4      M\J        p\7        TTTTRRTRS \M        \        TRR4      ;'       g    R4      TTR7      pRTP                   R2pR TP                   R!2pRp\        TR"R4      p T '       Ed   TP                  R#/ 4      p!T!P                  R$/ 4      p"\G        T"\H        4      '       d   T T"9   d   T"T ,          p#\G        T#\H        4      '       d   T#P                  R%R4      ;'       g    T#P                  R&R4      .p$T#P                  R'4      '       d   T$PO                  R(T#R',           24       T#P                  R)4      '       d   T$PO                  R*T#R),           24       R+PQ                  R, T$ 4       4      pM\        T#4      pT'       d   TTn)        TPU                  TT,           T\W        TPX                  4      S TR-7      p%\[        T%P                  R.4      ;'       g    TPX                  T%P                  R/4      4      Tn,        \        TR0R4      p&R1p'T&'       d   T&S 8w  d   S p(T&p)\\        T( R22,          p*\\        T) R22,          p+T)Tn/        \`        ;_uu_ 4        T(\b        9   d   \b        P&                  ! T(4      \b        T)&   RRR4       T*Pe                  4       '       d)   T+Pe                  4       '       g    T*Pg                  T+4       Rp'T''       g*   \        TR3R4      p,T,'       d   \        T,R4^ 4      ^ 8  d   Rp'T''       d   SS! R5RR6/4       \j        Pj                  ! 4       p-TPX                   F[  p.\G        T.\H        4      '       g   K  T.P                  R74      '       d   K4  T.P                  R84      '       d   KM  \m        T-4      T.R7&   K]  	  \o        TPX                  TPp                  4      Tn8        \        TR9^ 4      ;'       g    ^ p/\        TR:^ 4      ;'       g    ^ p0\        TR;R4      p1TPr                  ;'       g    ^ T/,           Tn9        TPt                  ;'       g    ^ T0,           Tn:        T1'       d#   TPv                  ;'       g    ^ T1,           Tn;        . p2/ p3/ p4/ p5\y        TPX                  4       EF?  w  p6p7T7P                  R<4      R=8X  Edz   T7P                  R>R4      p8\G        T8\z        4      '       d{   T8 Ft  p9\G        T9\H        4      '       g   K  T9P                  R?4      R@8X  g   K3  T9P                  RAR4      p:T9P                  RBR4      T3T:&   T9P                  RC/ 4      T4T:&   T6T5T:&   Kv  	  T7P                  RD. 4       F  p;\G        T;\H        4      '       g   K  T;P                  RAR4      ;'       g    T;P                  RER4      p:T;P                  RF/ 4      p<T<P                  RBR4      p= ^ RI>p>T>P                  T<P                  RGRH4      ;'       g    RH4      p?T:'       g   K  T='       g   K  T=T3T:&   T?T4T:&   T6T5T:&   K  	  EK  T7P                  R<4      RI8X  g   EK  T7P                  RJ4      ;'       g    T7P                  RKR4      p:T3P                  T:R4      p=T='       d   T=RI8X  d   EK  T5P                  T:Rp4      p@T4P                  T:/ 4      p?\        T7P                  R>R4      4      pA \|        P~                  ! TA4      pB\        TBP                  RL4      ;'       g5    XBP                  RM4      ;'       g    XBP                  RN4      ;'       g    XA4      RO,          pC/ pD\G        T?\H        4      '       d[   \{        T?P                  4       4      RP,           F6  w  pEpF\        TF4      pGTGRQ,          \        TG4      ^x8  d   RRMR,           XDXE&   K8  	  T2PO                  RBT=RSXCRTT:RUX@RVXD/4       EKB  	  T2TnB        T'       d   \        TPX                  4       F  p7T7P                  R<4      RW8X  g   K  \        T7P                  R>R4      4      pHTP                  RX4      ^ ,          P                  4       pITIRY,          TH9   g   XHRY,          T9   g   Kz  TT7RZ&    M	  TP                  4         ^ R[I!HGpJ TJ! 4       P                  R\4      '       do   ^ R]IHHIpK TK! TP^                  TPr                  ;'       g    ^ TPt                  ;'       g    ^ TPv                  TTPp                  \        TPX                  4      R^7       R_T/R`T0RaT1/pL\        TR3R4      pMTM'       dO   \        XMRb^ 4      ;'       g    ^ XLRb&   \        XMRc^ 4      ;'       g    ^ XLRc&   \        XMRd^ 4      ;'       g    ^ XLRd&   SS! ReRfTP                  4       R.TPX                  RDT2/,          RgXL/4       Tf"   \.        P0                  P'                  RR4       MT\.        P0                  R&   Tf"   \.        P0                  P'                  RR4       MT\.        P0                  R&   Tf"   \.        P0                  P'                  RR4       MT\.        P0                  R&   Tf"   \.        P0                  P'                  R	R4       MT\.        P0                  R	&    RRR4       \%        4        \        ;_uu_ 4        \         P&                  ! TR4       \
        P&                  ! TR4       RRR4       R#   + '       g   i     EL; i  + '       g   i     R# ; i  \,         d%    \.        P0                  P                  R	R4      p
 ELi ; i  \>         d   p\A        RT 2RR7        Rp?ELRp?ii ; i  + '       g   i     EL; i  \h         d     ELi ; i  \>         d    / p? ELi ; i  \>         d    XARO,          pC ELi ; i  \>         d     ELi ; i  Tf"   \.        P0                  P'                  RR4       MT\.        P0                  R&   Tf"   \.        P0                  P'                  RR4       MT\.        P0                  R&   Tf"   \.        P0                  P'                  RR4       MT\.        P0                  R&   Tf"   \.        P0                  P'                  R	R4       i T\.        P0                  R	&   i ; i  + '       g   i     EL1; i  \>         d   pN\A        Rh\        P                  ! 4       ,           RR7       \        TN4      pORiTOP                  4       9   ;'       g&    RjXO9   ;'       g    Rk\        XN4      P                  9   pPTP'       d&   RlpQ\        S RmXOTQ4       SS! RnRTOR?RmRoTQ/4        RpN?NEL\        S RNXO4       SS! RnRTOR?RN/4        RpN?NELRpN?Nii ; i  + '       g   i     R# ; i  \%        4        \        ;_uu_ 4        \         P&                  ! TR4       \
        P&                  ! TR4       RRR4       i   + '       g   i     i ; i; i)qzIRun agent in background thread, writing SSE events to STREAMS[stream_id].Nc                    < SP                  4       '       d
   V R9  d   R#  SP                  W34       R#   \         d     R# i ; i)cancelN)rd   error)is_set
put_nowaitr0   )r^   r_   cancel_eventqs   &&r#   put!_run_agent_streaming.<locals>.put   sB      U2E%E	LL%' 		s   6 AAreasoning_effortr,   rd   r=   zCancelled before start)get_active_hermes_homeHERMES_HOME1)TERMINAL_CWDHERMES_EXEC_ASKHERMES_SESSION_KEYrn   rp   rq   rr   c                 *   < V f   R # S! RRV /4       R # )Ntokentext )ru   rj   s   &r#   on_token&_run_agent_streaming.<locals>.on_token   s    <Gfd^,rT   c           	        < / p\        V\        4      '       dX   \        VP                  4       4      R ,           F3  w  rE\	        V4      qfR,          \        V4      ^x8  d   RMR,           W4&   K5  	  S! RRV RVRV/4       ^ RIHpHpH	p	 V! S4      '       dD   V	;_uu_ 4        \        VP                  S/ 4      4      p
R	R	R	4       X
'       d   S! R
V
4       R	# R	# R	#   + '       g   i     L'; i):N   NNx   N...r,   toolnamepreviewargs)has_pending_pending_lockNapproval)r   r   rL   r   r4   r2   tools.approvalr   r   r   r   )r   r   r   	args_snapr    r!   s2_has_pendingr   r   prj   r;   s   &&&        r#   on_tool%_run_agent_streaming.<locals>.on_tool   s    	dD)) $TZZ\ 22 6 6 VtHs2ws{eXZ4[Y\ !7FVT9gvyQRWW
++ j"!=> J*  ,s   "CC-	z?AIAgent not available -- check that hermes-agent is on sys.path)resolve_runtime_provider)	requestedapi_keyproviderbase_urlz2[webui] WARNING: resolve_runtime_provider failed: T)r\   )
get_configplatform_toolsetscli)modelr   r   r   platform
quiet_modeenabled_toolsetsfallback_modelr;   reasoning_configstream_delta_callbacktool_progress_callbackz[Workspace: z]
z#Active workspace at session start: ab  
Every user message is prefixed with [Workspace: /absolute/path] indicating the workspace the user has selected in the web UI at the time they sent that message. This tag is the single authoritative source of the active workspace and updates with every message. It overrides any prior workspace mentioned in this system prompt, memory, or conversation history. Always use the value from the most recent [Workspace: ...] tag as your default working directory for ALL file operations: write_file, read_file, search_files, terminal workdir, and patch. Never fall back to a hardcoded path when this tag is present.personalityagentpersonalitiessystem_promptprompttonezTone: stylezStyle: 
c              3   8   "   T F  q'       g   K  Vx  K  	  R # 5iNrv   )rI   r   s   & r#   rJ   '_run_agent_streaming.<locals>.<genexpr>$  s     7O6aQ6s   	
)user_messagesystem_messageconversation_historytask_idpersist_user_messager   rO   r;   Fz.jsoncontext_compressorcompression_count
compressedz4Context auto-compressed to continue the conversationr-   _tssession_prompt_tokenssession_completion_tokenssession_estimated_cost_usdr   r*   r+   typetool_useidr   input
tool_callscall_idfunction	argumentsz{}r~   tool_call_idtool_use_idoutputrQ   re   :N   N:N   Nr{   r}   snippettidassistant_msg_idxr   userz

[Attached files::N<   Nattachments)load_settingssync_to_insights)sync_session_usage)r;   input_tokensoutput_tokensestimated_costr   r8   message_countr   r   r   context_lengththreshold_tokenslast_prompt_tokensdonesessionusagez[webui] stream error:
z
rate limit429RateLimitErrorz*Rate limit reached. Try again in a moment.r&   apperrorr>   r/   )Qr   r   	threadingEventr   r   r   r4   r   
expanduserresolve	workspacer   r   r3   rl   r   rf   r   popapi.profilesrm   ImportErrorosenvironr   	_ENV_LOCKr   r   hermes_cli.runtime_providerr   r0   print
api.configr   r   r   r   r   r   joinephemeral_system_promptrun_conversationr$   r   rS   r
   r;   r   r	   existsrenameOSErrorr7   r6   r   r8   r   r   r   	enumeraterL   rW   loadsr   r2   r   rN   splitr5   r9   r   api.state_syncr   compact	traceback
format_exclowerr   __name__rF   )Ur;   msg_textr   r   	stream_idr   rl   rA   _agent_lockrm   _profile_homeold_cwdold_exec_askold_session_keyold_hermes_homerw   r   resolved_modelresolved_providerresolved_base_urlresolved_api_keyr   _rt_e_get_config_cfg_pt	_toolsetsr   workspace_ctxworkspace_system_msg_personality_prompt_pname
_agent_cfg_personalities_pval_partsrQ   
_agent_sid_compressedold_sidnew_sidold_pathnew_path_compressor_now_mr   r   r   r   pending_namespending_argspending_asst_idxmsg_idxmcr   r   tcfnr   _jr   asst_idxrawrdr   r   r    r!   r   r+   	base_text_load_settingsr   r   _cceerr_strrB   r>   rh   rj   ri   sU   f&&&&&&                                                                           @@@r#   _run_agent_streamingr(     s6   IAy ??$L	".Y 
D.
#$y/446>>@A3BB+=r B

 .j9   9&>?@f	 	\KK	4(Y- \c		>; 6 89M 	Q[[))%		
 YJJNN>2'(9:,JJNN+?@/JJNN=9/'*1;;'7"**^
$*-"**&
'-7"**)
**7bjj'D>-
+ !"cddCYZ_C`@N-/@  $	]P.9JK#&779#5 ((+
(;%((+
(;%
 ==D ((.3C8B38M8M|4S_I$**(!*  $%!7CUWY8Z8`8`^`!a&.'.E& +1;;-s;M5akk] CP P ! #'Qt4Fv!XXgr2
!+!Dnd33.8P*62E!%.."'))OR"@"["[EIIhXZD[!\ 99V,,"MMF5=/*BC 99W--"MMGE'N3C*DE.2ii7O67O.O+.1%j+"0C-++*X53%?

%K"%- , F 8

:&44!**

+,AJ !d;JKjJ6$$&G9E)::&G9E)::&T(*,4LL,A)  ??$$X__->-> 1 #%e-A4H7;8KQ#ORS#S"&KLU# 
 99;Djjb$''{0C0CBFFSXMM&)$iB{O ! !QWW5AG"5*A1EJJL#E+FJOOaM$U,H$ONnn11\AAN 33!}DAO$%$4$4$9$9^#K  JML!'

3
55=K/i,A!!T**!"A)!T22quuV}
7R&'eeD"o56UU625Fc 245EE'24FS 18? 0 5 "#  eeL"5)"d33$ ffT2.GG"&&B2GVVJ3!vvfb1&-#%88BFF;,E,M,M#ND 34415M#.04L-4;,S1 6 UU6]f,%%/KK1553KC(,,S"5D46> /33C<H'++C4DaeeIr23C,!ZZ_"%bffX&6&d&d"&&:J&d&dbffU\o&d&dad"efj"k !#I!$--$($6r$:$:DAq!$QB+-d8B#uSU+VIaL %; %%i%+Xvy' ] 4d &AL !!**-AuuV}."%aeeIr&:";$,NN3I$J1$M$S$S$U	$S>W48P/:Am,! . FFHF!#''(:;;A&#$<<%&^^%8%8q&'oo&:&:'('7'7#gg&)!**o $\?MScestE%!5t<C*1#7G*K*P*Pq&',3C9KQ,O,T,TST().5c;OQR.S.X.XWX*+AIIK:qzz<Yc2d$dfmotuv

~t D/6"**^,#RZZ^^4Et%L2>"**./&

7KT(R5D"**12&

}d(K.="**]+_ F	 	\KK	4(Y- \]
 
\
 \\]	  	>JJNN="=M	>p  ]J2$OW[\\]p TT # p  ) &#%D&" % ,"%d),P   

~t D/6"**^,#RZZ^^4Et%L2>"**./&

7KT(R5D"**12&

}d(K.="**]+_ YYb  C')*>*>*@@Ma& %7ss5G;KssO_cghicjcscsOs?D!*lGTJ
7   "*gw?
YABB!C& \\ 	\KK	4(Y- \\\s  
x%BA@ /x9	y 0A@ C$441|&A y?'y?8D6|/*|1|A|A|'A=|$)z(	|+|z<	|0|A||.|A
||)"|!|.||B
|'|?B
|
7|'{*{1|;|)|4|,|9A	|A{"{"({"6B |+|A|&| !{="%{={=3{=0|||56|+C!4A@ ,/AC%x6	9y
	+y<8A@ ;y<<A@ ?z%
z | z%%|(z93	|<{|
{|{|{|"{:	6|9{:	:|=||||C"1144A@	?A@ @AC. @A@ @AC@AACA, ACBACB,AC. B2ACCAC. CACCAC. CAC+	C.AED/AD?	D6	AED?AEE
AEc                0    V ^8  d   QhR\         R\        /# )   r   return)r4   bool)formats   "r#   __annotate__r.    s      S T rT   c                n   \         ;_uu_ 4        V \        9  d    RRR4       R# \        P                  ! V 4      pV'       d   VP	                  4        \        P                  ! V 4      pV'       d    VP                  RRR/34       RRR4       R#   \         d     Li ; i  + '       g   i     R# ; i)zISignal an in-flight stream to cancel. Returns True if the stream existed.NFrd   r=   zCancelled by userT)r   r   r   r   setrg   r0   )r   flagri   s   &  r#   cancel_streamr2    s    	G# 
 	*HHJKK	"h4G(HIJ 
    
 s4   B#B#-B#3BB B#B  B##B4	>   r   r   r+   refusalr   r   r   )Nr,   )*__doc__rW   r   queuer   r7   r   pathlibr   hermes_constantsr   r   r   r   r   r   r   r	   r
   r   r   r   r   r   Lockr   	run_agentr   r   
api.modelsr   r   r   api.workspacer   r   r$   rF   rS   ra   r(  r2  rv   rT   r#   <module>r<     s     	      3    NN	! 8 7 ,
 Z "--`2X.D]  Gs   B
 
	BB