
    oj              	          S r SSKrSSKrSSKrSSKrSSKrSSKrSSKJr  SSK	J
r
  \R                  R                  \R                  R                  \5      5      r\\R                  ;  a  \R                  R!                  S\5        SSKJr  \R                  R'                  S5      r\R                  R'                  S5      r\R                  R'                  S5      rS	\4S
 jrS\4S jrS\4S jrSS\S\S\\\4   4S jjrS\4S jr S r!\"S:X  a	   \!" 5         gg! \# a`  r$\" S\$ 35        \%" \S5       r&\&RO                  S\$ S35        SSS5        O! , (       d  f       O= f\RP                  " S5         Sr$C$gSr$C$ff = f)a)  
Quick-start a local model service by gguf filename.

Called from gateway after /model switch to a local model.
Stops any other running local service first, then starts the target.
Verifies the model actually loads, then sends a Telegram notification.

Usage: quick-start-model.py <gguf-filename>
    N)datetime)Path)MODELSz~/.hermes/config.yamlz~/.hermes/.model-switch-notifyz	~/.hermesmsgc                 t   [         R                  " 5       R                  S5      n[        R                  R                  [        S5      n[        R                  " USS9  [        [        R                  R                  US5      S5       nUR                  U SU  S35        S S S 5        g ! , (       d  f       g = f)	Nz%Y-%m-%d %H:%M:%SlogsT)exist_okzmodel-switch.logaz [quick-start] 
)
r   nowstrftimeospathjoinHERMES_HOMEmakedirsopenwrite)r   tslog_dirfs       2/home/rurouni/.hermes/scripts/quick-start-model.pylogr      s|    		 	 !4	5Bggll;/GKK$'	bggll7$67	=	2$ocU"-. 
>	=	=s   B))
B7messagec                    SSK n [        [        S5       nUR                  U S-   5        SSS5        Sn [        R                  R                  S5      nUR                  USS	U/S
SS9  [        S5        g! , (       d  f       NQ= f! [         a  n[        SU 35         SnAgSnAff = f! [         a  n[        SU 35         SnAgSnAff = f)zDeliver a notification via Hermes cron watchdog.
Works on any platform (Telegram, Discord, etc.) because Hermes cron
auto-resolves the delivery target to the current origin platform.r   Nwr   zFailed to write notify file: a35af7b299a1z~/.local/bin/hermescronrunTx   capture_outputtimeoutzWatchdog triggered for deliveryzFailed to trigger watchdog: )

subprocessr   NOTIFY_FILEr   	Exceptionr   r   r   
expanduserr   )r   _spr   ewatchdog_id
hermes_bins         r   send_notificationr,   '   s     +s#qGGGdN# $ !K0WW''(=>
4 	 	
 	-. $# +A3/0  0*1#.//0sJ   B A6B ?B, 6
B B B 
B)B$$B),
C6C		Creturnc                  @    [         R                  " / SQSSSS9n U R                  S:X  ad  U R                  R	                  5       R                  S5      n[        U5      S:X  a,  [        US   5      S-  n[        US	   5      S-  nUS
 SUS
 S3$ g! [         a     gf = f)zGet current VRAM usage.)z
nvidia-smiz$--query-gpu=memory.used,memory.totalz--format=csv,noheader,nounitsT   r"   textr#   r   z,    i      .1fzG / G?)	r$   r   
returncodestdoutstripsplitlenintr&   )rpartsused_gbtotal_gbs       r   get_vramrA   A   s    NN.dA

 <<1HHNN$**40E5zQeAh-$.uQx=4/!#d8C.::   s   BB 
BBporttimeout_secc                    SU  S3n[         R                   " 5       n[        U5       H  n [        R                  R	                  U5      n[        R                  R                  USS9nUR                  S:X  a  [         R                   " 5       U-
  nSU4s  $  [         R                  " S5        M     S[         R                   " 5       U-
  4$ ! [        R                  R                  [        [        4 a     N_f = f)	zEWait for the model API to respond. Returns (success, seconds_waited).http://127.0.0.1:z
/v1/modelsr2   )r#      Tr3   F)timerangeurllibrequestRequesturlopenstatuserrorURLErrorConnectionErrorOSErrorsleep)rB   rC   urlstartireqrespelapseds           r   wait_for_modelrY   T   s    dV:
.CIIKE;	..((-C>>))#q)9D{{c!))+-W}$ "
 	

1   $))+%%% %%@ 		s   A(C)C76C7c                 D   SU  S3n[        [        5       nUR                  5       nSSS5        / nSnW Hr  nUR                  5       nUR	                  S5      (       a8  UR	                  S5      (       d"  U(       d  UR                  SU S35        S	nM_  Ma  UR                  U5        Mt     U(       d  UR                  SU S35        [        [        S
5       nUR                  U5        SSS5        [        SU 35        g! , (       d  f       N= f! , (       d  f       N.= f)z@Update model.base_url in config.yaml to match the target's port.rE   z/v1NFz	base_url:z
base_urls:z  base_url: r   Tr   zUpdated base_url to )r   CONFIG_PATH	readlineslstrip
startswithappend
writelinesr   )rB   base_urlr   lines	new_lineswrotelinestrippeds           r   update_base_urlrg   e   s    "4&,H	k	a 
IE;;={++H4G4G4U4U  <z!<=T"  <z45	k3	1	Y 
 
xj)*% 
	  
 	s   D D 
D
Dc                    ^ [        [        R                  5      S:  a  [        R                  " S5        [        R                  S   m[	        U4S j[
         5       S 5      n U (       d2  [        ST 35        [        ST 35        [        R                  " S5        U S   nU S   nU S	   n[        S
U SU S35        [        R                  " SSU/SSSS9nUR                  R                  5       S:X  ai  [        U5        [        U S35        [        USS9u  pVU(       a'  [        5       nSU SU SU SU S    S3	n[        U5        [        R                  " S5        [
         Hy  n	U	S	   U:X  a  M  [        R                  " SSU	S	   /SSSS9nUR                  R                  5       S:X  d  MK  [        SU	S    35        [        R                  " SSSU	S	   /SSS 9  M{     [        S!U S"35        [        R                  " SSS#U/SS$S 9nUR                  S:w  ai  UR                   (       a  UR                   R                  5       S S% OS&n
[        S'U S(U
 35        [        S)U S*U
 S+35        [        R                  " S5        [        U5        [        S,U S-U S"35        [        US.S9u  pV[        5       nU R#                  S/5      (       a  U R#                  S/S5      S0 OS1nU(       a1  SU S2U SU S3U S4US5 S63n[        S7US5 S8U 35        [        U5        O(S9U S:U S;US< S=3n[        S>US< S?35        [        U5        [        R                  " S5        g )@Nr2   r   r3   c              3   <   >#    U  H  oS    T:X  d  M  Uv   M     g7f)
model_nameN ).0mrj   s     r   	<genexpr>main.<locals>.<genexpr>   s     Ff,:(E11fs   	zUnknown model: u   ❌ Unknown model: namerB   servicezStarting switch to z (port )	systemctlz	is-activeT
   r0   activez already running)rC   u   ✅ **uQ   ** already running
━━━━━━━━━━━━━━━━━
**Port:** z
**VRAM:** z
**Model:** rj   r   r/   z	Stopping sudostop   r!   z	Starting z...rT      rF   zunknown errorzFailed to start z: u   ❌ **z** failed to start
```
z
```zWaiting for z to respond on port r    context,r6   uH   ** loaded
━━━━━━━━━━━━━━━━━
**Port:** z
**Context:** z tokens
**Load time:** r4   zs
z	Ready in u   s — u	   ⚠️ **u\   ** started but not responding
━━━━━━━━━━━━━━━━━
**Port:** z!
**Service:** active
**Waited:** z.0fu   s — still loading
z!Started but not responding after s)r;   sysargvexitnextr   r   r,   r$   r   r8   r9   rg   rY   rA   r7   stderrget)targetrp   rB   rq   r=   readyrX   vramr   rm   errctxrj   s               @r   mainr   }   s   
388}q!JFfFMFoj\*+/
|<=&>D&>DYG
dV74&23 		k7+$	A 	xx~~8#tf$%&'"=:D !F #!F #$\232	7  c" Y<7"NN+q|4dA
 88>>x')AfI;'(NNfa	l;#R  )D6	gw/S	A
 	||q()ahhnnt$otfBse,-F4&(A#eLM D ,tf0c:;#Dc:NE :D-3ZZ	-B-BVZZ	1%a(CTF   5 !%c]#/ 	 	i}F4&12# v  "3-'<	> 	 	/}A>?#HHQK    __main__zUnhandled error: r   u   ❌ Model switch error: r   r3   )r    ))__doc__r$   r}   r   rG   urllib.requestrI   urllib.errorr   pathlibr   r   dirnameabspath__file___script_dirinsertmodelsr   r'   r[   r%   r   strr   r,   rA   r<   tupleboolfloatrY   rg   r   __name__r&   r)   r   r   r   r   rk   r   r   <module>r      sr    
 	     ggoobggooh78chhHHOOA{# gg  !89gg  !ABgg  -/S /0s 04# && &3 &tU{9K &"+# +0dN z   s#$+s#qGG.qc45 $##	s0   D F%F 9E	F 
E&	"F  F