
    ]j                        d Z ddlZddlZddlZddlZddlZddlZddlZej	        
                    dej	                            ej	                            e                               ddlmZ ej	                            d          ZdededefdZd	 Zd
 Zd Zd Zedk    r$	  e             dS # e$ r  ed           Y dS w xY wdS )u  
Hermes Local Model Switcher v4
-------------------------------
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)

v4: Clean rewrite — fixed corrupted imports and duplicate function defs.
    N)MODELSz~/.hermes/config.yamlprovider
model_namebase_urlc                    t          t          d          5 }t          j        |          pi }ddd           n# 1 swxY w Y   t	          |t
                    si }|                    di           }t	          |t
                    si }||d<   | |d<   ||d<   |r||d<   t          j        	                    t                    pd}t          j        d	d
|d          \  }}	 t          j        |dd          5 }t          j        ||ddd           |                                 t          j        |                                           ddd           n# 1 swxY w Y   t          j        |t                     t          j                            |          rt          j        |           dS dS # t          j                            |          rt          j        |           w w xY w)zDAtomically update model.provider, model.default, and model.base_url.zutf-8)encodingNmodelr   defaultr   .z.config.yaml.z.tmpT)prefixsuffixdirtextwF)default_flow_style	sort_keysallow_unicode)openHERMES_CONFIGyaml	safe_load
isinstancedict
setdefaultospathdirnametempfilemkstempfdopen	safe_dumpflushfsyncfilenoreplaceexistsunlink)	r   r   r   fcfg	model_cfg	directoryfdtmp_paths	            ,/home/rurouni/.hermes/scripts/model-switcherwrite_config_atomicr/      sK   	mg	.	.	. &!nQ%2& & & & & & & & & & & & & & &c4   w++Ii&& !	 G$Ij%Ii ) (	*..5#I#?6y_cdddLB Yr3111 	!QN3eu\`aaaaGGIIIHQXXZZ   	! 	! 	! 	! 	! 	! 	! 	! 	! 	! 	! 	! 	! 	! 	! 	
8]+++7>>(## 	 Ih	  	 27>>(## 	 Ih	 s>   :>>!F4 8AEF4 EF4 E F4 46G*c                      t           D ]Y} |                     d          rt          j        dd| d         gdd          }|j                                        dk    r| c S ZdS )	zFFind which model service is currently active, skipping preserved ones.preserve	systemctl	is-activeserviceTcapture_outputr   activeN)r   get
subprocessrunstdoutstrip)r	   rs     r.   get_active_servicer>   6   s~      99Z   	N+uY'78d
 
 
 8>>x''LLL (4    c                    t                      }d| d          d}t          | d         | d         |           t          d| d          d| d          d	           |r|d         d
k    r| d         d
k    r|                    d          rt          d|d          dd	           nt          d|d          dd           t	          j        ddd|d         gdd          }t          d|j        dk    rdnd d	           t          dd	           t          j        d           n|st          dd	           | d         d
k    r>t          d| d          dd           t	          j        ddd| d         gdd          }t          d|j        dk    rdnd d	           t          d | d          d!dd           t          d"          D ]}	 t          j                            d| d          d#          }t          j                            |d$%          }|j        d&k    rt          d'd	            nKn# t          $ r Y nw xY wt          d(dd           t          j        d$           t          d)d	           d*S t          d+| d          d,| d-          d.           t          d/| d0                     t          d1d	           dS )2zStop active model, start target, update config.

    Writes all config changes atomically FIRST, then swaps services.
    When switching to a cloud model, keeps local models warm in VRAM.
    VRAM drain delay only applies to local-to-local switching.
    zhttp://127.0.0.1:portz/v1r   r   u     ⚙  Config → z / T)r"   localr1   u     🛡  Preserving namez (background service)u     ⏹  Stopping  )endr"   sudor2   stopr4   r5    r   u   ✅u   ❌u"     💤 Waiting 3s for VRAM free...   u#     ℹ️  No active service to stopu     ▶️  Starting startu     ⏳ Waiting for z...   z
/v1/models   )timeout   u    ✅r   u    ❌ (timeout)Fu   
  ✅ Now on z - contextz token contextz     Desc: descz)     Run /reset in Hermes to start fresh.)r>   r/   printr8   r9   r:   
returncodetimesleeprangeurllibrequestRequesturlopenstatus	Exception)targetr7   r   r=   _reqresps          r.   swapr`   D   s     !!F66&>666Hz*F<,@(KKK	
Lvj1
L
Lf\6J
L
LTXYYYY  A&$//F:4F'4Q4Q::j!! 	MvMMMUYZZZZZ5VF^552TJJJJffY.?@#$  A =q|q00eee==TJJJJ6dCCCCJqMMMM A34@@@@ jW$$4F6N44"DIIIIN['6)+<=d
 
 
 	91<1,,%%%99FFFF66&>666BdKKKKr 	 	An,,-[-[-[-[\\~--c1-==;#%%&----E &    #2T****JqMMMM"$////5	
PF6N
P
Pvi/@
P
P
PQQQ	
(v
(
()))	
6dCCCC4s   A&H==
I
	I
c                  $   t                       t          ddddddddddd	d
dddd           t          dd dd dd dd dd dd            t          t                    D ]\  } }t          j        dd|d         gdd          }|j                                        }|dk    rdnd}|d         d}t          d| dz    d |d!         dd|ddt          |d"                   d
d|dd|d#                     t                       d$S )%zPrint formatted model list.z  #z<3rH   Model22sStatus12sPort6sContextz>8sz  Descriptionu	   ───uB   ──────────────────────u$   ────────────u   ──────u   ────────u   ──────────────────────────────────────────────────────────r2   r3   r4   Tr5   r7   u   🟢 ACTIVEu   ⚪rO   ,z  [   z] rC   rA   rP   N)rQ   	enumerater   r9   r:   r;   r<   str)ir	   r=   active_statusrZ   ctxs         r.   show_all_modelsrq      s   	GGG	
]s
]
]
]
]
]
]h
]
]
]V
]
]
]
]
]
]
]^^^	
Nw
N
N
N
NH
N
Nw
N
N
N
NH
N
NOOOf%% p p5N+uY'78d
 
 
 (("/8";";y!%%nAaCnn5=nnnvnnnCf<N<NnnnTWnnn_dek_lnnoooo	GGGGGr?   c            	         t          t          j                  dk    r&t          j        d                                                             dd                              dd          } t
          D ]y}| |d                                         k    sD| |d                                                             dd                              dd          v rt          |          rdndc S zt          d	d
                    d t
          D                                   t          dt          j        d          d           dS 	 t          j
        t          j        dk    rdnd           t                      }t          d           t          d           t          d           |r1t          d|d                     t          d|d                     nt          d           t                       t          d           t          dd                    d t
          d d         D                                   t                       t          d           t                       t          d                                                                          dv rt          d            d S fd!t
          D             }|s	 t!                    dz
  }d|cxk    rt          t
                    k     rn nt
          |         g}nc# t"          $ rV t
          D ]K}|d                                                             dd                              dd          v r|g} nLY nw xY w|r%t          |d                    t          d"           n4t          d#t          t
                     d$           t          d%           )&Nrk   -rD   rH   shortrC   r   r   zUnknown model. Try: z, c              3   &   K   | ]}|d          V  dS rt   N .0ms     r.   	<genexpr>zmain.<locals>.<genexpr>   s&      .J.Jaqz.J.J.J.J.J.Jr?   z	Example: z 9bTposixclearclsu   ╔══════════════════════════════════════════════════════╗u<   ║      🤖  Hermes Local Model Switcher  v4           ║u   ╚══════════════════════════════════════════════════════╝u   
  🟢 Currently running: z     detailu'   
  ⚪ No local model currently runningz  Quick shortcuts:z | c              3   &   K   | ]}|d          V  dS rv   rw   rx   s     r.   r{   zmain.<locals>.<genexpr>   s&       @ @7 @ @ @ @ @ @r?      z
  [q] Quitz  Select model (# or name): )qquitexitu   
  👋 Bye!c                 P    g | ]"}|d                                           k     |#S )rt   )lower)ry   rz   choices     r.   
<listcomp>zmain.<locals>.<listcomp>   s3    EEE!G*2B2B2D2D(D(D1(D(D(Dr?   z
  Press Enter to continue...u'   
  ❌ Invalid choice. Try a number (1-z) or shortcut name.z  Press Enter...)lensysargvr   r%   r   r`   rQ   joinr   systemrC   r>   rq   inputr<   int
ValueError)argr	   r7   matchedidxrz   r   s         @r.   mainr      s   
38}}qhqk!!))#r22::3CC 	/ 	/EeGn**,,,,uV}7J7J7L7L7T7TUXZ\7]7]7e7efikm7n7n0n0n KK.qqQ... 1oLTYY.J.J6.J.J.J%J%JLLMMM*#(1+***+++q)&
	RW//''U;;;#%%  y  	z  	z  	zLMMM  y  	z  	z  	z 	?AAABBB,&*,,----=>>>"###Bejj @ @VBQBZ @ @ @@@BBCCCl566<<>>DDFF***/"""E FEEEfEEE 		&kkAo))))c&kk)))))%c{mG     A6!2!2!:!:3!C!C!K!KCQS!T!TTT#$# U  	&23333]S[[]]]^^^$%%%S)&s   AL AM/.M/__main__u   

  👋 Bye!)__doc__r   r   rS   r9   r   urllib.requestrV   r   r   insertr   abspath__file__modelsr   
expanduserr   rm   r/   r>   r`   rq   r   __name__KeyboardInterruptrQ   rw   r?   r.   <module>r      sw  	 	 
			 



            27??27??8#<#<== > > >      ""#:;; #  3  #        6  : : :z  "5& 5& 5&p z! ! ! !      ! s   '
B3 3CC