+
    „WÝjdu  ã                  ó\  a € 0 t $ R t^ RIHt ^ RIt^ RIt^ RI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HtHt ^ RIHt ^ RIHt ]P2                  ! R4      tRtR	 R
 ltR R ltR R ltR R ltR R lt R R lt!R R lt"R R lt#R R lt$RR/R R llt%Rt&R]'R &   / t(R!]'R"&   / t)R#]'R$&   / t*R%]'R&&   ^t+R]'R'&   R(t,R]'R)&   R* R+ lt-R, R- lt.R. R/ lt/R0 R1 lt0RfR2 R3 llt1RfR4 R5 llt2R6 R7 lt3]4! 0 Rgm4      t5]4! 0 Rhm4      t6RiR8 R9 llt7R: R; lt8R< R= lt9RiR> R? llt:RjR@ RA llt;RB RC lt<RD RE lt=RjRF RG llt>RjRH RI llt? ! RJ RK]4      t@RL RM ltARN RO ltBRkRPRQ/RR RS llltCRlRT RU lltDRlRV RW lltERXtFRY RZ ltGR[ R\ ltHR]RQ/R^ R_ lltIR` Ra ltJRmRbRQRcRQ/Rd Re llltKR# )na›  Local / self-hosted model servers.

Ollama (native ``/api/tags`` probe, request headers, base-url resolution), LM Studio
(``/api/v1/models``, load-on-demand) and Ollama Cloud (live + models.dev merged catalog with a
disk cache). Split out of ``hermes_cli.models``; helpers still defined there are looked up on
``hermes_cli.models`` at call time so ``patch("hermes_cli.models.<name>")`` mocks keep intercepting.
)ÚannotationsN)ÚPath)ÚAnyÚ
NamedTupleÚOptional)Úget_secret_str)Ú
url_originzhermes_cli.modelsiª,  c               ó$   € V ^8„  d   QhRRRRRR/# )é   ÚrootÚstrÚsuffixesztuple[str, ...]Úreturn© )Úformats   "ÚKC:\Users\johnn\AppData\Local\hermes\hermes-agent\hermes_cli\models_local.pyÚ__annotate__r      s!   € ÷ ñ ˜#ð ¨ð ¸Sñ ó    c                ó†   € V F:  pV P                  V4      '       g   K  V R\        V4      )  P                  R4      u # 	  V # )zIDrop the first matching path suffix (and any trailing slash) from *root*.NÚ/)ÚendswithÚlenÚrstrip)r   r   Úsuffixs   && r   Ú_strip_suffixesr      s@   € ãˆØ�=‰=˜× Ô Ø˜œ3˜v›;˜,Ð'×.Ñ.¨sÓ3Ò3ñ ð €Kr   c               ó    € V ^8„  d   QhRRRR/# )r
   Úbase_urlúOptional[str]r   r   r   )r   s   "r   r   r   '   s   € ÷ ñ ¨ð ¸3ñ r   c                ó¼   € \        T ;'       g    R4      P                  4       pVP                  R4      '       d
   RV,           # V'       d   RV9  d
   RV,           # V# )z=Add a usable HTTP scheme without changing an OpenAI API path.Ú Ú:úhttp://127.0.0.1ú://úhttp://)r   ÚstripÚ
startswith)r   Úvalues   & r   Ú_normalize_openai_base_urlr'   '   sQ   € ä�—�˜BÓ×%Ñ%Ó'€EØ×Ñ˜×ÒØ! EÕ)Ð)ß�˜eÔ#Ø˜5Õ Ð Ø€Lr   c               ó    € V ^8„  d   QhRRRR/# )r
   r   r   r   r   )r   s   "r   r   r   1   s   € ÷ Mñ M¨#ð M°#ñ Mr   c                óð   € \        T ;'       g    R4      P                  4       P                  R4      pVP                  R4      '       d   RV,           pMV'       d   RV9  d
   RV,           p\	        VR4      # )z?Convert an OpenAI-style Ollama base URL to the native API root.r   r   r    r!   r"   r#   )ú	/api/tagsz
/v1/modelsú/apiú/v1)r   r$   r   r%   r   )r   r   s   & r   Ú_root_for_ollama_native_apir-   1   sa   € äˆx�~ˆ~˜2Ó×$Ñ$Ó&×-Ñ-¨cÓ2€DØ‡��s×ÒØ! DÕ(‰ß	�%˜tÔ#Ø˜4ÕˆÜ˜4Ð!KÓLÐLr   c               ó   € V ^8„  d   QhRR/# ©r
   r   r   r   )r   s   "r   r   r   ;   s   € ÷ Vñ V Sñ Vr   c                 óæ   € ^ RI Hp  V ! R4      p\        VP                  R4      ;'       g5    VP                  R4      ;'       g    VP                  R4      ;'       g    R4      P	                  4       # )zI``providers.ollama.base_url`` (legacy keys ``api`` / ``url``), or ``""``.©Ú_get_provider_config_dictÚollamar   ÚapiÚurlr   )Úhermes_cli.modelsr2   r   Úgetr$   )r2   Úcfgs     r   Ú_configured_ollama_base_urlr9   ;   sT   € å;á
# HÓ
-€CÜˆs�w‰w�zÓ"×LÐL c§g¡g¨e£n×LÐL¸¿¹À»×LÐLÈ"ÓM×SÑSÓUÐUr   c               ó    € V ^8„  d   QhRRRR/# )r
   Úenv_hostr   r   r   )r   s   "r   r   r   C   s   € ÷ ñ  Cð ¨Cñ r   c                óN  € \         pV P                  R4      '       d!   V P                  R4      '       g
   RV ,           # V P                  R4      '       d   V P                  R4      '       d   V  RV 2# RV 9   d×    \        P                  P                  V 4      pVP                  '       d£   VP                  f•   VP                  pRV9   d   VP                  R4      '       g   RV R2pRVP                  9   d+   VP                  P                  R^4      ^ ,          R,           MRpVP                  V V RV 2R	7      P                  4       # V # V P                  R4      ^8”  d    V P                  R4      '       g	   RV  R
V 2# RV 9  d   V  RV 2# V #   \         d     T # i ; i)zRApply Ollama's own ``OLLAMA_HOST`` defaulting rules (port 11434, IPv6 bracketing).r    z::z	127.0.0.1Ú[Ú]r"   Ú@r   )Únetlocz]:)Ú_OLLAMA_DEFAULT_PORTr%   r   ÚurllibÚparseÚurlsplitÚhostnameÚportr@   ÚrsplitÚ_replaceÚgeturlÚ
ValueErrorÚcount)r;   rF   ÚparsedrE   Úuserinfos   &    r   Ú_ollama_host_from_envrN   C   sŽ  € ä€DØ×Ñ˜3×Ò¨×(;Ñ(;¸D×(AÒ(AØ˜XÕ%Ð%Ø×Ñ˜3×Ò H×$5Ñ$5°c×$:Ò$:Ø�˜1˜T˜FÐ#Ð#Ø�Ôð		Ü—\‘\×*Ñ*¨8Ó4ˆFØ��ˆ 6§;¡;Ò#6Ø!Ÿ?™?�Ø˜(”?¨8×+>Ñ+>¸s×+CÒ+CØ!" 8 *¨A˜�HØDGÈ6Ï=É=ÔDX˜6Ÿ=™=×/Ñ/°°QÓ7¸Õ:¸SÖ@Ð^`�Ø—‘°°
¸8¸*ÀAÀdÀVÐ.L�ÓM×TÑTÓVÐVð ˆØ‡~�~�cÓ˜QÔ x×':Ñ':¸3×'?Ò'?Ø�8�*˜B˜t˜fÐ%Ð%Ø
�(ÔØ�˜1˜T˜FÐ#Ð#Ø€Oøô ô 	ØØˆð	ús   Á;0F Â,7F Ã$A)F ÆF$Æ#F$c               ó   € V ^8„  d   QhRR/# r/   r   )r   s   "r   r   r   ]   s   € ÷ Uñ U˜cñ Ur   c                 óN  € ^ RI Hp  \        4       pV'       d   V# V ! 4       p\        VP	                  RR4      ;'       g    R4      P                  4       P                  4       p\        VP	                  RR4      ;'       g    R4      P                  4       pVR8X  d   V'       d   V# VR8X  d   V'       d    \        RV4      '       d   V#  \        P                  ! RR4      P                  4       pV'       d   \        V4      # R#   \        \        \        \        3 d     LWi ; i)	u”  Resolve the local Ollama-compatible endpoint URL: explicit ``providers.ollama.base_url``
(wires local endpoints without changing the active provider) â†’ active ``model.base_url`` when
the active provider is ollama, or custom AND the endpoint actually serves ``/api/tags``
(otherwise the picker would probe an unrelated endpoint and hide the local catalog) â†’
``OLLAMA_HOST`` â†’ Ollama's local default.)Ú_get_model_config_dictÚproviderr   r   r3   ÚcustomÚOLLAMA_HOSTzhttp://localhost:11434)r6   rQ   r9   r   r7   r$   ÚlowerÚ should_use_ollama_native_catalogÚOSErrorÚRuntimeErrorÚ	TypeErrorrJ   ÚosÚgetenvrN   )rQ   Ú
configuredÚ	model_cfgÚmodel_providerÚ
model_baser;   s         r   Ú_get_ollama_base_urlr`   ]   sù   € õ 9Ü,Ó.€JßØÐá&Ó(€IÜ˜Ÿ™ z°2Ó6×<Ð<¸"Ó=×CÑCÓE×KÑKÓM€NÜ�Y—]‘] :¨rÓ2×8Ð8°bÓ9×?Ñ?ÓA€JØ˜Ô!§jØÐØ˜Ô!§jð	Ü/°¸*×EÒEØ!Ð!ð Fô �yŠy˜¨Ó+×1Ñ1Ó3€Hß.6Ô  Ó*ÐTÐ<TÐTøô œ¤y´*Ð=ô 	Ùð	ús   Â7D ÄD$Ä#D$c               ó$   € V ^8„  d   QhRRRRRR/# )r
   ÚentryÚdictÚenv_keysr   r   r   )r   s   "r   r   r   w   s&   € ÷ 
Bñ 
B¨ð 
B¸#ð 
BÀ#ñ 
Br   c                ó2  a € \        S P                  R4      ;'       g    R4      P                  4       pV'       d   V# \        \        V 3R lV 4       R4      ;'       g    R4      P                  4       pV'       d   \	        VR4      P                  4       # R# )a
  ``api_key`` from a provider config block, else the env var named by the first set *env_keys*.

The variable is read through the profile secret scope (fresh ``.env``, never another
profile's process env under multiplexing), like every other credential read (#67935).
Úapi_keyr   c              3  óx   <"  € T F/  pSP                  V4      '       g   K  SP                  V4      x € K1  	  R # 5i©N)r7   )Ú.0Úkrb   s   & €r   Ú	<genexpr>Ú0_api_key_from_provider_config.<locals>.<genexpr>€   s'   øé € ÐG©h¨¸%¿)¹)ÀA¿,œ˜Ÿ	™	 !Ÿ˜«hùs   ƒ:¡:)r   r7   r$   Únextr   )rb   rd   rf   Úkey_envs   f*  r   Ú_api_key_from_provider_configro   w   sw   ø€ ô �%—)‘)˜IÓ&×,Ð,¨"Ó-×3Ñ3Ó5€GßØˆÜ”$ÔG©hÓGÈÓL×RÐRÐPRÓS×YÑYÓ[€Gß29Œ>˜' 2Ó&×,Ñ,Ó.ÐA¸rÐAr   c               ó    € V ^8„  d   QhRRRR/# )r
   Úheadersúdict[str, str]r   ÚNoner   )r   s   "r   r   r   „   s   € ÷ ñ  ð °Dñ r   c                ó\   € \        V 4       F  pVP                  4       R 8X  g   K  W K  	  R# ©ÚauthorizationN)ÚtuplerU   )rq   Úkeys   & r   Ú_drop_authorizationry   „   s#   € Ü�WŽ~ˆØ�9‰9‹;˜/Ö)Ø’ó r   c               ó   € V ^8„  d   QhRR/# )r
   r   rr   r   )r   s   "r   r   r   Š   s   € ÷ ñ  ^ñ r   c                 ó\  € ^ RI Hp  V ! R4      p ^ RIHp V! VP	                  R4      4      p\        VRR4      pV'       dC   \        ;QJ d    R V 4       F  '       g   K   RM	  R	M! R V 4       4      '       g	   R
V 2VR&   V#   \
        \        \        \        \        3 d    / p L}i ; i)zEReturn configured headers and credentials for native Ollama requests.r1   r3   )Únormalize_extra_headersÚextra_headersrn   Úapi_key_envc              3  óF   "  € T F  qP                  4       R 8H  x € K  	  R# 5iru   )rU   )ri   rx   s   & r   rk   Ú._get_ollama_request_headers.<locals>.<genexpr>–   s   é € ÐLÁV¸cŸ9™9›;¨/Ö9ÃVùs   ‚!TFúBearer ÚAuthorization)r6   r2   Úhermes_cli.configr|   r7   ÚImportErrorrW   rX   rY   rJ   ro   Úany)r2   rb   r|   Úresultrf   s        r   Ú_get_ollama_request_headersr‡   Š   s”   € å;Ù% hÓ/€EðÝ=á(¨¯©°?Ó)CÓDˆô ,¨E°9¸mÓL€Gß—s“sÑLÁVÓL—s—s’sÑLÁVÓL×LÒLØ$+¨G¨9Ð"5ˆˆÑØ€Møô œ¤,´	¼:ÐFô ØŠðús   �B Â"B+Â*B+rf   c               ó$   € V ^8„  d   QhRRRRRR/# )r
   r   r   rf   r   rr   r   )r   s   "r   r   r   ›   s"   € ÷ ñ ¨ð ÀMð Ð]kñ r   c               ó:  € \        4       p^ RIHp V! V4      p\        T;'       d    T ;'       d    \	        W4      4      pV'       g   V'       g   / # V'       d   \        4       M/ pV'       g   \        V4      '       d   \        V4       V'       d	   RV 2VR&   V# )zçOllama credentials and headers for one endpoint origin. Configured headers apply only when
*base_url* shares the configured Ollama root; an explicit *api_key* replaces any configured
Authorization variant rather than inheriting it.©Úmaterialize_probe_api_keyr�   r‚   )r9   Úagent.command_token_sourcer‹   ÚboolÚ_same_ollama_native_rootr‡   Úcallablery   )r   rf   Úconfigured_baser‹   Úexplicit_keyÚconfigured_matchesrq   s   &$     r   Ú_get_ollama_native_headersr“   ›   s€   € ô 2Ó3€OÝDÙ,¨WÓ5€LÜ˜o×rÐr°(×rÐrÔ?WÐX`Ó?rÓsÐß§lØˆ	ß/AÔ)Ô+Àr€Gß”x ×(Ò(Ü˜GÔ$ßØ%,¨\¨NÐ#;ˆ�Ñ Ø€Nr   i,  ÚintÚ_OLLAMA_LOCAL_MODELS_CACHE_TTLz(dict[str, tuple[tuple[str, ...], float]]Ú_OLLAMA_LOCAL_MODELS_CACHEzdict[str, float]Ú!_OLLAMA_LOCAL_PROBE_FAILURE_CACHEzdict[str, bool]Ú_OLLAMA_LOCAL_PROBE_REACHABLEÚ_OLLAMA_LOCAL_PROBE_FAILURE_TTLé   Ú_OLLAMA_LOCAL_CACHE_MAX_ENTRIESc               ó    € V ^8„  d   QhRRRR/# )r
   rx   r   r   rs   r   )r   s   "r   r   r   ·   s   € ÷ Eñ E¨Sð E°Tñ Er   c                óú   € \         P                  V R 4       \        P                  V R 4       \        \        4       F;  pW8X  g   VP                  V  R24      '       g   K%  \        P                  VR 4       K=  	  R # )Nú	|timeout:)r–   Úpopr˜   Úlistr—   r%   )rx   Úfailure_keys   & r   Ú#_evict_related_ollama_cache_entriesr¢   ·   s_   € Ü×"Ñ" 3¨Ô-Ü!×%Ñ% c¨4Ô0ÜÔ=Ö>ˆØÔ ×!7Ñ!7¸3¸%¸yÐ8I×!JÔ!JÜ-×1Ñ1°+¸tÖDó ?r   c               ó(   € V ^8„  d   QhRRRRRRRR/# )	r
   Úcachezdict[str, Any]rx   r   r&   r   r   rs   r   )r   s   "r   r   r   ¿   s(   € ÷ ñ  .ð °sð À3ð È4ñ r   c                óª   € W9  dI   \        V 4      \        8¼  d5   \        \        \	        V 4      4      P                  R ^4      ^ ,          4       W V&   R# )rž   N)r   r›   r¢   rm   ÚiterÚsplit)r¤   rx   r&   s   &&&r   Ú_remember_ollama_cacher¨   ¿   s@   € Ø
ÔœC ›JÔ*IÔIÜ+¬D´°e³Ó,=×,CÑ,CÀKÐQRÓ,SÐTUÕ,VÔWØˆ#ƒJr   c               ó$   € V ^8„  d   QhRRRRRR/# )r
   r   r   rq   úOptional[dict[str, str]]r   r   )r   s   "r   r   r   Å   s'   € ÷ Wñ W #ð WÐ0Hð WÈSñ Wr   c                ó   € V'       g   V # \        R  VP                  4        4       4      p\        P                  ! VRRR7      P	                  RRR7      pV  R\
        P                  ! V^R7      P                  4        2# )	c              3  ón   "  € T F+  w  r\        V4      P                  4       \        V4      3x € K-  	  R # 5irh   )r   rU   )ri   rx   r&   s   &  r   rk   Ú*_ollama_probe_cache_key.<locals>.<genexpr>È   s(   é € ÐaÑQ`Á:À3¤ S£§¡Ó!1´3°u³:Õ >ÓQ`ùs   ‚35F)Úensure_asciiÚ
separatorszutf-8Úreplace)Úerrorsz	|headers:)Údigest_size)Ú,r    )ÚsortedÚitemsÚjsonÚdumpsÚencodeÚhashlibÚblake2bÚ	hexdigest)r   rq   Únormalized_headersÚheader_blobs   &&  r   Ú_ollama_probe_cache_keyr¾   Å   sq   € ßØˆÜÑaÐQX×Q^ÑQ^ÔQ`ÓaÓaÐÜ—*’*Ð/¸eÐPZÔ[×bÑbÐcjÐs|ÐbÓ}€KØˆV�9œWŸ_š_¨[ÀaÔH×RÑRÓTÐUÐVÐVr   c               ó    € V ^8„  d   QhRRRR/# )r
   Úpayloadr   r   úOptional[list[str]]r   )r   s   "r   r   r   Í   s   € ÷ ñ  ð Ð(;ñ r   c                óÐ  € \        V \        4      '       d   V P                  R4      MRp\        V\        4      '       g   R# . pV FŠ  p\        V\        4      '       g    R# \	        VP                  R4      ;'       g    VP                  R4      ;'       g    R4      P                  4       pV'       g   Kq  WB9  g   Ky  VP                  V4       KŒ  	  V'       d   V'       g   R# V# )zMModel ids from an ``/api/tags`` payload; None when the shape is not Ollama's.ÚmodelsNÚmodelÚnamer   )Ú
isinstancerc   r7   r    r   r$   Úappend)rÀ   Ú
raw_modelsrÃ   ÚitemÚmodel_ids   &    r   Ú_parse_ollama_tagsrË   Í   s§   € ä*4°W¼d×*CÒ*C�—‘˜XÔ&È€JÜ�j¤$×'Ò'ÙØ€FÛˆÜ˜$¤×%Ò%ÚÜ�t—x‘x Ó(×BÐB¨D¯H©H°VÓ,<×BÐBÀÓC×IÑIÓKˆß‰8˜Ö.Ø�M‰M˜(Ö#ñ ÷ Ÿ&ÙØ€Mr   c               ó(   € V ^8„  d   QhRRRRRRRR/# ©	r
   r   r   ÚtimeoutÚfloatrq   rª   r   rÁ   r   )r   s   "r   r   r   Þ   s0   € ÷ %ñ %Øð%àð%ð &ð%ð ñ	%r   c           	     ó@  € ^ RI HpHpHp \	        T ;'       g    V! 4       4      pV'       g   R# \        Wb4      pV R\        V4      R 2p\        P                  V4      p	V	e?   \        P                  ! 4       V	^,          ,
          \        8  d   \        V	^ ,          4      # \        P                  V4      p
V
e>   \        P                  ! 4       V
,
          \        8  d   R# \        P                  VR4        RV/T;'       g    / Cp\         P"                  P%                  VP'                  R4      R,           VR7      pV! WÁR	7      ;_uu_ 4       p\)        \*        P,                  ! VP/                  4       P1                  4       4      4      pRRR4       Xf8   \G        \H        TR
4       \G        \        T\        P                  ! 4       4       R# \G        \H        TR4       \        P                  TR4       \G        \        T\K        T4      \        P                  ! 4       34       T#   + '       g   i     L£; i  \2        \4        \6        \8        P:                  P<                  \         P>                  P@                  \*        PB                  \D        3 d    Rp ELi ; i)a  Probe local Ollama-compatible models from native ``/api/tags`` (Ollama's authoritative local
catalog; ``/v1/models`` is not required for local servers). ``None`` when the endpoint cannot be
reached or returns malformed data; a list (possibly empty) when it was reachable.)Ú_HERMES_USER_AGENTr`   Ú_urlopen_model_catalog_requestNrž   z.3fú
User-Agentr   r*   ©rq   ©rÎ   FT)&r6   rÑ   r`   rÒ   r-   r¾   rÏ   r–   r7   ÚtimeÚ	monotonicr•   r    r—   r™   rŸ   rB   ÚrequestÚRequestr   rË   r¶   ÚloadsÚreadÚdecoderJ   rW   ÚTimeoutErrorÚhttpÚclientÚHTTPExceptionÚerrorÚURLErrorÚJSONDecodeErrorÚUnicodeDecodeErrorr¨   r˜   rw   )r   rÎ   rq   rÑ   r`   rÒ   r   Ú	cache_keyr¡   ÚcachedÚ	failed_atÚrequest_headersÚreqÚresprÃ   s   &&&            r   Úprobe_ollama_local_modelsrë   Þ   sð  € ÷ kÑjÜ& x×'IÐ'IÑ3GÓ3IÓJ€DßÙÜ'¨Ó6€IØ�K˜y¬¨w«¸Ð(<Ð=€KÜ'×+Ñ+¨IÓ6€FØÒœdŸnšnÓ.°¸µÕ:Ô=[Ô[Ü�F˜1•I‹ÐÜ1×5Ñ5°kÓB€IØÒÜ�>Š>Ó˜iÕ'Ô*IÔIÙÜ)×-Ñ-¨k¸4Ô@ðØ'Ð);ÐOÀÇÀÈ2ÐOˆÜ�n‰n×$Ñ$ T§[¡[°Ó%5¸Õ%CÈ_Ð$Ó]ˆÙ+¨C×AÕAÀTÜ'¬¯
ª
°4·9±9³;×3EÑ3EÓ3GÓ(HÓIˆF÷ Bð
 ‚~ÜÔ<¸iÈÔOÜÔ@À+ÌtÏ~Ê~ÓO_Ô`ÙÜÔ8¸)ÀTÔJÜ%×)Ñ)¨+°tÔ<ÜÔ5°yÄ5ÈÃ=ÔRV×R`ÒR`ÓRbÐBcÔdØ€M÷ B×Aûäœ¤¬t¯{©{×/HÑ/HÌ&Ï,É,×J_ÑJ_Ü× Ñ Ô"4ð6ô à‹ðús8   Ã9H; ÄAH; Å<H(ÆH; È(H8	È3H; È8H; È;AJÊJc               ó(   € V ^8„  d   QhRRRRRRRR/# rÍ   r   )r   s   "r   r   r     s6   € ÷ Iñ IØðIàðIð &ðIð ñ	Ir   c                ó   € \        WVR7      # )zKFetch local Ollama-compatible models, preserving probe failure as ``None``.rÔ   )rë   )r   rÎ   rq   s   &&&r   Úfetch_ollama_local_modelsrî     s   € ô % XÀÔHÐHr   c               ó$   € V ^8„  d   QhRRRRRR/# )r
   Úleftr   Úrightr   r�   r   )r   s   "r   r   r     s!   € ÷ ñ  3ð ¨sð °tñ r   c                óè  € \        V 4      P                  R4      p\        V4      P                  R4      pV'       d	   V'       g   R#  \        P                  P	                  V4      p\        P                  P	                  V4      p\        V4      \        V4      8H  ;'       d8    VP                  P                  R4      VP                  P                  R4      8H  #   \        \        3 d     R# i ; i)zEReturn True when two Ollama/OpenAI-style base URLs share an API root.r   F)	r-   r   rB   rC   rD   r   ÚpathÚAttributeErrorrJ   )rð   rñ   Ú	left_rootÚ
right_rootÚ
left_partsÚright_partss   &&    r   rŽ   rŽ     sÅ   € ä+¨DÓ1×8Ñ8¸Ó=€IÜ,¨UÓ3×:Ñ:¸3Ó?€JßŸJÙðÜ—\‘\×*Ñ*¨9Ó5ˆ
Ü—l‘l×+Ñ+¨JÓ7ˆä�yÓ!¤Z°
Ó%;Ñ;÷ Lð LØ—‘×&Ñ& sÓ+¨{×/?Ñ/?×/FÑ/FÀsÓ/KÑKð	
øô œJÐ'ô Úðús   ÁAC Â$7C ÃC1Ã0C1c               ó(   € V ^8„  d   QhRRRRRRRR/# )r
   rR   r   r   rq   rª   r   r�   r   )r   s   "r   r   r   $  s6   € ÷ 1Uñ 1UØð1Uàð1Uð &ð1Uð 
ñ	1Ur   c                ó°  € \        T ;'       g    R4      P                  4       P                  4       p\        T;'       g    R4      pV'       dd    \        P
                  P                  V4      P                  ;'       g    RP                  4       pVR8X  g   VP                  R4      '       d   R#  V\        9   d   R# \        4       pVR8X  d6   V'       g   R# V'       d"   \        WF4      '       g   \        VRVR7      RJ# R	# V'       d   \        WF4      '       d   R	# V'       g   R# V\        9  d   VP                  R
4      '       g   R# VR8X  g   VP                  R4      '       d   R	#  \        P
                  P                  V4      P                   \"        8w  d   R#  \        TRTR7      RJ#   \         d     ELi ; i  \         d     R# i ; i)a·  True when model discovery should use local Ollama ``/api/tags``: the caller asked for Ollama
explicitly, the base URL matches ``providers.ollama.base_url``, or an ambiguous custom URL on
Ollama's default port actually serves ``/api/tags``. (Bare ``ollama`` is normalized to
``custom`` elsewhere so runtime paths share the OpenAI client, but ``/api/tags`` is the
authoritative local list; other custom endpoints keep the ``/models`` probe.)r   z
ollama.comz.ollama.comFr3   g      à?©rÎ   rq   NTzcustom:zcustom:ollamaz-ollama)r   r$   rU   r-   rB   rC   ÚurlparserE   r   rJ   Ú_NEVER_OLLAMA_PROVIDERSr9   rŽ   rë   Ú_LOCAL_LIKE_PROVIDERSr%   rF   rA   )rR   r   rq   Ú	requestedr   Úhostr�   s   &&&    r   rV   rV   $  s‹  € ô �H—N�N Ó#×)Ñ)Ó+×1Ñ1Ó3€IÜ& x§~ ~°2Ó6€Dßð	Ü—L‘L×)Ñ)¨$Ó/×8Ñ8×>Ð>¸B×EÑEÓGˆDØ�|Ô# t§}¡}°]×'CÒ'CÙð (Dð
 Ô+Ô+Ùä1Ó3€OØ�HÔßÙßÔ#;¸D×#RÒ#RÜ,¨T¸3ÈÔPÐX\Ð\Ð\ÙçÔ3°D×JÒJÙçÙàÔ-Ô-°i×6JÑ6JÈ9×6UÒ6UÙà�OÔ# y×'9Ñ'9¸)×'DÒ'DÙðÜ�<‰<× Ñ  Ó&×+Ñ+Ô/CÔCÙð Dô
 % T°3ÀÔHÐPTÐTÐTøôA ô 	Úð	ûô: ô Úðús*   Á/F4 Â .F4 Å/2G Æ4GÇGÇGÇGc               ó    € V ^8„  d   QhRRRR/# )r
   Úforce_refreshr�   r   ú	list[str]r   )r   s   "r   r   r   X  s   € ÷ añ a¨ð a°)ñ ar   c                ó„  € ^ RI HpHp V '       d=   \        P	                  4        \
        P	                  4        \        P	                  4        \        4       p\        V4      p\        RW4R7      '       dl   V'       d   \        W4R7      M
\        V4      p\        \        V4      T;'       g    R4      pV'       g   \        P                  V4      RJ d   T;'       g    . # V! R4      p\        VR4      p\        VP                  R4      ;'       g    T4      p	\        W˜R7      p
T! Y‰T
;'       g    RR7      ;'       g    . # )	z½Catalog for the raw ``ollama`` provider: native ``/api/tags`` when the endpoint is a real
Ollama server, else the OpenAI-style ``/v1/models`` of the configured gateway (incl. Ollama
Cloud).)r2   Úfetch_api_modelsr3   rÔ   NTrn   r   )rf   )r6   r2   r  r–   Úclearr—   r˜   r`   r“   rV   rî   r¾   r-   r7   ro   r'   )r  r2   r  r   rq   Únative_modelsÚ
native_keyÚconfigÚfallback_keyÚfallback_baseÚfallback_headerss   &          r   Ú_ollama_local_catalogr  X  s  € ÷ NßÜ"×(Ñ(Ô*Ü)×/Ñ/Ô1Ü%×+Ñ+Ô-Ü#Ó%€HÜ(¨Ó2€GÜ'¨°(×LÓLßPWÔ1°(ÕLÔ]vÐwó  ^AˆÜ,Ô-HÈÓ-RÐT[×TcÐTcÐ_cÓdˆ
ßÔ9×=Ñ=¸jÓIÈTÓQØ ×&Ð& BÐ&Ù& xÓ0€FÜ0°¸ÓC€LÜ.¨v¯z©z¸*Ó/E×/QÐ/QÈÓR€MÜ1°-ÔVÐÙ˜LÐAQ×AYÐAYÐUYÔZ×`Ð`Ð^`Ð`r   c               ó    € V ^8„  d   QhRRRR/# )r
   r   r   r   r   )r   s   "r   r   r   o  s   € ÷ eñ e Mð e°mñ er   c                ó|   € \        T ;'       g    RP                  4       P                  R4      R4      ;'       g    R# )z«LM Studio server root: users paste the OpenAI runtime URL (``.../v1``) or the native prefix
(``.../api``, ``.../api/v1``); native probes append ``/api/v1/...`` themselves.r   r   N)z/api/v1r+   r,   )r   r$   r   )r   s   &r   Ú_lmstudio_server_rootr  o  s5   € ô ˜HŸN˜N¨×1Ñ1Ó3×:Ñ:¸3Ó?ÐA[Ó\×dÐdÐ`dÐdr   c               ó    € V ^8„  d   QhRRRR/# )r
   rf   r   r   rc   r   )r   s   "r   r   r   u  s   € ÷ iñ i }ð iÀñ ir   c                óV   € ^ RI Hp ^ RIHp V! V 4      pRV/V'       d	   RRV 2/C# / C# )z/HTTP headers for LM Studio native API requests.)rÑ   rŠ   rÓ   r‚   r�   )r6   rÑ   rŒ   r‹   )rf   rÑ   r‹   Útokens   &   r   Ú_lmstudio_request_headersr  u  s;   € å4ÝDÙ% gÓ.€EØÐ,Ðh×Y^°/ÀWÈUÈGÐCTÐ1UÐhÐhÐdfÐhÐhr   c               ó(   € V ^8„  d   QhRRRRRRRR/# )r
   rf   r   r   rÎ   rÏ   r   úOptional[list[dict]]r   )r   s   "r   r   r   }  s0   € ÷ "ñ "Øð"àð"ð ð"ð ñ	"r   c                ó\  € ^ RI Hp \        V4      pV'       g   R# \        P                  P                  VR,           \        V 4      R7      p V! WRR7      ;_uu_ 4       p\        P                  ! VP                  4       P                  4       4      pRRR4       \'        X\(        4      '       d   TP+                  R4      MRp
\'        T
\,        4      '       g   \         P#                  RT4       R# T
#   + '       g   i     Li; i  \        P                  P                   d]   pTP                  R9   d!   ^ RIHp	 T	! RTP                   R2R	R
R7      Th\         P#                  RYHP                  4        Rp?R# Rp?i\$         d"   p\         P#                  RYH4        Rp?R# Rp?ii ; i)z†Raw model list from LM Studio's ``/api/v1/models``; None on network errors / malformed
payloads; raises ``AuthError`` on HTTP 401/403.©rÒ   Nz/api/v1/modelsrÔ   rÕ   )Ú	AuthErrorz)LM Studio rejected the request with HTTP Ú.ÚlmstudioÚauth_rejected)rR   Úcodez)LM Studio probe at %s failed with HTTP %sz LM Studio probe at %s failed: %srÃ   zCLM Studio probe at %s returned malformed payload (no `models` list)>   é‘  é“  )r6   rÒ   r  rB   rØ   rÙ   r  r¶   rÚ   rÛ   rÜ   rá   Ú	HTTPErrorr  Úhermes_cli.authr  ÚloggerÚdebugÚ	ExceptionrÆ   rc   r7   r    )rf   r   rÎ   rÒ   Úserver_rootrØ   rê   rÀ   Úexcr  rÈ   s   &&&        r   Ú_lmstudio_fetch_raw_modelsr'  }  sD  € õ AÜ'¨Ó1€KßÙä�n‰n×$Ñ$ [Ð3CÕ%CÔMfÐgnÓMoÐ$Óp€GðÙ+¨G×EÕEÈÜ—j’j §¡£×!3Ñ!3Ó!5Ó6ˆG÷ Fô  +5°W¼d×*CÒ*C�—‘˜XÔ&È€JÜ�j¤$×'Ò'Ü�‰ÐZÐ\gÔhÙØÐ÷) F×Eûä�<‰<×!Ñ!ô 	Ø�8‰8�zÔ!Ý1ÙØ;¸C¿H¹H¸:ÀQÐGØ#Ø$ôð ð	ô
 	�‰Ð@À+ÏxÉxÔXÝûÜô Ü�‰Ð7¸ÔJÝûðúsI   ÁD Á3C3ÂD Ã3D	Ã>D ÄD ÄF+Ä%AE<Å<F+Æ	F+Æ
F&Æ&F+c               ó   € V ^8„  d   QhRR/# )r
   r   r  r   )r   s   "r   r   r   ¢  s   € ÷ ñ Ð@Tñ r   c                óB   €  \        WVR7      #   \         d     R# i ; i)zV``_lmstudio_fetch_raw_models`` with every failure (incl. AuthError) collapsed to None.©rf   r   rÎ   N)r'  r$  r*  s   &&&r   Ú_lmstudio_raw_models_or_noner+  ¢  s'   € ðÜ)°'ÐV]Ô^Ð^øÜô Úðús   ‚ ��c               ó$   € V ^8„  d   QhRRRRRR/# )r
   rÈ   r    rÄ   r   r   úOptional[dict]r   )r   s   "r   r   r   ª  s!   € ÷ ñ  Dð °ð ¸ñ r   c                ó¨   € V  FK  p\        V\        4      '       g   K  VP                  R 4      V8X  g   VP                  R4      V8X  g   KI  Vu # 	  R# )rx   ÚidN)rÆ   rc   r7   )rÈ   rÄ   Úraws   && r   Ú_lmstudio_entry_forr1  ª  sB   € ÛˆÜ�cœ4× Ô  c§g¡g¨e£n¸Ô&=ÀÇÁÈÃÐRWÖAWØŠJñ ñ r   c               ó(   € V ^8„  d   QhRRRRRRRR/# )r
   rf   r   r   rÎ   rÏ   r   rÁ   r   )r   s   "r   r   r   ±  s0   € ÷ ñ Øðàðð ðð ñ	r   c                óØ  € \        WVR7      pVf   R# . pV FÎ  p\        V\        4      '       dF   \        VP	                  R4      ;'       g    R4      P                  4       P                  4       R8X  d   K`  \        VP	                  R4      ;'       g    VP	                  R4      ;'       g    R4      P                  4       pV'       g   Kµ  Wd9  g   K½  VP                  V4       KÐ  	  V# )u  Chat-capable LM Studio model keys â€” a valid empty list when the server is reachable but has
no non-embedding models; ``None`` on network errors, malformed responses, or bad base URLs.
Raises ``AuthError`` on HTTP 401/403 so token issues surface separately from reachability.r*  NÚtyper   Ú	embeddingrx   r/  )r'  rÆ   rc   r   r7   r$   rU   rÇ   )rf   r   rÎ   rÈ   Úkeysr0  rx   s   &&&    r   Úprobe_lmstudio_modelsr7  ±  s·   € ô ,°GÐX_Ô`€JØÒÙà€DÛˆÜ˜#œt×$Ò$¬¨C¯G©G°F«O×,AÐ,A¸rÓ(B×(HÑ(HÓ(J×(PÑ(PÓ(RÐVaÔ(aÙÜ�#—'‘'˜%“.×7Ð7 C§G¡G¨D£M×7Ð7°RÓ8×>Ñ>Ó@ˆß‰3�3–?Ø�K‰K˜Öñ ð €Kr   c               ó(   € V ^8„  d   QhRRRRRRRR/# )r
   rf   r   r   rÎ   rÏ   r   r  r   )r   s   "r   r   r   Ç  s6   € ÷ \ñ \Øð\àð\ð ð\ð ñ	\r   c                ó0   € \        WVR7      ;'       g    . # )z±LM Studio chat-capable model keys; ``[]`` when unreachable/malformed. Raises ``AuthError`` on
HTTP 401/403 so callers can tell a wrong ``LM_API_KEY`` from an unreachable server.r*  )r7  r*  s   &&&r   Úfetch_lmstudio_modelsr:  Ç  s   € ô !¨ÈWÔU×[Ð[ÐY[Ð[r   c                  óB   € ] tR tRt$ RtR]R&   RtR]R&   RtR]R&   R	tR
# )ÚLMStudioLoadResultiÑ  z8Verified LM Studio runtime plus load-attempt provenance.úOptional[int]Úcontext_lengthFr�   Úload_attemptedÚrejectedr   N)	Ú__name__Ú
__module__Ú__qualname__Ú__firstlineno__Ú__doc__Ú__annotations__r?  r@  Ú__static_attributes__r   r   r   r<  r<  Ñ  s   ‡ ÙBà!Ó!Ø €N�DÓ Ø€Hˆd×r   r<  c               ó    € V ^8„  d   QhRRRR/# )r
   r&   r   r   r=  r   )r   s   "r   r   r   Ù  s   € ÷ ñ ˜ð  ñ r   c                óp   € \        V \        4      '       d    \        V \        4      '       g
   V ^ 8”  d   V # R# )é    N)rÆ   r”   r�   )r&   s   &r   Ú_positive_intrK  Ù  s)   € Ü�%œ×Ò¤j°¼×&=Ò&=À%È!Ä)ØˆÙr   c               ó    € V ^8„  d   QhRRRR/# )r
   rb   r-  r   r=  r   )r   s   "r   r   r   ß  s   € ÷ 
ñ 
 Nð 
°}ñ 
r   c                ó<  € V e   V P                  R4      MRp\        V\        4      '       g   R# V Ff  p\        V\        4      '       d   VP                  R4      MRp\	        \        V\        4      '       d   VP                  R4      MR4      pVf   Kd  Vu # 	  R# )zNFirst positive ``loaded_instances[*].config.context_length`` of a model entry.NÚloaded_instancesr	  r>  )r7   rÆ   r    rc   rK  )rb   Ú	instancesÚinstancer	  rL   s   &    r   Ú_lmstudio_loaded_contextrQ  ß  s‚   € à16Ò1B�—	‘	Ð,Ô-È€IÜ�i¤×&Ò&ÙÛˆÜ+5°hÄ×+EÒ+E�—‘˜hÔ'È4ˆÜ¼zÈ&ÔRV×?WÒ?W˜vŸz™zÐ*:Ô;Ð]aÓbˆØÔØŠMñ	 ñ
 r   Úreturn_load_resultFc               ó4   € V ^8„  d   QhRRRRRRRRRR	R
RRR/# )r
   rÄ   r   r   r   rf   Útarget_context_lengthr=  rÎ   rÏ   rR  r�   r   z"Optional[int] | LMStudioLoadResultr   )r   s   "r   r   r   ì  s`   € ÷ Fpñ FpØðFpàðFpð ðFpð )ð	Fpð
 ðFpð ðFpð (ñFpr   c               ó&  a€ ^ RI Hp RRRR/R V3R lllp\        V4      pV'       g	   V! R4      # \        V4      p	Ve   V	f	   V! R4      # \	        \        W!^
4      ;'       g    . V 4      p
V
f	   V! R4      # \        V
P                  R4      4      pV	e   Ve   W›8”  d   V! RR	R
7      # \        V
4      pVe	   V! V4      # V
P                  R4      p\        V\        4      '       d	   V'       d	   V! R4      # RV RR	/pV	e   WžR&    \        P                  P                  VR,           \        P                  ! V4      P                  4       / \!        V4      CRR/CRR7      pV! WôR7      ;_uu_ 4       pVP#                  4       pRRR4        \        P&                  ! XP)                  4       4      p\        T\*        4      '       d   TP                  R4      MRp\        T\*        4      '       d   \        TP                  R4      4      MRpTe   T! TR	R7      # \        Y!^
4      pTf   T! RR	R7      # T! \        \	        TT 4      4      R	R7      #   + '       g   i     LÕ; i  \$         d    T! RR	R7      u # i ; i  \$         d    Rp LÝi ; i)a  Ensure ``model`` is loaded and return verified runtime context.

Existing loaded-instance context is authoritative. Cold loads omit ``context_length`` unless the
caller supplied an explicit override; the returned context comes from LM Studio's echoed or
refreshed state.r  r?  Fr@  c               ó$   € V ^8„  d   QhRRRRRR/# )r
   r>  r=  r?  r�   r@  r   )r   s   "r   r   Ú2ensure_lmstudio_model_loaded.<locals>.__annotate__ü  s'   € ÷ @ñ @ ð @À$ð @ÐZ^ñ @r   c               ó4   <€ \        WV4      pS'       d   V# T # rh   )r<  )r>  r?  r@  r†   rR  s   &$$ €r   Ú_resultÚ-ensure_lmstudio_model_loaded.<locals>._resultü  s   ø€ Ü# NÀHÓMˆß+ˆvÐ?°Ð?r   NÚmax_context_lengthT)r@  rN  rÄ   Úecho_load_configr>  z/api/v1/models/loadzContent-Typezapplication/jsonÚPOST)Údatarq   ÚmethodrÕ   )r?  Úload_config)r6   rÒ   r  rK  r1  r+  r7   rQ  rÆ   r    rB   rØ   rÙ   r¶   r·   r¸   r  rÛ   r$  rÚ   rÜ   rc   )rÄ   r   rf   rT  rÎ   rR  rÒ   rY  r%  Úexplicit_contextÚtarget_entryÚmax_ctxÚcurrent_contextrN  Úload_payloadÚload_requestrê   Úresponse_bodyÚresponse_payloadr`  Úapplied_contextÚrefreshed_modelss   &&&&&d                r   Úensure_lmstudio_model_loadedrk  ì  s’  ø€ õ Að@Èð @Ðaf÷ @ò @ô (¨Ó1€KßÙ�t‹}Ðä$Ð%:Ó;ÐØÒ(Ð-=Ò-EÙ�t‹}ÐÜ&Ô'CÀGÐWYÓ'Z×'`Ð'`Ð^`ÐbgÓh€LØÒÙ�t‹}Ðä˜L×,Ñ,Ð-AÓBÓC€GØÒ#¨Ò(;Ð@PÔ@ZÙ�t dÔ+Ð+ä.¨|Ó<€OØÒ"Ù�Ó'Ð'à#×'Ñ'Ð(:Ó;ÐÜÐ&¬×-Ò-×1AÙ�t‹}Ðà$+¨UÐ4FÈÐ#M€LØÒ#Ø)9Ð%Ñ&ð
2Ü—~‘~×-Ñ-ØÐ/Õ/Ü—’˜LÓ)×0Ñ0Ó2Ø^Ô0°Ó9Ð^¸>ÐK]Ñ^Øð	 .ó 
ˆñ ,¨L×JÕJÈdØ ŸI™I›KˆM÷ Kð
 ÜŸ:š: m×&:Ñ&:Ó&<Ó=Ðô :DÐDTÔVZ×9[Ò9[Ð"×&Ñ& }Ô5Ðae€KÜJTÐU`Ôbf×JgÒJg”m K§O¡OÐ4DÓ$EÔFÐmq€OØÒ"Ù�°tÔ<Ð<ä3°GÀrÓJÐØÒÙ�t¨DÔ1Ð1ÙÔ+Ô,?Ð@PÐRWÓ,XÓYÐjnÔoÐo÷# K×Jûäô 2Ù�t¨DÔ1Ò1ð2ûô
 ô  ØÒð úsC   ÄA,I% Å4IÆI% Æ$J  ÉI"	ÉI% É"I% É%I=É<I=Ê JÊJc          
     ó,   € V ^8„  d   QhRRRRRRRRRR	/# )
r
   rÄ   r   r   r   rf   rÎ   rÏ   r   r  r   )r   s   "r   r   r   5  s:   € ÷ ñ Øðàðð ðð ð	ð
 ñr   c                óì  € \        \        W!V4      ;'       g    . V 4      pVf   . # VP                  R4      p\        V\        4      '       d   VP                  R4      MRp\        V\        4      '       d   VP                  R4      MRp\        V\
        4      '       dP   V Uu. uFB  p\        V\        4      '       g   K  \        V4      P                  4       P                  4       NKD  	  up# . # u upi )z¤Reasoning ``allowed_options`` LM Studio publishes for ``model`` under
``capabilities.reasoning`` in ``/api/v1/models``; ``[]`` when unknown, unreachable, or absent.NÚcapabilitiesÚ	reasoningÚallowed_options)	r1  r+  r7   rÆ   rc   r    r   r$   rU   )	rÄ   r   rf   rÎ   r0  Úcapsro  ÚoptsÚos	   &&&&     r   Ú lmstudio_model_reasoning_optionsrt  5  sÀ   € ô Ô:¸7ÈgÓV×\Ð\ÐZ\Ð^cÓ
d€CØ
‚{Øˆ	Ø�7‰7�>Ó"€DÜ)3°D¼$×)?Ò)?�—‘˜Ô%ÀT€IÜ/9¸)ÄT×/JÒ/Jˆ9�=‰=Ð*Ô+ÐPT€DÜ�$œ×ÒÙ04ÓK±¨1¼
À1Äc×8JÔ&”�A“—‘“×$Ñ$Ö&±ÑKÐKØ€Iùò Ls   Â$C1Ã+C1c          
     ó,   € V ^8„  d   QhRRRRRRRRRR	/# )
r
   rÄ   r   r   r   rf   rÎ   rÏ   r   zOptional[bool]r   )r   s   "r   r   r   H  s:   € ÷ ñ Øðàðð ðð ð	ð
 ñr   c                ó¬  € ^ RI pT;'       g    RP                  4       P                  R4      pVP                  R4      p\	        T ;'       g    RP                  4       4      pV'       d	   V'       g   R# ^ RIHp V! V4      p TP                  Y8'       d   RRV 2/M/ R7      ;_uu_ 4       p	V	P                  V R	2R
V/R7      p
V
P                  ^È8w  d    RRR4       R# V
P                  4       P                  R4      p\        V\        4      '       d   RV9   uuRRR4       #  RRR4       R#   + '       g   i     R# ; i  \         d     R# i ; i)a  Tri-state: True if an Ollama (Cloud or local) model advertises ``thinking`` in native
``/api/show`` ``capabilities`` (authoritative; OpenAI-compat ``/v1/models`` omits it), False
when the probe succeeded without it, None when it failed (caller treats as "don't emit").Nr   r   r,   rŠ   r‚   r�   rû   z	/api/showrÅ   )r¶   rn  Úthinking)Úhttpxr$   r   ÚremovesuffixÚ_strip_ollama_cloud_suffixrŒ   r‹   ÚClientÚpostÚstatus_coder¶   r7   rÆ   r    r$  )rÄ   r   rf   rÎ   rx  Ú
server_urlÚ
bare_modelr‹   r  rß   rê   rq  s   &&&&        r   Úollama_model_supports_thinkingr€  H  s/  € ó à—.�.˜b×'Ñ'Ó)×0Ñ0°Ó5€JØ×(Ñ(¨Ó/€JÜ+¨U¯[¨[°b×,?Ñ,?Ó,AÓB€JßŸZÙåDÙ% gÓ.€Eð	Ø�\‰\ 'Ö[`°OÀwÈuÈgÐEVÑ3WÐfhˆ\×iÔiÐmsØ—;‘; * ¨YÐ7¸vÀzÐ>R�;ÓSˆDØ×Ñ 3Ô&Ø÷ jÑið —9‘9“;—?‘? >Ó2ˆDÜ˜$¤×%Ò%Ø! TÑ)÷ jÒið
 &÷ jñ ÷ jÖiñ ûô ô ÚðúsB   Â)E Â,+D0ÃE Ã!9D0Ä
E Ä&E Ä0E	Ä;E ÅE ÅEÅEi  c               ó    € V ^8„  d   QhRRRR/# )r
   rÊ   r   r   r   )r   s   "r   r   r   k  s   € ÷ ñ ¨ð °ñ r   c                óh   € R F+  pV P                  V4      '       g   K  V R\        V4      )  u # 	  V # )z�Strip the ``:cloud`` / ``-cloud`` suffix models.dev appends to Ollama Cloud IDs (the live
API uses bare ids), so the dedup merge does not produce duplicates.N)z:cloudz-cloud)r   r   )rÊ   r   s   & r   rz  rz  k  s9   € ó 'ˆØ×Ñ˜V×$Ô$Ø˜Nœs 6›{˜lÐ+Ò+ñ 'ð €Or   c               ó   € V ^8„  d   QhRR/# )r
   r   r   r   )r   s   "r   r   r   t  s   € ÷ @ñ @ $ñ @r   c                 ó*   € ^ RI Hp  V ! 4       R,          # )rJ  ©Úget_hermes_homezollama_cloud_models_cache.json)Úhermes_constantsr†  r…  s    r   Ú_ollama_cloud_cache_pathrˆ  t  s   € Ý0ÙÓÐ?Õ?Ð?r   Ú
ignore_ttlc               ó    € V ^8„  d   QhRRRR/# )r
   r‰  r�   r   r-  r   )r   s   "r   r   r   y  s   € ÷ ñ ¨Dð ¸^ñ r   c                óD  € ^ RI Hp  V! \        4       4      pVe   VP                  R4      MRp\	        V\
        4      '       d	   V'       g   R# V '       g8   \        P                  ! 4       VP                  R^ 4      ,
          \        8”  d   R# V#   \         d     R# i ; i)zOLoad cached Ollama Cloud models from disk (None when missing, empty, or stale).)Ú_read_json_cacheNrÃ   Ú	cached_at)	r6   rŒ  rˆ  r7   rÆ   r    rÖ   Ú_OLLAMA_CLOUD_CACHE_TTLr$  )r‰  rŒ  r^  rÃ   s   $   r   Ú_load_ollama_cloud_cacher�  y  sz   € å2ð	ÙÔ 8Ó :Ó;ˆØ'+Ò'7�—‘˜(Ô#¸TˆÜ˜6¤4×(Ò(¯VÙßœtŸyšy›{¨T¯X©X°kÀ1Ó-EÕEÔI`Ô`ÙØˆøÜô Úðús$   ˆAB ÁB Á5B ÂB ÂBÂBc               ó    € V ^8„  d   QhRRRR/# )r
   rÃ   r  r   rs   r   )r   s   "r   r   r   ‰  s   € ÷ ñ  Yð °4ñ r   c                óŒ   € ^ RI Hp  V! \        4       RV R\        P                  ! 4       /RR7       R#   \         d     R# i ; i)z@Persist the merged Ollama Cloud model list to disk. Best-effort.)Ú_write_json_cacherÃ   r�  N)Úindent)r6   r’  rˆ  rÖ   r$  )rÃ   r’  s   & r   Ú_save_ollama_cloud_cacher”  ‰  s@   € å3ðÙÔ2Ó4°xÀÈÔVZ×V_ÒV_ÓVaÐ6bÐko×pøÜô Úðús   ˆ*4 ´AÁAr  Ú
cache_onlyc          
     ó,   € V ^8„  d   QhRRRRRRRRRR/# )	r
   rf   r   r   r  r�   r•  r   r  r   )r   s   "r   r   r   “  s:   € ÷ )<ñ )<Øð)<àð)<ð ð	)<ð
 ð)<ð ñ)<r   c               óJ  € ^ RI Hp V'       g   \        4       pVe
   VR,          # T ;'       g    \        P                  ! RR4      p T;'       g"    \        P                  ! RR4      ;'       g    RpV'       d   . MV '       d   V! WRR7      ;'       g    . M. p. p ^ R	IHp V! R
4      p. p	. VOR V 4       O F&  p
V
'       g   K  W©9  g   K  V	P                  V
4       K(  	  V'       d   \        V	4       V	# \        RR7      pVe
   VR,          # T	#   \         d     Lvi ; i)u8  Ollama Cloud models: fresh disk cache (< 1h, unless force_refresh) â†’ live ``/v1/models``
(freshest) merged with models.dev additions (deduped, live first) â†’ stale cache â†’ models.dev
only â†’ ``[]``. ``cache_only`` (GUI read path) never runs the 8s network probe and never writes
the disk cache. Never None.)r  rÃ   ÚOLLAMA_API_KEYr   ÚOLLAMA_BASE_URLzhttps://ollama.com/v1g       @rÕ   )Úlist_agentic_modelsúollama-cloudc              3  ó8   "  € T F  p\        V4      x € K  	  R # 5irh   )rz  )ri   Úms   & r   rk   Ú,fetch_ollama_cloud_models.<locals>.<genexpr>±  s   é € ÐQÁ[ÀÔ8¸×;Ð;Ã[ùs   ‚T)r‰  )
r6   r  r�  rZ   r[   Úagent.models_devrš  r$  rÇ   r”  )rf   r   r  r•  r  ræ   Úlive_modelsÚmdev_modelsrš  Úmergedr�  Ústales   &&$$        r   Úfetch_ollama_cloud_modelsr¤  “  s  € õ 3ßÜ)Ó+ˆØÒØ˜(Õ#Ð#à×8Ð8œŸšÐ#3°RÓ8€GØ×VÐVœ2Ÿ9š9Ð%6¸Ó;×VÐVÐ?V€H÷ #‘"×elÑ*:¸7ÐVYÔ*Z×*`Ð*`Ð^`øÐrt€KØ€KðÝ8Ù)¨.Ó9ˆð €FØRˆ{ÐRÑQÁ[ÓQÓRˆß‰1�–Ø�M‰M˜!Öñ S÷ ô 	! Ô(Øˆä$°Ô5€EØ#Ò/ˆ5��?Ð;°VÐ;øô ô Ùðús   ÂD ÄD"Ä!D")Ng       @N>   ÚnousÚgeminiÚopenaiÚ	anthropicÚ
openrouterr›  úopenai-codex>   r   ÚvllmÚlocalrS   Úllamacppú	llama-cppú	llama.cpprh   )NNç      @)g      ^@)Nr°  )NN)LÚ__conditional_annotations__rE  Ú
__future__r   r¹   Úhttp.clientrÞ   r¶   ÚloggingrZ   rÖ   Úurllib.errorrB   Úurllib.parseÚurllib.requestÚpathlibr   Útypingr   r   r   Úagent.secret_scoper   Úhermes_cli.urllib_securityr   Ú	getLoggerr"  rA   r   r'   r-   r9   rN   r`   ro   ry   r‡   r“   r•   rF  r–   r—   r˜   r™   r›   r¢   r¨   r¾   rË   rë   rî   rŽ   Ú	frozensetrý   rþ   rV   r  r  r  r'  r+  r1  r7  r:  r<  rK  rQ  rk  rt  r€  rŽ  rz  rˆ  r�  r”  r¤  )r±  s   @r   Ú<module>r¾     sÊ  øðôõ #ã Û Û Û Û 	Û Û Û Û Ý ß ,Ñ ,Ý -Ý 1ð 
×	Ò	Ð.Ó	/€àÐ õõõMõVõõ4Uõ4
Bõõð"ÐTX÷ ð( '*Ð  Ó )ØGIÐ ÐDÓ IØ68Ð !Ð#3Ó 8Ø13Ð ˜Ó 3Ø')Ð  Ó )Ø'*Ð  Ó *õEõõWõ÷"%÷PIõñ" $Ò${Ó|Ð Ù!Ò"gÓhÐ ÷1Uõhaõ.e÷i÷"õJõ÷÷,\ô˜ô õõ
ñFpð  %÷Fpð Fp÷R÷&ð@ Ð õõ@ð
°5÷ õ ñ)<ð  ð	)<ð
 ÷)<ò )<r   