
    5jx                         S r SSKrSSKrSSKrSSKrSSKr\R                  R                  S\R                  R                  \R                  R                  \5      5      5        SSKJr  \R                  R                  S5      r\R                  R                  S5      rS rS rS rS	 rS
 r\S:X  a	   \" 5         gg! \ a    \" S5         gf = f)ac  
Hermes Local Model Switcher v2
------------------------------
Lists available models and hot-swaps them (stop old, start new, update config).
Usage: python3 ~/.hermes/scripts/model-switcher      (interactive menu)
       python3 ~/.hermes/scripts/model-switcher 35b   (direct switch)
       python3 ~/.hermes/scripts/model-switcher 9b    (direct switch)
    N)MODELSz~/.local/bin/hermesz~/.hermes/config.yamlc                      [          HA  n [        R                  " SSU S   /SSS9nUR                  R	                  5       S:X  d  M?  U s  $    g)z-Find which model service is currently active.	systemctl	is-activeserviceTcapture_outputtextactiveN)r   
subprocessrunstdoutstrip)modelrs     ,/home/rurouni/.hermes/scripts/model-switcherget_active_servicer      sJ    NNKeI6FG*.T;88>>x'L	 
     c                      [        [        5       n SnU  Hd  nUR                  5       nUR                  S5      (       d  M+  SU;   d  M3  UR	                  S5      S   R                  5       R                  S5      n  O   U(       a#  [
         H  nUS   U:X  d  M  Us  sSSS5        $    SSS5        g! , (       d  f       g= f!    g= f)z*Check which model Hermes config points to.Nzdefault:z.ggufz'"
model_name)openHERMES_CONFIGr   
startswithsplitr   )f	cfg_modellinems       r   get_current_configr    $   s    - AIzz|??:..7d? $

: 6r : @ @ B H H OI	 
 A)3  !    !  !  sG   C ,B1B1	AB1B1	C &B1(C 1
B?;C ?C Cc                    [        5       n[        5       nU(       a2  US   U S   :X  a&  U(       a  US   U S   :X  a  [        SU S    S35        g[        SU S    S3SS9  SU S	   4S
U S   4SSU S    S34/nU Hm  u  pE[        R                  " [
        SSXE/SSS9nUR                  S:X  a  [        SU SU 3SS9  ME  [        SU SUR                  R                  5        3SS9  Mo     [        R                  " S5        U(       aD  [        R                  " SSSUS   /SSS9n[        SUS   S SUR                  S:X  a  S OS! 3SS9  O*[         H   n[        R                  " SSSUS   /SSS9  M"     [        R                  " SSS"U S   /SSS9nUR                  S:w  a,  [        S#U S    S$UR                  R                  5        3SS9  g%[        S&U S   S S'3SS9  [        S(U S    S)3S*SS+9  [        S,5       H  n [        R                  R                  SU S    S-35      n	[        R                  R!                  U	S.S/9n
U
R"                  S0:X  a  [        S'SS9    O1 [        S1S*SS+9  [        R                  " S.5        M     [        S2SS9  g%[        S3U S    S4U S    3SS9  [        S5U S6   S7 S8U S9    3SS9  [        S:SS9  g!    Nl= f);u  Stop active model, start target, update config.

UPDATES CONFIG FIRST to avoid the path watcher race:
'hermes config set' fires the path watcher on each write.
If model.default hasn't been updated yet, auto-model-switch.py
sees the old model, finds it dead, and restarts it — undoing
the switch before model-switcher finishes.

Fix: write all config changes atomically FIRST, then swap services.
nameu   
  ✅ z" is already running and configuredTu   
  🔄 Switching to z...)flushzmodel.providerproviderzmodel.defaultr   zmodel.base_urlzhttp://127.0.0.1:portz/v1configsetr   r   u     ⚙  Config u    → u     ⚠  Config z	 failed:    sudor   stopr   u     ⏹  Stopped 20s u   ✅u   ❌startu     ❌ Failed to start z: Fu     ▶️  Starting u    ✅u     ⏳ Waiting for z to load... )endr#      z
/v1/models   )timeout   .u    ❌ (timeout)u   
  ✅ Now using z	 on port z     Context: context,z
 tokens | desczC     Run /reset in Hermes to start a fresh session with this model.)r   r    printr   r   
HERMES_CLI
returncodestderrr   timesleepr   rangeurllibrequestRequesturlopenstatus)targetr   current_cfgconfig_updateskeyvaluer   r   _reqresps              r   swaprL   7   s@     !F$&K&.F6N2{{SYGZ^dek^lGl((JKL	"6&>"2#
6dC 
6*-.	&./	.vf~.>cBCN
 %
NN5#5d
 <<1N3%uUG4DAN3%y1A0BC4P % 	JJqM NN[&&*;<d
 	vs31alla>OUUZ4[\dhi ANNFK9F*.T; 
 		gvi'89$	A 	||q&vf~&6b9I8JKSWX	vs34
8E 
vf~.k
:$O2Y	..((+<VF^<LJ)WXC>>))#q)9D{{c!fD) "
 	cr&

1  	d+	vf~.iv7G
HPTU	N6),Q/z&.9I
JRVW	OX\]	s   AK

Kc                     [        5         [        SSS SSS SSS SS	S
 SSS S35        [        SS SS SS SS SS SS 35        [        [        5       H  u  p[        R                  " SSUS   /SSS9R
                  R                  5       nUS:X  a  SOSnUS   S n[        SU S-    S US!   S SUS S[        US"   5      S
 SUS SUS#    35        M     [        5         g$)%zPrint formatted model list.z  #z<3r,   Model22sStatus12sPort6sContextz>8sz  Descriptionu	   ───uB   ──────────────────────u$   ────────────u   ──────u   ────────u   ──────────────────────────────────────────────────────────r   r   r   Tr   r   u   🟢 ACTIVEu   ⚪r5   r6   z  [r(   z] r"   r%   r7   N)r8   	enumerater   r   r   r   r   str)ir   r   rC   ctxs        r   show_all_modelsrZ      s!   	G	Bs2ha}Ahs^1VBKq3}
]^	Bwiq
!H:Qwiq	H:
NOf%k5;K L/3$@@Fuuw 	"(H"4%y!!$AaC55=-Qvcl!Cf<Nr;RRSTWX[S\\^_dek_l^mno & 
Gr   c                  z   [        [        R                  5      S:  a  [        R                  S   R                  5       R	                  SS5      R	                  SS5      n [
         Hg  nXS   R                  5       :X  d8  XS   R                  5       R	                  SS5      R	                  SS5      ;   d  MQ  [        U5      (       a  Ss  $ Ss  $    [        S	S
R                  S [
         5       5       35        [        S[        R                  S    S35        g [        R                  " [        R                  S:X  a  SOS5        [        5       n[        5       n[        S5        [        S5        [        S5        U(       a#  [        SUS    35        [        SUS    35        O[        S5        [        5         [        S5        [        S5        [        5         [        S5        [        5         [        S5      R!                  5       R                  5       nUS;   a  [        S5        g [
         Vs/ s H  oTUS   R                  5       :X  d  M  UPM     nnU(       d6   [#        U5      S-
  nSUs=::  a  [        [
        5      :  a  O  O
[
        U   /nU(       a  [        US   5        [        S5        O'[        S[        [
        5       S 35        [        S!5        GM  s  snf ! [$         aM    [
         H@  nXES   R                  5       R	                  SS5      R	                  SS5      ;   d  M;  U/n   M      Nf = f)"Nr(   -r.   r,   shortr"   r4   r   zUnknown model. Try: z, c              3   *   #    U  H	  oS    v   M     g7f)r]   N ).0r   s     r   	<genexpr>main.<locals>.<genexpr>   s     .J6az6s   z	Example: z 9bposixclearclsu   ╔══════════════════════════════════════════════════════╗u<   ║      🤖  Hermes Local Model Switcher  v2           ║u   ╚══════════════════════════════════════════════════════╝u   
  🟢 Currently running: z     detailu'   
  ⚪ No local model currently runningz  Quick shortcuts:z:    35b | 14b | 9b | 8b | 4b | gemma3 | gemma3qat | gemma4z
  [q] Quitz  Select model (# or name): )qquitexitu   
  👋 Bye!z
  Press Enter to continue...u'   
  ❌ Invalid choice. Try a number (1-z) or shortcut name.z  Press Enter...)lensysargvlowerreplacer   rL   r8   joinossystemr"   r   r    rZ   inputr   int
ValueError)argr   r   currentchoicer   matchedidxs           r   mainrz      s   
388}qhhqk!))#r2::3CEGn**,,V}7J7J7L7T7TUXZ\7]7e7efikm7n0n KKq.Q.  	$TYY.J6.J%J$KLM	#((1+c*+ 
		RWW/'U;#%$&  y  	zLM  y  	z00@ABE&*+,-<>"#JLl56<<>DDF**/" %Ef!G*2B2B2D(D1fE	&kAo)c&k)%c{mG 23<S[MI\]^$%c > F  A6!2!:!:3!C!K!KCQS!TT#$#  s1   0KK*K# 	
K# #AL:.L:5L:9L:__main__u   

  👋 Bye!)__doc__r   rk   rp   r<   urllib.requestr?   pathinsertdirnameabspath__file__modelsr   
expanduserr9   r   r   r    rL   rZ   rz   __name__KeyboardInterruptr8   r_   r   r   <module>r      s     
 	   277??277??8#<= >  WW 56
""#:;&Sl=&@ z!   ! !s   7C   CC