+
    „WÝjcÜ  ã                   ó2  a € R‡ t~0 t 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HtHtHtHt ^ RIHtHt ^ RIHtHtHtHtHt ^ RIHtHtHtHt ^ RI	HtH t  ^ RI!H"t"H#t#H$t$H%t%H&t&H't'H(t(H)t)H*t*H+t+ ^ R	I,H-t-H.t. ^ R
I/H0t0H1t1H2t2H3t3H4t4 ^ RI5H6t6H7t7H8t8H9t9H:t: ]Pv                  ! R4      t<]
! 4       t=]
! 4       t>]! RR4      t?]! RR4      t@]! RR4      tA]! R4      tB]! RR4      tC]! RR4      tD]! RR4      tE]! RR4      tF]! RR4      tG]! R4      tH. tI] ^ k ^tJ^tK. RˆOtL]Pš                  R R l4       tN]=PŸ                  R4      R‰R R ll4       tP]=PŸ                  R4      R  4       tQ]=PŸ                  R!4      RŠR" R# ll4       tR]=PŸ                  R$4      RŠR% R& ll4       tS]>P©                  R4      R‹R' R( ll4       tUR) R* ltVR+R,R- 3R.R/ 33R0R1R2 33/tWR3 R4 ltX]>PŸ                  R54      RŠR6 R7 ll4       tYRŠR8 R9 lltZ]>P©                  R54      RŠR: R; ll4       t[RŒR< R= llt\R>R�R?RŽR@R�RAR�/t]] ^k R‘RB RC llt^RD RE lt_RF RG lt`RH RI ltaRJ RK ltbRL RM ltc0 R’mtdRQ RR lteRS RT ltfRU RV ltgRW RX lthRY RZ ltiRŠR[ R\ lltjR] R^ ltk]>PŸ                  R_4      RŠR` Ra ll4       tl]>PÛ                  R_4      RŠRb Rc ll4       tnRd Re lto]>PÛ                  Rf4      RŠRg Rh ll4       tp]>Pã                  Ri4      RŠRj Rk ll4       tr]>PÛ                  Rl4      Rm Rn l4       tsRo Rp lttRq Rr ltuRNRsRORtRPRu/tvRNRvRORwRPRx/twRy Rz ltxR{ R| ltyR} R~ ltz]>PÛ                  R4      R€ R� l4       t{]>Pã                  R54      RŠR‚ Rƒ ll4       t|]>PÛ                  R„4      RŠR… R† ll4       t}R# )“zÍConfig, env var and provider custom-endpoint dashboard routes.

Extracted from ``hermes_cli.web_server``; helpers/state that tests monkeypatch on
``web_server`` stay there and are late-bound (cycle-safe).
N)Ú	APIRouter)Ú REDACTED_CREDENTIAL_WRITE_DETAILÚhttp_failureÚis_redacted_credential_previewÚredacted_credential_previewÚscoped_to_thread)Ú	LateStateÚlate)Ú_apply_main_model_assignmentÚ_denormalize_config_from_webÚ_normalize_config_for_webÚ%_schema_with_dynamic_provider_optionsÚ_validated_main_model_selection)Ú_approval_mode_ofÚ_broadcast_gateway_session_infoÚ_is_other_profileÚ_parse_model_entries)ÚHTTPExceptionÚRequest)
ÚDEFAULT_CONFIGÚOPTIONAL_ENV_VARSÚread_raw_configÚ$require_readable_config_before_writeÚcustom_endpoint_key_envÚcoerce_provider_idÚfind_provider_entryÚget_compatible_custom_providersÚ_ENV_REF_REÚ_deep_merge)Ú_canonical_api_modeÚ)_custom_provider_entry_to_provider_config)ÚConfigUpdateÚEnvVarUpdateÚEnvVarDeleteÚEnvVarRevealÚCustomEndpointUpdate)ÚAnyÚDictÚListÚOptionalÚTuplezhermes_cli.web_serverÚ_channel_managed_env_keyszhermes_cli.web_server_messagingÚ_config_profile_scopezhermes_cli.web_server_profilesÚ_profile_scopeÚ_require_tokenÚload_configzhermes_cli.configÚload_envÚremove_env_valueÚsave_configÚsave_env_valueÚ_CONFIG_MUTATION_LOCKc                ó$   € V ^8„  d   QhR\         /# )é   Úlog_msg©Ústr)Úformats   "ÚUC:\Users\johnn\AppData\Local\hermes\hermes-agent\hermes_cli\web_routers\config_env.pyÚ__annotate__r<   >   s   € ÷ Mñ Mœsñ Mó    c              #  óÚ   "  €  Rx € R#   \          d    h \         d   p\        R\        T4      R7      ThRp?i\         d$    \        P                  T 4       \        RRR7      hi ; i5i)u¨  ``ValueError`` -> 400 with its message (save/remove_env_value reject
invalid names and denylisted keys â€” LD_PRELOAD, PATH, PYTHONPATH, â€¦, the
credential lifecycle rejects keys a managed install or administrator pins,
and the SPA needs the reason, not an opaque 500); ``HTTPException`` (the
profile scope's 404 for an unknown ``?profile=``) passes through; anything
else is logged and becomes 500 "Internal server error".Né�  ©Ústatus_codeÚdetailéô  úInternal server error)r   Ú
ValueErrorr9   Ú	ExceptionÚ_logÚ	exception)r7   Úexcs   & r;   Ú_env_write_errorsrJ   =   s`   é € ðMÝøÜô ØÜô GÜ¨´C¸³HÔ=À3ÐFûÜô MÜ�‰�wÔÜ¨Ð4KÔLÐLðMüs-   ‚A+„
 ˆA+ŠA(ŸA( 7·A(Á$A(Á(A+z/api/configc                óF   € V ^8„  d   QhR\         \        ,          R\        /# )r6   ÚprofileÚinclude_defaults)r)   r9   Úbool)r:   s   "r;   r<   r<   Q   s"   € ÷ 
Fñ 
Fœh¤s�mð 
FÄdñ 
Fr=   c              ƒ   óÆ   a"  € \        V V3R  l4      G Rj  x€L
 pVP                  4        UUu/ uF   w  r4VP                  R4      '       d   K  W4bK"  	  upp#  LAu uppi 5i)c                  óV   <€ \        S '       d   \        4       4      # \        4       4      # ©N)r   r/   r   )rM   s   €r;   Ú<lambda>Úget_config.<locals>.<lambda>X   s   ø€ Ô2×DT´;³=ÔlÔZiÓZkÔlr=   NÚ_)r   ÚitemsÚ
startswith)rL   rM   ÚconfigÚkÚvs   &f   r;   Ú
get_configrZ   P   sV   øé € ô $ØÔló÷ €Fð $Ÿ\™\œ^ÔE™^‘T�Q°1·<±<À×3DŒDˆAŠD™^ÒEÐEñ	ùó Fùs&   ƒA!—A˜A!¯AÁAÁA!ÁA!z/api/config/defaultsc               ƒ   ó   "  € \         # 5irQ   )r   © r=   r;   Úget_defaultsr]   ^   s   é € äÐùs   ‚	z/api/config/schemac                ó:   € V ^8„  d   QhR\         \        ,          /# ©r6   rL   ©r)   r9   )r:   s   "r;   r<   r<   d   s   € ÷ Añ Aœh¤s�mñ Ar=   c              ƒ   ó�   "  € \        V 4      ;_uu_ 4        \        4       pR R R 4       RXR\        /#   + '       g   i     L; i5i)NÚfieldsÚcategory_order)r,   r   Ú_CATEGORY_ORDER)rL   rb   s   & r;   Ú
get_schemare   c   s7   é € ô
 
˜w×	'Õ	'Ü6Ó8ˆ÷ 
(à�fÐ.´Ð@Ð@÷ 
(×	'üs   ‚A–3¡A³A	¾Az/api/egress/statusc                ó:   € V ^8„  d   QhR\         \        ,          /# r_   r`   )r:   s   "r;   r<   r<   n   s   € ÷ .ñ .¤X¬c¥]ñ .r=   c              ƒ  óŒ   "  € ^ RI Hp \        V 4      ;_uu_ 4        RV! 4       /uuRRR4       #   + '       g   i     R# ; i5i)zDDashboard/Desktop-readable egress proxy status and remediation text.)Úformat_status_textÚtextN)Úhermes_cli.proxy_clirh   r,   )rL   rh   s   & r;   Úget_egress_statusrk   m   s/   é € õ 8Ü	˜w×	'Õ	'ØÑ*Ó,Ð-÷ 
(×	'×	'Ó	'üs   ‚Aœ	0¥A°A	»	Ac                óR   € V ^8„  d   QhR\         R\        \        ,          R\        /# )r6   ÚbodyrL   Úpreserve_language)r!   r)   r9   rN   )r:   s   "r;   r<   r<   v   s(   € ÷ &-ñ &-Ü
ð&-Ü!)¬#¥ð&-ÜJNñ&-r=   c              ƒ   óÊ   a aa"  € V VV3R  lp\        RRRR7      ;_uu_ 4        \        P                  ! V4      G Rj  x€L
 uuRRR4       #  L  + '       g   i     R# ; i5i)c            	      ó
  <€ R p \        SP                  ;'       g    S4      ;_uu_ 4        \        ;_uu_ 4        \        4       p\	        SP
                  4      p\        W4      p\        V4      \        V4      8g  p \        TS'       d   R0MRR7       RRR4       RRR4       V '       d0   \        SP                  ;'       g    S4      '       g   \        4        RR/#   + '       g   i     LS; i  + '       g   i     L^; i)FN)Úpreserve_keysÚokT)ÚdisplayÚlanguage)r-   rL   r4   r   r   rW   r   r   r2   r   r   )Úapprovals_mode_changedÚexistingÚincomingÚmergedrm   rn   rL   s       €€€r;   Ú_runÚupdate_config.<locals>._runy   sÅ   ø€ Ø!&ÐÜ˜DŸL™L×3Ð3¨G×4Õ4÷
 'Ö&ô @ÓA�Ü7¸¿¹ÓD�Ü$ XÓ8�ô *;¸6Ó)BÔFWÐX`ÓFaÑ)aÐ&ô Ø×GXÐ+BÑ*CÐ^bõ÷! '÷ 5÷8 "Ô*;¸D¿L¹L×<SÐ<SÈG×*TÒ*TÜ+Ô-Ø�dˆ|Ð÷3 '×&ú÷ 5×4ús#   «C2ºAC	ÂC2ÃC/Ã*C2Ã2D	zPUT /api/config failedrC   rD   ©rB   N)r   ÚasyncioÚ	to_thread)rm   rL   rn   ry   s   fff r;   Úupdate_configr~   u   sH   úé € ÷ ôD 
Ð.°Ð<S×	TÖ	TÜ×&Ò& tÓ,×,÷ 
UÒ	TÙ,÷ 
U×	TÐ	Tüs,   …A#¤A¾A¿AÁA#ÁAÁA 	Á	A#c                óH   € V ^8„  d   QhR\         R\        R\        R\        /# )r6   ÚdescriptionÚis_passwordÚadvancedÚreturn)r9   rN   Údict)r:   s   "r;   r<   r<   Ÿ   s)   € ÷ ñ ¤3ð ¼Tð ÌTð ÔVZñ r=   c                óJ   € R V P                   RV P                  RVRVRVRVRR /# )ÚproviderÚprovider_labelr€   Úurlr�   r‚   Úcategory)ÚslugÚlabel)Údr€   rˆ   r�   r‚   s   &&&$$r;   Ú_provider_cardr�   Ÿ   s5   € à�A—F‘FÐ,¨a¯g©g°}ÀkÐSXÐZ]Ø�{ J°¸*Àjðð r=   Úaws_sdkÚ
AWS_REGIONc                 ó&   € V P                    R V R2# ©z (Ú)©r‹   ©rŒ   Úvars   &&r;   rR   rR   ¨   s   € ¨¯©¨	°°C°5¸Ñ&:r=   ÚAWS_PROFILEc                 ó&   € V P                    R V R2# r‘   r“   r”   s   &&r;   rR   rR   ©   s   € ¨!¯'©'¨°"°S°E¸Ñ';r=   ÚvertexÚVERTEX_CREDENTIALS_PATHc                 ó    € V P                    R 2# )u+    â€” service account JSON path (or use ADC)r“   r”   s   &&r;   rR   rR   «   s   € ¸Q¿W¹W¸IÐEpÑ:qr=   c                ó$   € V ^8„  d   QhR\         /# )r6   rƒ   ©r„   )r:   s   "r;   r<   r<   ¯   s   € ÷ Qñ Q¬ñ Qr=   c                 óü  aa€  ^ RI Hp  \        P                  ! 4        UUu0 uFL  w  rT;'       g    / P                  R4      '       g   K(  T;'       g    / P                  R4      R8w  g   KJ  TkKN  	  ppp/ oR R loR TT3R llpT ! 4        EFN  pTP                  R8w  d   K  \        TP                  4       FK  w  rgYs9   d   K  \        YUP                  TP                  ;'       g    R	R
RR7      pT^ 8H  TR&   T! TT4       KM  	  TP                  '       d7   SP                  TP                  \        YUP                   R2R	RR
R7      4       \        P                  TP                   R4       Fg  w  ršSP                  T	/ 4      p\        Y[P                  R4      ;'       g	    T
! YY4      TP                  R4      RTP                  RR
4      R7      ST	&   Ki  	  EKQ  	  S#   \         d    / u # i ; iu uppi )a8  Map provider env vars -> desktop card metadata, derived from the catalog.

Returns ``{env_var: {provider, provider_label, description, url, is_password,
advanced}}`` for every API-key provider in the unified ``provider_catalog()``
(the ``hermes model`` universe). When multiple providers intentionally share
one env var, ``provider_profiles`` preserves every provider identity while
the legacy singular fields keep describing the first provider. Hand
``OPTIONAL_ENV_VARS`` prose is layered on top in the endpoint; this only
supplies membership + grouping + fallbacks.
)Úprovider_catalogr‰   r†   c                ó0   € V ^8„  d   QhR\         R\         /# ©r6   Úentryrƒ   rœ   )r:   s   "r;   r<   Ú4_catalog_provider_env_metadata.<locals>.__annotate__É   s   € ÷ 
ñ 
œð 
¤ñ 
r=   c                ó‚   € RV R,          RV R,          RV R,          RV R,          R\        V P                  R4      4      /# )z=Return the provider-specific part of a shared credential row.r†   r‡   r€   rˆ   ÚprimaryÚprovider_primary)rN   Úget)r¡   s   &r;   Ú_profileÚ0_catalog_provider_env_metadata.<locals>._profileÉ   sJ   € ð ˜˜jÕ)Ø˜eÐ$4Õ5Ø˜5 Õ/Ø�5˜•<Ø”t˜EŸI™IÐ&8Ó9Ó:ð
ð 	
r=   c                ó4   € V ^8„  d   QhR\         R\        RR/# )r6   Úenv_varr¡   rƒ   N©r9   r„   )r:   s   "r;   r<   r¢   Ó   s!   € ÷ 
-ñ 
-¤3ð 
-¬tð 
-¸ñ 
-r=   c                ót  <a€ SP                  V 4      pVf   SSV &   R# VP                  R4      SP                  R4      8X  d   R# VP                  RS! V4      .4      p\        ;QJ d    V3R lV 4       F  '       g   K   RM	  RM! V3R lV 4       4      '       g   VP                  S! S4      4       R# R# )zAAdd one provider without discarding peers that share ``env_var``.Nr†   Úprovider_profilesc              3   óh   <"  € T F'  qP                  R 4      SP                  R 4      8H  x € K)  	  R# 5i)r†   N)r¦   )Ú.0rL   r¡   s   & €r;   Ú	<genexpr>ÚL_catalog_provider_env_metadata.<locals>._add_provider_env.<locals>.<genexpr>Ü   s(   øé € Ð\ÑS[È—;‘;˜zÓ*¨e¯i©i¸
Ó.CÖCÓS[ùs   ƒ/2TF)r¦   Ú
setdefaultÚanyÚappend)rª   r¡   rv   Úprofilesr§   Úmetas   &f  €€r;   Ú_add_provider_envÚ9_catalog_provider_env_metadata.<locals>._add_provider_envÓ   s”   ù€ à—8‘8˜GÓ$ˆØÒØ!ˆD�‰MÙØ�<‰<˜
Ó# u§y¡y°Ó'<Ô<ÙØ×&Ñ&Ð':¹XÀhÓ=OÐ<PÓQˆß‹sÔ\ÑS[Ó\�s�sŠsÔ\ÑS[Ó\×\Ò\Ø�O‰O™H U›OÖ,ñ ]r=   ÚkeysNTF)r�   r‚   r¥   z base URL overrider€   rˆ   r‚   r\   )Úhermes_cli.provider_catalogrž   rF   r   rU   r¦   ÚtabÚ	enumerateÚapi_key_env_varsr�   r€   Ú
signup_urlÚbase_url_env_varr²   r‹   Ú_AUTH_TYPE_ENV_VARSÚ	auth_type)rž   rX   rY   Ú_non_provider_keysr·   rŒ   Úindexrª   r¡   r•   Údescriberv   r§   r¶   s               @@r;   Ú_catalog_provider_env_metadatarÅ   ¯   sÕ  ù€ ðÝ@ô (×-Ò-Ô/ôÙ/‰dˆaØ�GˆG��=‰=˜×$ô 	
Ø*+¯'¨'¨r¯©°zÓ)BÀjÑ)P÷ 	
ˆÑ/ð ñ ð
 €Dõ
÷
-ñ 
-ñ ×ˆØ�5‰5�FŒ?Ùô (¨×(:Ñ(:Ö;‰NˆEØÔ,ÙÜ"Ø—=‘= !§,¡,×"6Ð"6°$ÀDÐSXôˆEð ).°©
ˆEÐ$Ñ%ÙØØöñ <ð ××ÐØ�O‰OØ×"Ñ"Ü˜q§W¡W IÐ-?Ð"@À$ÐTYÐdhÔiôô 1×4Ñ4°Q·[±[À"ÖE‰MˆCØ—x‘x  RÓ(ˆHÜ&Ø—<‘< Ó.×BÐB±(¸1Ó2BÀHÇLÁLÐQVÓDWØ!¨H¯L©L¸ÀTÓ,JôˆD�‹Iô Fñ7  ðB €KøôI ô ØŠ	ðüós-   „G% ¢G8²G8ÁG8ÁG8Á.G8Ç%G5Ç4G5z/api/envc                ó:   € V ^8„  d   QhR\         \        ,          /# r_   r`   )r:   s   "r;   r<   r<     s   € ÷ @ñ @¤¬¥ñ @r=   c              ƒ   óT   "  € \         P                  ! \        V 4      G R j  x€L
 #  L5irQ   )r|   r}   Ú_get_env_vars_sync©rL   s   &r;   Úget_env_varsrÊ     s!   é € ô ×"Ò"Ô#5°wÓ?×?Ð?Ñ?ùs   ‚(¡&¢(c                ó:   € V ^8„  d   QhR\         \        ,          /# r_   r`   )r:   s   "r;   r<   r<   
  s   € ÷ ;ñ ;¤¬¥ñ ;r=   c                 ó²  aaa€ \        V 4      ;_uu_ 4        \        4       oR R R 4       \        4       o\        4       oRR/R VVV3R lllp/ p\        P
                  ! 4        F  w  r4V! W44      W#&   K  	  S F  pW29  g   K  V! V/ 4      W#&   K  	  S F+  pW29   g   VS9   d   K  V! V/ RR7      pRVR&   RVR&   WRV&   K-  	  V#   + '       g   i     L¬; i)	NÚcustomFc                óH   € V ^8„  d   QhR\         R\        R\        R\        /# )r6   Úvar_nameÚinforÍ   rƒ   )r9   r„   rN   )r:   s   "r;   r<   Ú(_get_env_vars_sync.<locals>.__annotate__  s(   € ÷ !
ñ !
”sð !
¤$ð !
´4ð !
ÄDñ !
r=   c                óþ  <€ SP                  V 4      pSP                  V 4      ;'       g    / pR \        V4      R\        V4      RVP                  R4      ;'       g    VP                  RR4      RVP                  R4      e   VP                  R4      MVP                  R4      RVP                  R4      ;'       g    VP                  RR4      RVP                  RVP                  RR4      4      R	VP                  R	. 4      R
VP                  R
VP                  R
R4      4      RV S9   RVP                  RR4      RVP                  RR4      RVP                  R. 4      R\        VP                  RR4      4      RV/# )Úis_setÚredacted_valuer€   Ú rˆ   r‰   r�   ÚpasswordFÚtoolsr‚   Úchannel_managedr†   r‡   r­   r¥   rÍ   )r¦   rN   r   )rÏ   rÐ   rÍ   ÚvalueÚcat_metaÚcatalog_metaÚchannel_keysÚenv_on_disks   &&$  €€€r;   Ú_rowÚ _get_env_vars_sync.<locals>._row  sY  ø€ Ø—‘ Ó)ˆØ×#Ñ# HÓ-×3Ð3°ˆð ”d˜5“kØÔ9¸%Ó@Ø˜4Ÿ8™8 MÓ2×UÐU°h·l±lÀ=ÐRTÓ6UØ d§h¡h¨u£oÒ&A�4—8‘8˜E”?ÀxÇ|Á|ÐTYÓGZØ˜Ÿ™ Ó,×LÐL°·±¸ZÈÓ0LØ˜4Ÿ8™8 J°·±¸]ÈEÓ0RÓSØ�T—X‘X˜g rÓ*Ø˜Ÿ™ ¨X¯\©\¸*ÀeÓ-LÓMð ˜x¨<Ñ7ð ˜Ÿ™ Z°Ó4Ø˜hŸl™lÐ+;¸RÓ@ð   §¡Ð.AÀ2Ó!Fð
 ¤ X§\¡\Ð2DÀeÓ%LÓ Mð �fð7
ð 	
r=   T©rÍ   r‰   r�   )r-   r0   r+   rÅ   r   rU   )	rL   rÞ   ÚresultrÏ   rÐ   ÚrowrÛ   rÜ   rÝ   s	   &     @@@r;   rÈ   rÈ   
  sÜ   ú€ Ü	˜×	 Õ	 Ü“jˆ÷ 
!ä,Ó.€LÜ1Ó3€Lð!
¸%÷ !
ô !
ðF €FÜ+×1Ò1Ö3‰ˆÙ Ó/ˆÓñ 4ó !ˆØÖ!Ù# H¨bÓ1ˆFÓñ !ó  ˆØÔ ¨\Ô!9ÙÙ�8˜R¨Ô-ˆØ"ˆˆJ‰Ø!ˆˆMÑØˆxÓñ  ð €M÷u 
!×	 ús   —CÃC	c                óF   € V ^8„  d   QhR\         R\        \        ,          /# ©r6   rm   rL   )r"   r)   r9   )r:   s   "r;   r<   r<   I  s"   € ÷ 	Hñ 	HœLð 	H´8¼Cµ=ñ 	Hr=   c              ƒ   ó$  a "  € \        S P                  4      '       d   \        R \        R7      h\	        R4      ;_uu_ 4        \        S P                  ;'       g    TV 3R l4      G Rj  x€L
 uuRRR4       #  L  + '       g   i     R# ; i5i)r?   r@   zPUT /api/env failedc                  óZ   <€ \        S P                  S P                  S P                  4      # rQ   )Ú_save_env_credentialÚkeyrÙ   Úprovider_setup)rm   s   €r;   rR   Úset_env_var.<locals>.<lambda>R  s0   ø€ ÔG[Ð\`×\dÑ\dÐfj×fpÑfpÐrv÷  sFñ  sFô  HGr=   N)r   rÙ   r   r   rJ   r   rL   )rm   rL   s   f&r;   Úset_env_varrë   H  sn   øé € ô & d§j¡j×1Ò1Ü¨Ô4TÔUÐUÜ	Ð0×	1Õ	1Ü% d§l¡l×&=Ð&=°gô  @Gó  H÷  H÷ 
2Ò	1ñ H÷ 
2×	1Ð	1üs0   ƒA BÁ(A<Á+A:Á,A<Á/BÁ:A<Á<B	Â	Bc                óH   € V ^8„  d   QhR\         R\         R\        R\        /# )r6   rè   rÙ   ré   rƒ   )r9   rN   r&   )r:   s   "r;   r<   r<   U  s)   € ÷ 	ñ 	œcð 	¬#ð 	¼tð 	ÔPSñ 	r=   c                óŠ   € ^ RI Hp ^ RIHp ^ RIHpHp V! 4       P                  V 4      pV! W4      pV! WWv! 4       VR7       V# )z_Save under the request's profile scope; a new provider API key also counts as a provider setup.)r0   )Úsave_provider_env_credential)Úrecord_api_key_savedÚweb_setup_surface)Ú
connecting)Úhermes_cli.configr0   Úhermes_cli.credential_lifecyclerî   Ú-hermes_cli.observability.shared_metrics_setuprï   rð   r¦   )	rè   rÙ   ré   r0   rî   rï   rð   Úpreviousrá   s	   &&&      r;   rç   rç   U  s<   € å*ÝLßeá‹z�~‰~˜cÓ"€HÙ)¨#Ó5€FÙ˜ XÐ/@Ó/BÈ~Õ^Ø€Mr=   ÚOPENROUTER_API_KEYÚOPENAI_API_KEYÚXAI_API_KEYÚGEMINI_API_KEYc                ó<   € V ^8„  d   QhR\         R\         R\         /# )r6   ÚrawÚfallbackrƒ   r8   )r:   s   "r;   r<   r<   n  s!   € ÷ ñ œSð ¬Cð ¼sñ r=   c                 ó–   € \         P                  ! R R\        V 4      4      P                  R4      P	                  4       pT;'       g    T# )z[^A-Za-z0-9_-]+Ú-z-_)ÚreÚsubr   ÚstripÚlower)rû   rü   rŠ   s   && r;   Ú_custom_endpoint_idr  n  s=   € Ü�6Š6Ð$ cÔ+=¸cÓ+BÓC×IÑIÈ$ÓO×UÑUÓW€DØ×Ð�8Ðr=   c                ó–   € V ^8„  d   QhR\         R\        R\        \         \        \        \        \         3,          ,          3,          /# )r6   Ú	providersÚendpoint_idrƒ   )r&   r9   Útupler)   r„   )r:   s   "r;   r<   r<   s  s>   € ÷ :ñ :¬cð :Äð :ÌÌcÔS[Ô\`ÔadÔfiÐaiÕ\jÕSkÐNkÕHlñ :r=   c                óf   € \        W4      w  r#Ve   W#3# \        V4      pWA8X  d   R# \        W4      # )u–  Resolve a custom endpoint id using the stored key first, then its legacy slug.

The list route hands Desktop the literal ``providers.<key>`` (a v11â†’v12
migration keeps dots/colons from the display name: ``local-127.0.0.1:8283``;
hand-written keys keep their case), so that spelling must round-trip
unchanged. Slugging is only the compatibility path for callers that still
send an unslugged display name.
)NN)r   r  )r  r  Ú
stored_keyr¡   Únormalized_keys   &&   r;   Ú_resolve_custom_endpoint_entryr  s  sA   € ô ,¨IÓCÑ€JØÒØÐ Ð Ü(¨Ó5€NØÔ$ØÐÜ˜yÓ9Ð9r=   c                óh   € V ^8„  d   QhR\         \        \        3,          R\        \        ,          /# r    )r„   r9   r&   Úlist)r:   s   "r;   r<   r<   …  s*   € ÷ [ñ [¬d´3¼°8­nð [ÄÄcÅñ [r=   c                 óð  € . pV P                  R 4      p\        V\        \        34      '       d   VP	                  R V 4       4       \        V P                  R4      ;'       g    V P                  R4      ;'       g    R4      P                  4       pV'       d   VP                  ^ V4       \        4       pV Uu. uF/  qU'       g   K  WT9   d   K  VP                  V4      '       d   K-  VNK1  	  up# u upi )Úmodelsc              3   óT   "  € T F  p\        V4      P                  4       x € K   	  R # 5irQ   )r9   r  )r¯   Úmodels   & r;   r°   Ú5_models_from_custom_endpoint_entry.<locals>.<genexpr>‰  s    é € ÐA±j¨U”c˜%“j×&Ñ&×(Ð(³jùs   ‚&(r  Údefault_modelrÕ   )
r¦   Ú
isinstancer„   r  Úextendr9   r  ÚinsertÚsetÚadd)r¡   r  Ú
raw_modelsr  Úseenr  s   &     r;   Ú"_models_from_custom_endpoint_entryr  …  s´   € Ø€FØ—‘˜8Ó$€JÜ�*œt¤T˜l×+Ò+Ø�‰ÑA±jÓAÔAä˜Ÿ	™	 'Ó*×NÐN¨e¯i©i¸Ó.H×NÐNÈBÓO×UÑUÓW€MßØ�‰�a˜Ô'ä“U€DÙ%ÓZ™v�e«ŒE¸¹ŒEÈÏÉÐRWÏ�EˆE™vÑZÐZùÒZs   Â;	C3Ã	C3ÃC3Ã*C3c                óŠ   € V ^8„  d   QhR\         \        \        3,          R\        \        \
        \        ,          3,          /# r    )r„   r9   r&   r  rN   r)   )r:   s   "r;   r<   r<   “  s0   € ÷ ñ œD¤¤c �Nð ¬u´T¼8ÄC½=Ð5HÕ/Iñ r=   c                ó  € \        V P                  R4      ;'       g    R4      P                  4       pV'       d   R\        V4      3# \        V P                  R4      ;'       g    R4      P                  4       pV'       d	   RRV R23# R# )zéReturn ``(has_api_key, preview)`` for a provider or model config block.

Keys live in ``.env`` behind ``key_env``; only older entries still carry a
plaintext ``api_key``. Checking both keeps the panel honest either way.

See #69449.
Úapi_keyrÕ   TÚkey_envú${Ú})FN)r9   r¦   r  r   )r¡   Ú	plaintextr  s   &  r;   Ú_api_key_displayr#  “  s}   € ô �E—I‘I˜iÓ(×.Ð.¨BÓ/×5Ñ5Ó7€IßØÔ0°Ó;Ð;Ð;Ü�%—)‘)˜IÓ&×,Ð,¨"Ó-×3Ñ3Ó5€GßØ�s˜7˜) 2Ð&Ð&Ð&ØÐr=   c                ó0   € V ^8„  d   QhR\         R\        /# ©r6   r  rƒ   )r9   r&   )r:   s   "r;   r<   r<   ¤  s   € ÷ Eñ E¤sð E¬sñ Er=   c                óž   € \        \        4       P                  R4      V 4      w  r\        V\        4      '       d   VP                  R4      # R# )zHThe on-disk (un-expanded) ``api_key`` of a providers entry, or ``None``.r  r  N)r   r   r¦   r  r„   )r  Ú_storedr¡   s   &  r;   Ú_raw_provider_api_keyr(  ¤  s>   € ä(¬Ó):×)>Ñ)>¸{Ó)KÈ[ÓY�N€GÜ#-¨e´T×#:Ò#:ˆ5�9‰9�YÓÐDÀÐDr=   c                ó0   € V ^8„  d   QhR\         R\        /# r%  )r9   rN   )r:   s   "r;   r<   r<   ª  s   € ÷ 	Qñ 	Q¬Cð 	Q´Dñ 	Qr=   c                óˆ   € \        V 4      p\        \        V\        4      ;'       d    \        P
                  ! RV4      4      # )ar  True when this endpoint's on-disk ``api_key`` is a ``${VAR}`` template.

``load_config()`` expands env refs, so a hand-written ``api_key: ${MY_KEY}``
is indistinguishable from a literal secret by the time it reaches us. Such
an entry already keeps its secret out of config.yaml, so migrating it would
only copy that secret into a second env var the user didn't ask for.
z\$\{[^}]+\})r(  rN   r  r9   rÿ   Úsearch)r  Úraw_keys   & r;   Ú_config_api_key_is_env_refr-  ª  s3   € ô $ KÓ0€GÜ”
˜7¤CÓ(×OÐO¬R¯YªY°~ÀwÓ-OÓPÐPr=   Úchat_completionsÚcodex_responsesÚanthropic_messagesc                óR   € V ^8„  d   QhR\         \        \        3,          R\        /# r    ©r„   r9   r&   )r:   s   "r;   r<   r<   ¹  s"   € ÷ 6ñ 6œd¤3¬ 8�nð 6´ñ 6r=   c                óÌ   € \        V P                  R4      ;'       g    V P                  R4      ;'       g    R4      p\        V4      P                  4       pV\        9   d   V# R# )zâThe transport a providers entry pins (``api_mode``, or the v12 migration's ``transport``
spelling), canonicalized; ``""`` = runtime auto-detect. Mirrors the read order of
``runtime_provider_custom._get_named_custom_provider``.Úapi_modeÚ	transportrÕ   )r9   r¦   r   r  Ú_DESKTOP_API_MODES)r¡   rû   Úmodes   &  r;   Ú_endpoint_api_moder8  ¹  sV   € ô ˆe�i‰i˜
Ó#×CÐC u§y¡y°Ó'=×CÐCÀÓ
D€CÜ˜sÓ#×)Ñ)Ó+€DØÔ-Ô-ˆ4Ð5°2Ð5r=   c                óê   € V ^8„  d   QhR\         R\         R\         R\         R\        \         ,          R\        R\        \         \        3,          R\        R	\         R
\        \         \        3,          /
# )r6   r  ÚnameÚbase_urlr  r  Údiscover_modelsÚ	key_entryÚ
is_currentÚsourcerƒ   )r9   r  rN   r„   r&   )r:   s   "r;   r<   r<   Â  sr   € ÷ ñ ÜðÜðÜ+.ðÜ7:ðÜDHÌÅIðäðä&*¬3´¨8¥nðäBFðäPSðô 
Œ#Œsˆ(…^ñr=   c
                 ób   € \        V4      w  r«R V RVRVRVRVR\        V4      RVRVRV
R	VR
VRV	/# )Úidr:  r;  r  r  r4  Úcontext_lengthr<  Úhas_api_keyÚapi_key_previewr>  r?  )r#  r8  )r  r:  r;  r  r  rB  r<  r=  r>  r?  rC  rD  s   &&&&&&&&&&  r;   Ú_endpoint_rowrE  Â  sY   € ô $4°IÓ#>Ñ €Kàˆk˜6 4¨°X¸wÈÈxÐY_ØÔ& yÓ1Ø˜.Ð*;¸_Ø�{Ð$5°Ø�j (¨Fðð r=   c          	      ó¢   € V ^8„  d   QhR\         \        \        3,          R\        R\        \         \        \        3,          ,          R\        /# )r6   Ú	model_cfgÚprovider_keyr¡   rƒ   )r„   r9   r&   r)   rN   )r:   s   "r;   r<   r<   Ð  sC   € ÷ 4ñ 4¤T¬#¬s¨(¥^ð 4Ä3ð 4ÌxÔX\Ô]`ÔbeÐ]eÕXfÕOgð 4Ôlpñ 4r=   c                ó¸  € \        V4      P                  4       0p\        V\        4      '       dX   \        VP	                  R4      4      '       d8   VP                  \        VP	                  R4      4      P                  4       4       \        V P	                  R4      ;'       g    R4      P                  4       P                  4       pVP                  R4      V9   # )a+  True when ``model.provider`` points at this ``providers`` entry.

``switch_model`` spells the active provider either as the stored key or as
``custom:<lowercased name>``; the list's ``is_current`` and delete's mirror
detach must accept both, or a mixed-case key activates but never shows as
active.
r:  r†   rÕ   zcustom:)	r   r  r  r„   r¦   r  r9   r  Úremoveprefix)rG  rH  r¡   ÚnamesÚcurrents   &&&  r;   Ú_model_names_providerrM  Ð  s¢   € ô   Ó-×3Ñ3Ó5Ð6€EÜ�%œ×ÒÔ#5°e·i±iÀÓ6G×#HÒ#HØ�	‰	Ô$ U§Y¡Y¨vÓ%6Ó7×=Ñ=Ó?Ô@Ü�)—-‘- 
Ó+×1Ð1¨rÓ2×8Ñ8Ó:×@Ñ@ÓB€GØ×Ñ 	Ó*¨eÑ3Ð3r=   c                ót   € V ^8„  d   QhR\         \        \        3,          R\         \        \        3,          /# )r6   Úcfgrƒ   r2  )r:   s   "r;   r<   r<   ß  s*   € ÷ ;ñ ;¤4¬¬S¨¥>ð ;´d¼3Ä¸8µnñ ;r=   c                 ó–  € \        V P                  R 4      \        4      '       d   V P                  R / 4      M/ p\        VP                  RR4      ;'       g    R4      p\        VP                  RVP                  RR4      4      ;'       g    R4      p\        VP                  RR4      ;'       g    R4      p. pV P                  R4      p\        V\        4      '       Edz   VP	                  4        EFd  w  rx\        V\        4      '       g   K  \        VP                  R4      ;'       g5    VP                  R4      ;'       g    VP                  R4      ;'       g    R4      P                  4       p	V	'       g   KŒ  \        V4      p
\        V4      pTP                  \        T
\        VP                  R4      ;'       g    T
4      T	\        VP                  R 4      ;'       g-    VP                  R	4      ;'       g    V'       d
   V^ ,          MR4      W¸P                  R
4      \        VP                  RR4      4      V\        WV4      R4
      4       EKg  	  VP                  4       R8H  ;'       d    \        V4      pV Uu0 uF  qÝR,          kK  	  pp\        V 4       EF  pVP                  R4      '       d   K  \        VR,          4      p
W®9   d   K7  VP                  V
4       \        V4      pT;'       d+    VR,          P                  R4      VP                  R4      8H  pTP                  \        Y¯R,          VR,          \        VP                  R 4      ;'       g    V'       d
   V^ ,          MR4      VVP                  R
4      \        VP                  RR4      4      VVR4
      4       EK  	  V'       dx   \         ;QJ d    R V 4       F  '       g   K   RM	  RM! R V 4       4      '       g>   TP#                  ^ \        RRYCV'       d   V.M. VP                  R
4      RVRR4
      4       RVRRVR VRV//# u upi )r  r†   rÕ   Údefaultr:  r;  r  rˆ   Úapir  rB  r<  TrÍ   rA  rH  Ú/Úcustom_providersc              3   óZ   "  € T F!  qR ,          R8H  ;'       g
    VR,          x € K#  	  R# 5i)rA  rÍ   r>  Nr\   )r¯   Úes   & r;   r°   Ú,_custom_endpoint_response.<locals>.<genexpr>  s(   é € Ð!\ÑR[ÈQ D¥'¨XÑ"5×"HÐ"H¸¸<½Ô"HÓR[ùs   ‚+™+FÚCustomzdirect-configÚ	endpointsrL  )r  r¦   r„   r9   rU   r  r  r´   rE  rN   rM  r  r   r  r  Úrstripr³   r  )rO  rG  Úcurrent_providerÚcurrent_modelÚcurrent_base_urlrY  r  Úprovider_idÚ	raw_entryr;  r  r  Úis_bare_customrV  Úseen_idsr¡   r>  s   &                r;   Ú_custom_endpoint_responserb  ß  s‰  € Ü(2°3·7±7¸7Ó3CÄT×(JÒ(J�—‘˜ Ô$ÐPR€IÜ˜9Ÿ=™=¨°RÓ8×>Ð>¸BÓ?ÐÜ˜	Ÿ™ i°·±¸vÀrÓ1JÓK×QÐQÈrÓR€MÜ˜9Ÿ=™=¨°RÓ8×>Ð>¸BÓ?Ðà&(€IØ—‘˜Ó$€IÜ�)œT×"Ó"Ø&/§o¡o×&7Ñ"ˆKÜ˜i¬×.Ò.ÙÜ˜9Ÿ=™=¨Ó4×jÐj¸	¿¹ÀeÓ8L×jÐjÐPY×P]ÑP]Ð^cÓPd×jÐjÐhjÓk×qÑqÓsˆHßÙÜ˜kÓ*ˆKÜ7¸	ÓBˆFØ×Ñœ]ØœS §¡¨vÓ!6×!EÐ!E¸+ÓFÈÜ�I—M‘M 'Ó*×mÐm¨i¯m©m¸OÓ.L×mÐm×^dÐQWÐXYÖQZÐjlÓnØŸ™Ð&6Ó7¼¸i¿m¹mÐL]Ð_cÓ>dÓ9eØÔ0°ÈÓSÐU`ó	÷ ñ '8ð* &×+Ñ+Ó-°Ñ9×TÐT¼dÐCSÓ>T€NÙ!*Ó+¡˜A�$—�¡€HÐ+Ü0°×5ˆØ�9‰9�^×$Ò$ÙÜ)¨%°­-Ó8ˆØÔ"ÙØ�‰�[Ô!Ü3°EÓ:ˆØ#×eÐe¨¨jÕ(9×(@Ñ(@ÀÓ(EÐIY×I`ÑI`ÐadÓIeÑ(eˆ
Ø×ÑœØ˜v�¨¨jÕ(9Ü�—	‘	˜'Ó"×CÐC·F v¨a¦yÀÓDÀfØ�I‰IÐ&Ó'¬¨e¯i©iÐ8IÈ4Ó.PÓ)QØ�:Ð1ó	
÷ 	ñ 6÷  Ÿc›cÑ!\ÑR[Ó!\ŸcŸcšcÑ!\ÑR[Ó!\×\Ò\Ø×Ñ˜œMØ�hÐ 0×TaÀ-ÁÐgiØ�M‰MÐ*Ó+¨T°9¸dÀOó
ô 	ð 	�YØØÐ(¨'°=À*ÐN^ð
ðð ùò/ ,s   ÊQc          	      ó–   € V ^8„  d   QhR\         \        \        3,          R\        R\        \         \        \        3,          ,          /# )r6   rO  rH  rƒ   ©r„   r9   r&   r)   )r:   s   "r;   r<   r<     s;   € ÷ ñ ¤T¬#¬s¨(¥^ð Ä3ð Ì8ÔTXÔY\Ô^aÐYaÕTbÕKcñ r=   c                ó:  € V P                  R4      p\        V\        4      '       g   R# \        V4       Fb  w  r4\        V\        4      '       g   K  \        \        VP                  R4      ;'       g    R4      4      V8X  g   KQ  VP                  V4      u # 	  R# )zaRemove and return the legacy ``custom_providers:`` list entry whose name slugs to *provider_key*.rT  Nr:  rÕ   )r¦   r  r  r¼   r„   r  r9   Úpop)rO  rH  ÚlegacyrÃ   r¡   s   &&   r;   Ú_pop_legacy_custom_providerrh    sx   € à�W‰WÐ'Ó(€FÜ�fœd×#Ò#ÙÜ! &Ö)‰ˆÜ�eœT×"Ô"Ô':¼3¸u¿y¹yÈÓ?P×?VÐ?VÐTVÓ;WÓ'XÐ\hÖ'hØ—:‘:˜eÓ$Ò$ñ *ñ r=   c          	      óš   € V ^8„  d   QhR\         \        \        3,          R\        R\        \         \        \        3,          ,          RR/# )r6   rO  rH  r¡   rƒ   Nrd  )r:   s   "r;   r<   r<   (  sD   € ÷ ñ ¬$¬s´C¨x­.ð Ìð ÔT\Ô]aÔbeÔgjÐbjÕ]kÕTlð Ðx|ñ r=   c                óº   € V P                  R4      p\        V\        4      '       d   \        W1V4      '       g   R# R F  pVP	                  VR4       K  	  W0R&   R# )u/  Drop the main-slot mirror of a provider that no longer exists.

``activate_custom_endpoint`` copies the endpoint's ``base_url`` and
``api_key`` onto ``model``; that mirror outranks the environment at client
construction, so deleting the endpoint without clearing it leaves the agent
authenticating to the deleted host with the deleted key (and the key in
config.yaml). Only touches ``model`` when it names the deleted provider â€”
``switch_model`` spells that either as the stored key or as
``custom:<lowercased name>``, so both spellings count.

See #62269.
r  N)r†   r;  r  r  )r¦   r  r„   rM  rf  )rO  rH  r¡   rG  Úfields   &&&  r;   Ú _detach_main_model_from_providerrl  (  sP   € ð —‘˜Ó €IÜ�i¤×&Ò&Ô.CÀIÐ]b×.cÒ.cÙÛ?ˆØ�‰�e˜TÖ"ñ @àˆƒLr=   c          
      ó¢   € V ^8„  d   QhR\         \        \        3,          R\        R\        \        \         \        \        3,          3,          /# )r6   rO  rm   rƒ   )r„   r9   r&   r%   r  )r:   s   "r;   r<   r<   =  sG   € ÷ Xñ X¤¤S¬# X¥ð XÔ6Jð XÌuÔUXÔZ^Ô_bÔdgÐ_gÕZhÐUhÕOiñ Xr=   c                 ó  € VP                   ;'       g    R P                  4       pVP                  ;'       g    R P                  4       P                  R4      pVP                  ;'       g    R P                  4       pV'       g   \        RRR7      hV'       g   \        RRR7      h \        P                  P                  V4      pTP                  '       d   TP                  '       g   \        RRR7      hT'       g   \        RRR7      hT P                  R	4      p\        T\        4      '       g   / p\        YqP                   ;'       g    TP                   4      w  r‰T	e   \#        T4      M(\%        TP                   ;'       g    TP                   4      p
T	fv   ^ R
IHp \+        Y
4      pTe
   T! YÊR7      MRp\        T\        4      '       d   Tp	M<Te9   T P                  R4      p\        T\,        4      '       d   TP/                  T4       T	f   / p	\        T	4      pTP1                  RTRTRTR\3        TP4                  4      /4       TP6                  eG   TP9                  RR4       TP6                  '       d   TP6                  TR&   MTP9                  RR4       TP:                  ;'       g    R Uu/ uF@  pTP                   P                  4       '       g   K%  TP                   P                  4       TbKB  	  ppTP                  R4      p\        T\        4      '       d   \        T4      M/ p. TP<                  ;'       g    ROTOTN Få  p\?        T4      P                  4       pT'       g   K&  TP                  T4      p\        T\        4      '       d   \        T4      M/ pTP                  T4      pTer   TP1                  RTP@                  3RTPB                  33 UUu/ uF9  w  ppT'       g   K  TP                  4       '       g   K(  TTP                  4       bK;  	  upp4       TTT&   Kç  	  TTR&   TP                  T4      pTe%   TP@                  ;'       g    R P                  4       MR pT'       dÝ   TT8w  dÖ   ^ RI"H#p TPB                  ;'       g    R P                  4       PI                  4       pT! T4      e|   \        T P                  R4      \        4      '       d   T P                  R4      M/ pTP                  R4      p \        T \        4      '       d   \        T 4      M/ p TT T&   T TR&   TT R&   TpYOR&   TPK                  T/ 4       TPL                  '       dP   TPL                  ^ 8”  d?   \O        TPL                  4      TR&   \O        TPL                  4      TR,          T,          R&   \Q        T
4      p!TPR                  e   TPR                  P                  4       MRp"T"'       dc   \T        PV                  ! T"4      '       g   \Y        T"4      '       d   \        R\Z        R7      h\]        T!T"4       T!TR&   TP9                  RR4       MµT"e1   \_        T!4       TP9                  RR4       TP9                  RR4       M�\?        TP                  R4      ;'       g    R 4      P                  4       '       dJ   \a        T
4      '       g9   \]        T!TR,          P                  4       4       T!TR&   TP9                  RR4       Te   YŠ8w  d   TP9                  TR4       Y÷T
&   YpR	&   TPb                  '       dŒ   \e        Y
YC4      p#\g        T P                  R/ 4      T#4      T R&   TP                  R4      '       dJ   \        T R,          \        4      '       d-   TR,          T R,          R&   T R,          P9                  RR4       Y¯3#   \         d   p\        RRR7      ThRp?ii ; iu upi u uppi )rÕ   rS  r?   zname requiredr@   zbase_url requiredz%base_url must include scheme and hostNzmodel requiredr  )r    ©rH  rT  r:  r;  r  r<  r5  r4  r  Úcanonical_modelÚreasoning_effort)Úparse_reasoning_effortÚagentÚreasoning_overridesrB  r  r  r\   )4r:  r  r;  rZ  r  r   ÚurllibÚparseÚurlparserE   ÚschemeÚnetlocr¦   r  r„   r  rA  r   r  Úhermes_cli.config_providersr    rh  r  r´   ÚupdaterN   r<  r4  rf  Úmodel_detailsr  r9   rp  rq  Úhermes_constantsrr  r  r²   rB  Úintr   r  r   Ú	fullmatchr   r   r3   r1   r-  Úmake_defaultr   r
   )$rO  rm   r:  r;  r  ÚparsedrI   r  r	  rv   r  r    rg  Ú	convertedÚrestoredr¡   rŒ   ÚdetailsÚexisting_modelsÚ
models_mapÚ	candidateÚmodel_idrL  râ   rB   rX   rY   ÚaliasÚ	canonicalrr  ÚeffortÚ	agent_cfgÚ	overridesrª   Úsubmitted_keyrá   s$   &&                                  r;   Ú_write_custom_endpointr�  =  sÄ  € Ø�I‰I�OˆO˜×"Ñ"Ó$€DØ—‘×#Ð# ×*Ñ*Ó,×3Ñ3°CÓ8€HØ�Z‰Z×Ð˜2×$Ñ$Ó&€EçÜ¨°OÔDÐDßÜ¨Ð4GÔHÐHðfÜ—‘×&Ñ& xÓ0ˆð �=�=ˆ= §§ Ü¨Ð4[Ô\Ð\ßÜ¨Ð4DÔEÐEð
 —‘˜Ó$€IÜ�i¤×&Ò&Øˆ	ô :¸)ÇWÁW×EYÐEYÐPT×PYÑPYÓZÑ€JØ4<Ò4HÔ$ ZÔ0ÔNaÐbf×biÑbi×bvÐbvÐmq×mvÑmvÓNw€KØÒõ 	Zä,¨SÓ>ˆð Ò!ñ 6°fÕWØ'+ð 	ô �i¤×&Ò&Ø ‰HØÒØ—w‘wÐ1Ó2ˆHÜ˜(¤D×)Ò)Ø—‘ Ô'ØÒØˆô ! ›N€EØ	‡L�LØ��j (¨G°UØœ4 × 4Ñ 4Ó5ðô ð ‡}�}Ò Ø�	‰	�+˜tÔ$Ø�=�=ˆ=Ø $§¡ˆE�*Òà�I‰I�j $Ô'ð *.×);Ñ);×)AÐ)A¸rÐ)AÓSÑ)A 1ÀaÇdÁdÇjÁjÇlŒˆq�t‰t�z‰z‹|˜QŠÑ)A€GÐSØ—i‘i Ó)€OÜ:DÀ_ÔVZ×:[Ò:[¤ oÔ!6Ðac€JØ<˜Ÿ™×)Ð) rÐ<¨WÐ<°eÓ<ˆ	Ü�y“>×'Ñ'Ó)ˆßÙØ—.‘. Ó*ˆÜ)¨'´4×8Ò8Œd�7Œm¸bˆØ—‘˜XÓ&ˆØÒð �J‰JÐ3DÀf×F\ÑF\Ð2]Ø3EÀv×G^ÑG^Ð2_ñ2aô uñ 2a©¨¨AÜdeô %Øjk×jqÑjq×jsô %˜˜1Ÿ7™7›9šñ 2aò uô và"ˆ
�8Óñ =ð !€Eˆ(�Oð �K‰K˜Ó€EØ9>Ò9J�×&Ñ&×,Ð,¨"×3Ñ3Ô5ÐPR€Iß�Y %Ô'Ý;Ø×(Ñ(×.Ð.¨B×5Ñ5Ó7×=Ñ=Ó?ˆÙ! &Ó)Ò5Ü,6°s·w±w¸wÓ7GÌ×,NÒ,N˜Ÿ™ Ô(ÐTVˆIØ!Ÿ™Ð&;Ó<ˆIÜ+5°iÄ×+FÒ+Fœ˜YœÈBˆIØ#)ˆI�iÑ Ø/8ˆIÐ+Ñ,Ø$ˆC�‰LØˆØˆg‰Ø×Ñ˜e RÔ(Ø××Ð˜t×2Ñ2°QÔ6Ü"% d×&9Ñ&9Ó":ˆÐÑÜ36°t×7JÑ7JÓ3Kˆˆh�˜ÕÐ/Ñ0ô & kÓ2€GØ,0¯L©LÒ,D�D—L‘L×&Ñ&Ô(È$€Mßô × Ò  ×/Ò/Ô3QÐR_×3`Ò3`Ü¨CÔ8XÔYÐYÜ�w Ô.Ø"ˆˆiÑØ�	‰	�)˜TÕ"Ø	Ò	"ä˜Ô!Ø�	‰	�)˜TÔ"Ø�	‰	�)˜TÕ"Ü	ˆU�Y‰Y�yÓ!×'Ð' RÓ	(×	.Ñ	.×	0Ò	0Ô9SÐT_×9`Ò9`ô 	�w  iÕ 0× 6Ñ 6Ó 8Ô9Ø"ˆˆiÑØ�	‰	�)˜TÔ"àÒ *Ô";Ø�‰�j $Ô'Ø"ˆkÑØ ˆÑà××ÐÜ0°À5ÓSˆÜ3°C·G±G¸GÀRÓ4HÈ&ÓQˆˆG‰Ø�9‰9�Y×Ò¤J¨s°7­|¼T×$BÒ$BØ&+¨IÕ&6ˆC��L˜Ñ#Ø��L×Ñ˜Y¨Ô-àÐÐøô[ ô fÜ¨Ð4[Ô\ÐbeÐeûðfüò@ Tùóus6   Â'_ Ê:"_9Ë!_9Ï+_>Ï=_>Ð_>ß_6ß#_1ß1_6z/api/providers/custom-endpointsc                ó:   € V ^8„  d   QhR\         \        ,          /# r_   r`   )r:   s   "r;   r<   r<   Ù  s   € ÷ 	<ñ 	<¤8¬C¥=ñ 	<r=   c           	     ó
  € \        RRRR7      ;_uu_ 4        \        V 4      ;_uu_ 4        \        \        4       4      uuRRR4       uuRRR4       #   + '       g   i     M; i RRR4       R#   + '       g   i     R# ; i)a  Return configured OpenAI-compatible custom endpoints for Desktop.

Scoped to the requested profile's config.yaml: the desktop settings UI
targets the active profile, so read/write must resolve that profile's home
rather than the process-level HERMES_HOME (mirrors ``/api/config``).
z*GET /api/providers/custom-endpoints failedrC   zFailed to list custom endpointsr{   N)r   r,   rb  r/   rÉ   s   &r;   Úlist_custom_endpointsr’  Ø  sU   € ô 
ÐBÀCÐPq×	rÖ	rÜ" 7×+Õ+Ü,¬[«]Ó;÷ ,Ñ+÷ 
sÒ	rß+×+úÐ+÷ 
s×	r×	rÒ	rús!   —A1«A	¾
A1ÁA#ÁA1Á1B	c                óF   € V ^8„  d   QhR\         R\        \        ,          /# rä   )r%   r)   r9   )r:   s   "r;   r<   r<   æ  s   € ÷ ñ Ô!5ð ÄÌÅñ r=   c                óˆ  € \        RRRR7      ;_uu_ 4        \        V4      ;_uu_ 4        \        ;_uu_ 4        \        4       pVP	                  R4      p\        \        V\        4      '       d   TM/ V P                  ;'       g    V P                  4      ^,          RJ p\        W 4      w  rV\        V4       \        V4      p^ RIHp V! 4       p	RRR4       RRR4       X'       d   \        X	4       RXR	&   XVR
&   VuuRRR4       #   + '       g   i     LA; i  + '       g   i     LL; i  + '       g   i     R# ; i)z<Create or update a v12+ ``providers`` custom endpoint entry.z+POST /api/providers/custom-endpoints failedrC   zFailed to save custom endpointr{   r  N)Úget_hermes_homeTrr   rA  )r   r,   r4   r/   r¦   r  r  r„   rA  r:  r�  r2   rb  r}  r•  Ú_record_custom_endpoint_setup)
rm   rL   rO  r  Úcreatedr  Ú_entryÚresponser•  Úhomes
   &&        r;   Úupsert_custom_endpointr›  å  sù   € ô 
ÐCÀSÐQq×	rÖ	rô # 7×+Õ+×-BÖ-BÜ“-ˆCØŸ™ Ó,ˆIÜ4Ü'¨	´4×8Ò8‘	¸bÀ$Ç'Á'×BVÐBVÈTÏYÉYóXØXYõ[Ø^bðcˆGä"8¸Ó"CÑˆKÜ˜ÔÜ0°Ó5ˆHÝ8Ù"Ó$ˆD÷ .C×+÷ Ü)¨$Ô/Øˆ�‰Ø$ˆ�‰Ø÷% 
sÒ	r÷ .C×-Bú×+×+ú÷	 
s×	rÐ	rúsG   —D0«D	ºAD
ÂA
D
ÃD	ÃD0Ã)D0Ä
DÄD	ÄD-Ä(D0Ä0E	c                ó(   € V ^8„  d   QhR\         RR/# )r6   rš  rƒ   N)r&   )r:   s   "r;   r<   r<   ý  s   € ÷ añ a¬ð a°ñ ar=   c                ó8   € ^ RI HpHp V! V! 4       RV RR7       R# )zZCounted after the config lock is released (a cold metrics runtime must not stall writers).)Úrecord_provider_setup_donerð   rÍ   T)Úhermes_homeÚ
backgroundN)rô   rž  rð   )rš  rž  rð   s   &  r;   r–  r–  ý  s   € çkáÑ0Ó2°HÈ$Ð[_×`r=   z6/api/providers/custom-endpoints/{endpoint_id}/activatec                óF   € V ^8„  d   QhR\         R\        \         ,          /# ©r6   r  rL   ©r9   r)   )r:   s   "r;   r<   r<     s"   € ÷ 0Fñ 0F¬#ð 0F¼Ä½ñ 0Fr=   c                ó>  € \        RV  R2RRR7      ;_uu_ 4        \        V4      ;_uu_ 4        \        ;_uu_ 4        \        4       p\	        VP                  R4      V 4      w  r4Vf   \        V 4      p\        W%4      pV'       d   \        WeR7      MRpVf   \        R	R
R7      h\        VP                  R4      \        4      '       d   VP                  R4      M/ pWGV&   WrR&   M\        V4      p\        V4      p\        VP                  R4      ;'       g-    VP                  R4      ;'       g    V'       d
   V^ ,          MR4      P                  4       p	\        VP                  R4      ;'       g    VP                  R4      ;'       g    R4      P                  4       p
V	'       d	   V
'       g   \        RRR7      h\!        VP                  R/ 4      \#        W%Wš4      4      pVP                  R4      '       d    VR,          VR&   VP%                  RR4       MƒVP                  R4      '       dm    \        \'        V4      ;'       g    R4      P                  4       pVP+                  R4      '       d   VP-                  R4      '       d   WËR&   MVR,          VR&   W²R&   \/        V4       RRR4       RRR4       RRRXRX	/uuRRR4       #   \(         d    Rp Li ; i  + '       g   i     L=; i  + '       g   i     LH; i  + '       g   i     R# ; i)z?Set a configured custom endpoint as the default model provider.z%POST /api/providers/custom-endpoints/z/activate failedrC   z"Failed to activate custom endpointr{   r  Nro  é”  úcustom endpoint not foundr@   r  r  rÕ   r;  rR  r?   zcustom endpoint is incompleter  r  r   r!  rr   Tr†   )r   r,   r4   r/   r  r¦   r  rh  r    r   r  r„   r   r  r9   r  r
   r   rf  r(  rF   rV   Úendswithr2   )r  rL   rO  r	  r¡   rH  rg  r  r  r  r;  rG  Ú_raw_keys   &&           r;   Úactivate_custom_endpointr©    s–  € ô 
Ø
/°¨}Ð<LÐMÈsØ3÷
ö 
ô # 7×+Õ+×-BÖ-BÜ“-ˆCÜ >¸s¿w¹wÀ{Ó?SÐU`Ó aÑˆJØŠ}ô  3°;Ó?�Ü4°SÓG�ßhnÔAÀ&ÕdÐtx�Ø’=Ü'°CÐ@[Ô\Ð\Ü4>¸s¿w¹wÀ{Ó?SÔUY×4ZÒ4Z˜CŸG™G KÔ0Ð`b�	Ø*/˜,Ñ'Ø#,�KÒ ä1°*Ó=�ä7¸Ó>ˆFÜ˜Ÿ	™	 'Ó*×iÐi¨e¯i©i¸Ó.H×iÐi×Z`ÈVÐTUÎYÐfhÓj×pÑpÓrˆEÜ˜5Ÿ9™9 ZÓ0×JÐJ°E·I±I¸eÓ4D×JÐJÈÓK×QÑQÓSˆHß§Ü#°Ð<[Ô\Ð\ä4Ø—‘˜ Ó$Ô&EÀcÐY^Ó&iókˆIà�y‰y˜×#Ò#Ø',¨YÕ'7�	˜)Ñ$Ø—‘˜i¨Õ.Ø—‘˜9×%Ò%ð"Ü"Ô#8¸Ó#F×#LÐ#LÈ"ÓM×SÑSÓU�Hð ×&Ñ& t×,Ò,°×1BÑ1BÀ3×1GÒ1GØ+3˜iÒ(à+0°Õ+;�I˜iÑ(Ø$�‰LÜ˜Ô÷S .C×+ðT �d˜J¨°g¸uÐE÷]
ò 
øôL !ô "Ø!’Hð"ú÷E .C×-Bú×+×+ú÷	
÷ 
ð 
ús›   ›L¯K8	¾CK%ÄK%Ä4K%Ä=9K%Å7K%ÆK%Æ-K%Æ5A?K%È6KÉKÉ"K%É9K%Ê K%Ê0K8	Ê8LËK"ËK%Ë!K"Ë"K%Ë%K5Ë0K8	Ë8LÌLÌL	z-/api/providers/custom-endpoints/{endpoint_id}c                óF   € V ^8„  d   QhR\         R\        \         ,          /# r¢  r£  )r:   s   "r;   r<   r<   9  s   € ÷ ñ ¬ð ´h¼sµmñ r=   c                ó²  € \        RV  R2RRR7      ;_uu_ 4        \        V4      ;_uu_ 4        \        ;_uu_ 4        \        4       pVP	                  R4      p\        W04      w  rEVe9   \        V\        4      '       d#   \        V4      pVP                  VR4       W2R&   M%\        V 4      p\        W&4      f   \        RR	R
7      h\        W&V4       \        \        V4      4       \!        V4       \#        V4      pRRR4       RRR4       RXR&   VuuRRR4       #   + '       g   i     L); i  + '       g   i     L4; i  + '       g   i     R# ; i)z7Remove a configured custom endpoint from ``providers``.z'DELETE /api/providers/custom-endpoints/z failedrC   z Failed to delete custom endpointr{   r  Nr¥  r¦  r@   Trr   )r   r,   r4   r/   r¦   r  r  r„   r   rf  r  rh  r   rl  r1   r   r2   rb  )r  rL   rO  r  r	  r¡   rH  r™  s   &&      r;   Údelete_custom_endpointr¬  8  s  € ô 
Ø
1°+°¸gÐFÈØ1÷
ö 
ô # 7×+Õ+×-BÖ-BÜ“-ˆCØŸ™ Ó,ˆIÜ >¸yÓ VÑˆJØÒ ¤Z°	¼4×%@Ò%@Ü1°*Ó=�Ø—‘˜j¨$Ô/Ø#,�KÒ ô  3°;Ó?�Ü.¨sÓAÒIÜ'°CÐ@[Ô\Ð\Ü,¨SÀÔFÜÔ4°\ÓBÔCÜ˜ÔÜ0°Ó5ˆH÷! .C×+ð" ˆ�‰Ø÷-
ò 
÷ .C×-Bú×+×+ú÷	
÷ 
ð 
ús:   ›E¯D2	¾C DÃ>D2	ÄEÄD/Ä*D2	Ä2EÄ=EÅE	z(/api/providers/custom-endpoints/validatec                ó$   € V ^8„  d   QhR\         /# )r6   rm   )r%   )r:   s   "r;   r<   r<   U  s   € ÷ -ñ -Ô)=ñ -r=   c              ƒ  óò  "  € V P                   ;'       g    RP                  4       P                  R4      pV'       g   RRRRRRR	. /# R
R/pV P                  '       dA   V P                  P                  4       '       d!   RV P                  P                  4        2VR&   \	        W4      G Rj  x€L
 w  r4Vf   RRRRRRV R2R	. /# VP
                  R9   d   RRRRRRR	. /# VP                  '       g   RRRRRRVP
                   R2R	. /# \        V4      pV Uu. uF  qfR,          NK  	  ppV'       g   RRRRR\        WC4      R	. R. RV/# \        V P                  ;'       g    R4      P                  4       ;'       g    \        V4      pV P                  ;'       g    RP                  4       ;'       g    V'       d
   V^ ,          MRp	 \        VR4      ;_uu_4       GRj  x€L
 p
\        W£W‰V4      G Rj  x€L
 pRRR4      GRj  x€L
  RRRRRRR	TRTRTRT/pX'       d   TP#                  RTR7       T#  ELŽu upi  L^ LK L=  + GRj  x€L 
 '       g   i     LT; i  \          d    Rp Lfi ; i5i)zEProbe a custom endpoint by calling its OpenAI-compatible /models URL.rÕ   rS  rr   FÚ	reachableTÚmessagezEnter an endpoint URL first.r  ÚAcceptúapplication/jsonúBearer ÚAuthorizationNúCould not reach z/models.z"The endpoint rejected the API key.zEndpoint returned HTTP Ú.rA  r|  Úresolved_base_urlç       @Útransport_checked)rr   r°  ©i‘  i“  )r;  r  rZ  r  Ú_probe_openai_compatible_modelsrA   Ú
is_successr   Ú_no_models_probe_messager   r4  r  Ú_auto_api_moder  Ú_endpoint_probe_clientÚ_probe_transport_routerF   r{  )rm   r;  ÚheadersÚresolvedÚrespÚentriesrV  Úidsr7  Úprobe_modelÚclientÚmissingrá   s   &            r;   Úvalidate_custom_endpointrÉ  T  sz  é € ð —‘×#Ð# ×*Ñ*Ó,×3Ñ3°CÓ8€HßØ�e˜[¨$°	Ð;YÐ[cÐegÐhÐhàÐ+Ð,€GØ‡|‡|€|˜Ÿ™×*Ñ*×,Ò,Ø%,¨T¯\©\×-?Ñ-?Ó-AÐ,BÐ#Cˆ�Ñ ä:¸8ÓM×M�N€HØ‚|Ø�e˜[¨%°Ð>NÈxÈjÐX`Ð<aÐckÐmoÐpÐpØ×Ñ˜:Ô%Ø�e˜[¨$°	Ð;_ÐaiÐkmÐnÐnØ�?�?ˆ?Ø�e˜[¨$°	Ð=TÐUY×UeÑUeÐTfÐfgÐ;hÐjrÐtvÐwÐwô # 4Ó(€GÙ#Ó
$™G�qˆT�7ˆ7™G€CÐ
$ßð �e˜[¨$°	Ô;SÐTXÓ;cØ˜"˜o¨rÐ3FÈðRð 	Rô ˜tŸ}™}×2Ð2°Ó3×9Ñ9Ó;×WÐW¼~ÈhÓ?W€DØ—:‘:×#Ð# ×*Ñ*Ó,×GÐG¿3°°Q¶ÀB€KðÜ)¨(°C×8×8Ô8¸FÜ2°6ÀTÐX_Ó`×`ˆG÷ 9×8ð
 �D˜+ t¨Y¸¸HÀcÈ?Ð\cØ! 4Ð)<¸hðH€FçØ�‰˜¨ˆÔ0Ø€MòG Nùò %ñ  9Ù`÷ 9×8×8Ò8ûäô ØŠðüsï   ‚;I7¾I7ÁI7Á>.I7Â,H:Â-AI7Ã2'I7ÄH=Ä*8I7Å#I7Å?I7ÆI7Æ6I7Æ?I7ÇI$ Ç#IÇ$I$ Ç'IÇ8IÇ9IÇ=I$ ÈIÈ	I$ ÈI7È%I7È=I7ÉI$ ÉIÉI$ ÉI!	ÉIÉ
I!	ÉI!	ÉI$ É I7É!I$ É$I4É1I7É3I4É4I7c                ó<   € V ^8„  d   QhR\         R\        R\        /# )r6   rÃ  r;  rƒ   )r&   r9   )r:   s   "r;   r<   r<   „  s!   € ÷ =ñ =¤3ð =´#ð =¼#ñ =r=   c                óæ  € VR,           pV P                   P                  R4      ;'       g    RP                  R4      ^ ,          P                  4       p V P	                  4       p\        V\        \        34      '       g   T;'       g    RpRV RV R	2# \        V\        4      '       d   VP                  R
4      MTp\        V\        4      '       g   RV R2# RV R2#   \
         d    Rp L‹i ; i)uB  Why a 200 ``/models`` probe yielded no usable models (#83128).

Distinguishes the three ways that happens â€” a non-JSON body (an SPA catch-all serves
HTML for every route, so 200 proves nothing), a JSON body without a model list, and a
genuinely empty list â€” mirroring the onboarding store's wording for the last case.
ú/modelszcontent-typerÕ   Ú;Nza non-JSON bodyzConnected to z, but it returned ut    instead of a JSON model list â€” the URL may be an SPA catch-all or a wrong base URL, not an OpenAI-compatible API.Údataz:, but its response is not an OpenAI-compatible model list.zL, but it advertised no models. Start a model on that endpoint and try again.)	rÁ  r¦   Úsplitr  ÚjsonrE   r  r„   r  )rÃ  r;  rˆ   Úcontent_typeÚpayloadÚkindrÎ  s   &&     r;   r½  r½  „  sù   € ð �YÕ
€CØ—L‘L×$Ñ$ ^Ó4×:Ð:¸×AÑAÀ#ÓFÀqÕI×OÑOÓQ€LðØ—)‘)“+ˆô �g¤¤d˜|×,Ò,Ø×0Ð0Ð0ˆØ ˜uÐ$6°t°fð =eð eð 	fä",¨W´d×";Ò";ˆ7�;‰;�vÔÀ€DÜ�dœD×!Ò!Ø˜s˜eÐ#]Ð^Ð^Ø˜C˜5ð !<ð <ð =øô ô ØŠðús   ÁC  Ã C0Ã/C0c                ót   € V ^8„  d   QhR\         R\        \        ,          R\        \         \        3,          /# )r6   r;  rÁ  rƒ   )r9   r)   r„   r  r&   )r:   s   "r;   r<   r<   œ  s2   € ÷ ñ ´Cð Ä(Ì4Å.ð ÔUZÔ[^Ô`cÐ[cÕUdñ r=   c              ƒ  óV  "  € V P                  R4      pVP                  4       P                  R4      '       d   VRR P                  R4      MVR,           pTRrT\        VR4      ;_uu_4       GRj  x€L
 pW#3 Fc  p VP	                  VR,           VR7      G Rj  x€L
 pTe$   TP                  '       g   TP                  R8X  d   YxrTTP                  '       g   Kc   M	  RRR4      GRj  x€L
  WE3#  L� LZ  \
         d     KŒ  i ; i L  + GRj  x€L 
 '       g   i     YE3# ; i5i)	uË  GET ``{base}/models``, then ``{base}/v1/models`` (or the ``/v1``-stripped variant) when the
first answers a non-success. Returns ``(resolved_base_url, response)`` â€” the base that served the
model list is what the caller must PERSIST: the runtime appends ``/chat/completions`` to the saved
URL verbatim, so a bare host root that only "detected" via ``/v1/models`` would 404 every chat
(#65488). ``response`` is None when no candidate could be reached at all.rS  z/v1Nr¸  rÌ  )rÁ  r¥  éýÿÿÿ)rZ  r  r§  r¿  r¦   rF   r¼  rA   )	r;  rÁ  ÚbaseÚ	alternaterÂ  rÃ  rÇ  r‡  Úcandidate_resps	   &&       r;   r»  r»  œ  s	  é € ð �?‰?˜3Ó€DØ)-¯©«×)>Ñ)>¸u×)EÒ)E��S�b�	× Ñ  Ô%È4ÐRWÍ<€IØ˜4ˆdÜ% d¨C×0×0Ô0°FØÓ*ˆIðØ'-§z¡z°)¸iÕ2GÐQX zÓ'Y×!Y�ð
 Š|˜~×8×8Ð8¸D×<LÑ<LÐPSÔ<SØ!*˜$Ø×(×(Ò(Ùñ +÷ 1×0ð ˆ>Ðñ 1ñ "ZøÜô Úðú÷	 1×0×0Ñ0ð ˆ>Ðüs�   ‚A/D)Á1C3Á2D)Á5DÁ=C7ÂC5
ÂC7ÂDÂ5"DÃDÃ D)Ã+D	Ã,D)Ã5C7Ã7D	ÄDÄD	ÄDÄ	D)ÄD&	ÄDÄ
D&	ÄD&	Ä
D)z/chat/completionsz
/responsesz	/messageszChat CompletionszResponses APIzAnthropic Messagesc                ó0   € V ^8„  d   QhR\         R\         /# )r6   r;  rƒ   r8   )r:   s   "r;   r<   r<   º  s   € ÷ Dñ DœSð D¤Sñ Dr=   c                ó2   € ^ RI Hp V! V 4      ;'       g    R# )z•The transport the runtime falls back to for an endpoint without a pinned ``api_mode``
(same resolver as ``runtime_provider_custom._custom_runtime``).)Ú_detect_api_mode_for_urlr.  )Úhermes_cli.runtime_providerrÜ  )r;  rÜ  s   & r;   r¾  r¾  º  s   € õ EÙ# HÓ-×CÐCÐ1CÐCr=   c          
      óv   € V ^8„  d   QhR\         R\         R\         R\        \         \         3,          R\         /# )r6   r;  r7  r  rÁ  rƒ   r«   )r:   s   "r;   r<   r<   Á  sD   € ÷ cñ c´3ð c¼cð cÌ#ð cÔX\Ô]`ÔbeÐ]eÕXfð cÔknñ cr=   c           	   ƒ  óê  "  € \         P                  V4      pVf   R# VR8X  dF   RVR^RRRR	R
/./pVP                  RR4      P                  R4      p/ VCRR/CV'       d   RV/M/ CpMVR8X  d
   RVRR
R^/pMRVR^RRRR	R
/./p V P                  W,           WdR7      G Rj  x€L
 pTP
                  R9  d   R# T RT RTP
                   R\        T,           R2#  L:  \         d     R# i ; i5i)ug  POST a 1-token request to ``mode``'s route; return a failure message when the host does
not serve it (404/405/501), ``""`` otherwise. Any other status â€” 200, 400 (bad body), 401,
422, 429 â€” means the route exists, which is all the check needs to know; a network error or
timeout (a local server still loading the model) is inconclusive and does not block.NrÕ   r0  r  Ú
max_tokensÚmessagesÚroleÚuserÚcontentÚhir´  r³  zanthropic-versionz
2023-06-01z	x-api-keyr/  ÚinputÚmax_output_tokens)rÐ  rÁ  z/models answered, but POST z returned HTTP z: this host does not serve the z& API. Pick the API mode it does serve.)r¥  i•  iõ  )Ú_TRANSPORT_ROUTESr¦   rJ  ÚpostrF   rA   Ú_TRANSPORT_LABELS)	rÇ  r;  r7  r  rÁ  ÚrouterÒ  ÚtokenrÃ  s	   &&&&&    r;   rÀ  rÀ  Á  sB  é € ô
 ×!Ñ! $Ó'€EØ‚}ÙØÐ#Ô#Ø˜E <°°JÀ&È&ÐR[Ð]aÐAbÐ@cÐdˆØ—‘˜O¨RÓ0×=Ñ=¸iÓHˆØk�WÐkÐ1°<Ñk×\aÀ[ÐRWÑDXÐgiÐk‰Ø	Ð"Ô	"Ø˜E 7¨DÐ2EÀrÐJ‰à˜E <°°JÀ&È&ÐR[Ð]aÐAbÐ@cÐdˆðØ—[‘[ Õ!1¸�[ÓQ×Qˆð ×Ñ˜Ô.ÙØˆjÐ3°E°7¸/È$×JZÑJZÐI[ð \"Ü"3°DÕ"9Ð!:Ð:`ðbð cñ RøÜô ÚðüsB   ‚AC3Á"%C3ÂC! Â$CÂ%C! Â)6C3ÃC! Ã!C0Ã,C3Ã/C0Ã0C3c                ó0   € V ^8„  d   QhR\         R\        /# )r6   rˆ   Útimeout)r9   Úfloat)r:   s   "r;   r<   r<   Û  s   € ÷ cñ c¤ð c¬eñ cr=   c                óp   € ^ RI p^ RIHp VP                  VP	                  V4      V! V 4      '       * R7      # )ak  httpx client for a user-entered endpoint probe. Local endpoints (loopback, LAN, Tailscale)
ignore ``HTTP(S)_PROXY``: httpx honours the env/system proxy but not its bypass list, so a
system proxy (Clash on Windows, corporate) answered the ``127.0.0.1`` probe with its own error
page and the GUI reported "advertised no models" while the CLI saw the model (#63472).N)Úis_local_endpoint)rî  Ú	trust_env)ÚhttpxÚagent.model_metadatarñ  ÚAsyncClientÚTimeout)rˆ   rî  ró  rñ  s   &&  r;   r¿  r¿  Û  s3   € ó
 Ý6Ø×Ñ U§]¡]°7Ó%;ÑK\Ð]`ÓKaÔGaÐÓbÐbr=   z/api/providers/validatec                ó0   € V ^8„  d   QhR\         R\        /# )r6   rm   Úrequest)r"   r   )r:   s   "r;   r<   r<   æ  s"   € ÷ Bsñ Bs¬\ð BsÄGñ Bsr=   c              ƒ  óX  "  € \        V4       ^ RIpV P                  ;'       g    RP                  4       pV P                  ;'       g    RP                  4       pV'       g	   RRRRRR/# VR	8X  dÈ   V P
                  ;'       g    RP                  4       pV'       d   R
RV 2/MRp\        WF4      G Rj  x€L
 w  rxVR,           p	Vf   RRRRRRV	 R2/# \        V4      p
V
 Uu. uF  q»R,          NK  	  ppV'       g-   VP                  '       g   RRRRRV	 RVP                   R2R. /# RRRRRRRVRV
RV/# \        P                  V4      pV'       g	   RRRRRR/# Vw  ržVR8X  d-   ^ RIHp V! V	P                  R^4      ^ ,          4      R,           p	RR/p/ pVR8X  d
   RV 2VR
&   MVVR&    VP                  VP!                  R4      R7      ;_uu_4       GRj  x€L
 pVP                  W–VR7      G Rj  x€L
 pRRR4      GRj  x€L
  XP                  R"9   d	   RRRRRR/# TP                  R8X  g   TP                  '       d	   RRRRRR/# RRRRRR TP                   R!2/#  EL³u upi  L‘ Lx Lj  + GRj  x€L 
 '       g   i     L�; i  \"         d    RRRRRR/u # i ; i5i)#aI  Live-probe a provider credential before it's saved.

Returns {ok, reachable, message}. ok=True means the provider accepted the
key; ok=False + reachable=True means the key is bad (caller should block);
reachable=False means the network probe couldn't run (caller may save with
a warning rather than hard-blocking offline users).
NrÕ   rr   Fr¯  Tr°  zEnter a value first.ÚOPENAI_BASE_URLr´  r³  rÌ  rµ  r¶  rA  z answered HTTP r  r|  r·  rù   )Únormalize_gemini_base_urlr±  r²  Úbearerrè   g      $@)rî  )rÁ  Úparamsz/Could not reach the provider to verify the key.z9That API key was rejected. Double-check it and try again.é­  zProvider returned HTTP z for this key.rº  )r.   ró  rè   r  rÙ   r  r»  r   r¼  rA   Ú_CREDENTIAL_PROBESr¦   Úagent.gemini_native_adapterrû  Úrsplitrõ  rö  rF   )rm   rø  ró  rè   rÙ   r  rÁ  rÂ  rÃ  rˆ   rÄ  rV  r  ÚprobeÚauthrû  rý  rÇ  s   &&                r;   Úvalidate_provider_credentialr  å  sæ  é € ô �7ÔÛà�8‰8�>ˆ>�r×
 Ñ
 Ó
"€CØ�Z‰Z×Ð˜2×$Ñ$Ó&€EßØ�e˜[¨$°	Ð;QÐRÐRð ÐÔØ—<‘<×%Ð% 2×,Ñ,Ó.ˆß<C�? g¨g¨YÐ$7Ñ8ÈˆÜ>¸uÓN×N‰ˆØ˜Õ"ˆØŠ<Ø˜% ¨e°YÐBRÐSVÐRWÐWXÐ@YÐZÐZÜ& tÓ,ˆÙ#*Ó+¡7˜a�D—'�'¡7ˆÐ+ß˜dŸoŸo˜oð ˜% ¨d°IÀ#ÀÀoÐVZ×VfÑVfÐUgÐghÐ?iÐksÐuwÐxÐxØ�d˜K¨¨y¸"¸hÈÐP_ÐahØ# Xð/ð 	/ô ×"Ñ" 3Ó'€Eßà�d˜K¨°	¸2Ð>Ð>à�I€CØ
ÐÔÝIñ (¨¯
©
°9¸aÓ(@ÀÕ(CÓDÀyÕPˆØÐ+Ð,€GØ€FØˆxÔØ%,¨U¨GÐ#4ˆ�Ò àˆˆu‰ðoØ×$Ñ$¨U¯]©]¸4Ó-@Ð$×A×AÔAÀVØŸ™ CÀ˜ÓH×HˆD÷ B×Að
 ×Ñ˜:Ô%Ø�e˜[¨$°	Ð;vÐwÐwØ×Ñ˜3Ô $§/§/ /à�d˜K¨¨y¸"Ð=Ð=Ø�%˜ d¨IÐ9PÐQU×QaÑQaÐPbÐbpÐ7qÐrÐròU Oùò
 ,ñ6 BÙH÷ B×A×AÒAûäô oØ�e˜[¨%°Ð<mÐnÒnðoüsà   ‚AJ*Á	J*Á"!J*ÂJ*ÂJ*Â4I'Â5.J*Ã#I*Ã4J*ÄAJ*ÅAJ*Æ0-J ÇI/ÇJ Ç!I5Ç8I1Ç9I5Ç=J ÈI3È	J È;J*É	J*É*J*É/J É1I5É3J É5J	É;I>É<
J	ÊJ	Ê	J ÊJ*ÊJ ÊJ'Ê$J*Ê&J'Ê'J*c                óF   € V ^8„  d   QhR\         R\        \        ,          /# rä   )r#   r)   r9   )r:   s   "r;   r<   r<   ,  s   € ÷ ñ œ|ð ´h¼sµmñ r=   c              ƒ   óB  a a"  € \        R 4      ;_uu_ 4        ^ RIHo \        S P                  ;'       g    TV V3R l4      G Rj  x€L
 pVP                  R4      '       g   \        RS P                   R2R7      hVuuRRR4       #  LA  + '       g   i     R# ; i5i)zDELETE /api/env failed)Úremove_provider_env_credentialc                  ó(   <€ S! S P                   4      # rQ   )rè   )rm   r  s   €€r;   rR   Ú remove_env_var.<locals>.<lambda>6  s   ø€ Ñ-KÈDÏHÉHÔ-Ur=   NÚfoundr¥  ú not found in .envr@   )rJ   ró   r  r   rL   r¦   r   rè   )rm   rL   rá   r  s   f& @r;   Úremove_env_varr  +  s}   ùé € ô 
Ð3×	4Õ	4ÝRä'Ø�L‰L×#Ð#˜GÕ%Uó
÷ 
ˆð �z‰z˜'×"Ò"Ü¨C¸4¿8¹8¸*ÐDVÐ8WÔXÐXØ÷ 
5Ò	4ñ
÷ 
5×	4Ð	4üs4   „B˜/BÁB	ÁBÁ#BÁ>BÂ	BÂB	Â	Bz/api/env/revealc                óR   € V ^8„  d   QhR\         R\        R\        \        ,          /# )r6   rm   rø  rL   )r$   r   r)   r9   )r:   s   "r;   r<   r<   >  s(   € ÷ -ñ -Ü
ð-Ü!(ð-Ü3;¼Cµ=ñ-r=   c              ƒ  óZ  "  € \        V4       \        P                  ! 4       pV\        ,
          p\         Uu. uF  qUV8”  g   K  VNK  	  up\        R&   \	        \        4      \
        8¼  d   \        RRR7      h\        P                  V4       \        V P                  ;'       g    T\        4      G Rj  x€L
 pVP                  V P                  4      pVf   \        RV P                   R2R7      h\        P                  RV P                  4       R	V P                  R
V/# u upi  Lr5i)zÍReturn the real (unredacted) value of a single env var.

Protected by the ephemeral session token (per server start, injected into
the SPA), rate limiting (max 5 reveals per 30s window) and audit logging.
:NNNrþ  z,Too many reveal requests. Try again shortly.r@   Nr¥  r  zenv/reveal: %srè   rÙ   )r.   ÚtimeÚ_REVEAL_WINDOW_SECONDSÚ_reveal_timestampsÚlenÚ_REVEAL_MAX_PER_WINDOWr   r´   r   rL   r0   r¦   rè   rG   rÐ   )rm   rø  rL   ÚnowÚcutoffÚtrÝ   rÙ   s   &&&     r;   Úreveal_env_varr  =  sï   é € ô �7Ôä
�)Š)‹+€CØÔ)Õ)€FÝ(:ÓIÑ(: 1À&¹jŸQ˜QÑ(:ÑIÔ�qÑÜ
ÔÓÔ"8Ô8Ü¨Ð4bÔcÐcÜ×Ñ˜cÔ"ä(¨¯©×)@Ð)@¸Ä(ÓK×K€KØ�O‰O˜DŸH™HÓ%€EØ‚}Ü¨°t·x±x°jÐ@RÐ4SÔTÐTä‡I�IÐ §¡Ô)Ø�4—8‘8˜W eÐ,Ð,ùò Jñ
 Lùs*   ‚6D+¸D$ÁD$ÁAD+Â'D+Â6D)Â7A3D+c                óÂ   € V ^8„  d   Qh/ ^ \         9   d   \        \        ,          ;R&   ^\         9   d,   \        \        \
        \        \        3,          3,          ;R&   # )r6   r  rÿ  )Ú__conditional_annotations__r  rï  r„   r9   r  )r:   s   "r;   r<   r<      sN   € ÷ ñ ÷` %Ò $”Dœ•KÑ $ña÷Jò ”Dœœe¤C¬ H�oÐ-Õ.ñ òKr=   )Úgeneralrs  Úterminalrs   Ú
delegationÚmemoryÚcompressionÚsecurityÚbrowserÚvoiceÚttsÚsttÚloggingÚdiscordÚ	auxiliary)NTrQ   )NF)F)z https://openrouter.ai/api/v1/keyrü  )z https://api.openai.com/v1/modelsrü  )zhttps://api.x.ai/v1/modelsrü  )z7https://generativelanguage.googleapis.com/v1beta/modelsÚqueryrà   >   r/  r.  r0  )r  Ú__doc__Ú
contextlibr$  rÿ   r|   r  Úurllib.parseru  Úfastapir   Úhermes_cli.web_routers._commonr   r   r   r   r   Úhermes_cli.web_depsr   r	   Úhermes_cli.web_server_configr
   r   r   r   r   Úhermes_cli.web_server_profilesr   r   r   r   r   r   rò   r   r   r   r   r   r   r   r   r   r   rz  r   r    Úhermes_cli.web_modelsr!   r"   r#   r$   r%   Útypingr&   r'   r(   r)   r*   Ú	getLoggerrG   Úconfig_routerÚrouterr+   r,   r-   r.   r/   r0   r1   r2   r3   r4   r  r  r  rd   ÚcontextmanagerrJ   r¦   rZ   r]   re   rk   Úputr~   r�   rÀ   rÅ   rÊ   rÈ   rë   rç   rÿ  r  r  r  r#  r(  r-  r6  r8  rE  rM  rb  rh  rl  r�  r’  ré  r›  r–  r©  Údeleter¬  rÉ  r½  r»  rè  rê  r¾  rÀ  r¿  r  r  r  r<   )r  s   @r;   Ú<module>r8     sA  øðöó Û Û 	Û Û Û Ý ÷õ ÷ 0÷õ ÷ó ÷ +÷ t÷  t÷  tß fß nÕ nß 3Õ 3à×ÒÐ0Ó1€Ù“€Ù	‹€ñ !Ð!<Ð>_Ó`Ð ÙÐ4Ð6VÓWÐ ÙÐ&Ð(HÓI€ÙÐ&Ó'€Ù�=Ð"5Ó6€Ù�
Ð/Ó0€ÙÐ*Ð,?Ó@Ð Ù�=Ð"5Ó6€ÙÐ&Ð(;Ó<€Ù!Ð"9Ó:Ð ð #%Ð Ó $ØÐ ØÐ ò€ð ×ÑôMó ðMð$ ×Ñ�=Ó!ö
Fó "ð
Fð ×ÑÐ)Ó*ñó +ðð ×ÑÐ'Ó(öAó )ðAð ×ÑÐ'Ó(ö.ó )ð.ð ‡�ˆMÓö&-ó ð&-õRð Ø	Ñ:Ð;Ø	Ñ;Ð<ðð Ð)Ñ+qÐrÐtðÐ õQðh ‡�ˆJÓö@ó ð@÷;ð| ‡�ˆJÓö	Hó ð	H÷	ð$ ÐHØÐDØÐ;ØÐZð	2Ð ó ÷õ
:õ$[õõ"Eõ	Qò SÐ õ6õõ4õ;õ|÷õ*Xðv ‡�Ð-Ó.ö	<ó /ð	<ð ‡�Ð.Ó/öó 0ðõ.að ‡�ÐEÓFö0Fó Gð0Fðf ‡�Ð>Ó?öó @ðð6 ‡�Ð7Ó8ô-ó 9ð-õ^=õ0ð0 (Ð)<Ð>OÐQ]Ø)¨;ð8Ð à'Ð);Ð=NÐP_Ø)Ð+?ðAÐ õDõcõ4cð ‡�Ð&Ó'ôBsó (ðBsðJ ‡�ˆzÓöó ðð" ‡�ÐÓö-ó  ò-r=   