+
    jHàjì/ ã                  óä  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t^ RIt^ RIt^ RIt^ RIHt ^ RIHtHtHt ]'       d   ^ RIHt ^ RIHt ^ RIHt ^ RIHt ^ R	IH t H!t!H"t"H#t#H$t$H%t%H&t&H't'H(t(H)t)H*t*H+t+H,t,H-t-H.t.H/t/H0t0H1t1H2t2 ^ R
I3H4t4H5t5 ^ RI6H7t7H8t8H9t9H:t:H;t;H<t<H=t=H>t>H?t?H@t@ ]P‚                  ! ]B4      tCR]! 4       Pˆ                   2tERtF]F R2tGRtH. ER®OtI. ER¯OtJRR/R R lltKRRRR/R R lltLR]M/R R lltNR R ltOR 3R R lltPR R  ltQRtRR!]SR"&   R# R$ ltTR% R& ltUR'R(/R) R* lltVR+ R, ltWRsXR!]SR-&   R. R/ ltYR0 R1 ltZR2 R3 lt[R4 R5 lt\R6 R7 lt]ER°R9R(/R: R; lllt^ER°R9R(/R< R= lllt_R> R? lt`^´taR@]SRA&   / tbRB]SRC&   RD RE ltcRF RG ltdRHR(RIR(/RJ RK llteRLtfRMtgR@]SRN&   / thRO]SRP&   RQ RR ltiRS RT ltjRU RV ltkER±R9R(/RX RY llltlRZ R[ ltmR\ R] ltnR^R(R_RR`R8R9R(/Ra Rb lltoER²Rd Re lltpRf Rg ltqER²Rh Ri lltrRj Rk ltsRl Rm lttRn Ro ltuRp Rq ltvRswRr]SRs&   RtxRt]SRu&   R(tyR(tzRt{Rr]SRv&   Rt|Rt]SRw&   R(t}R(t~^ RxIH€t€H�t‚Hƒtƒ Ry Rz lt„R{ R| lt…R} R~ lt†ER³R9R(RR(/R€ R� lllt‡R9R(/R‚ Rƒ lltˆR„ R… lt‰R† R‡ ltŠER³R9R(/Rˆ R‰ lllt‹R9R(/RŠ R‹ lltŒ]�! ].4      ]�! ]-4      ,          RcRŒ0,          tŽR�]SRŽ&   ]�]�]‘]’]“]”3t•R� R� lt–R‘ R’ lt—R“ R” lt˜R•R/R– R— llt™R˜ R™ ltšRš R› lt›Rœ R� ltœRž RŸ lt�ER´R R/R¡ R¢ llltž^tŸR£ R¤ lt R9R(/R¥ R¦ l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¸ 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Ê lt³RË RÌ lt´RÍRRÎRRÏR/RÐ RÑ l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àt½Rát¾Rs¿Râ]SRã&   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÷ ltÉRø Rù ltÊ/ RcRú bRû]¼bRü]ÁbRý]ÁbRþ]ÂbRÿ]ÅbER ]ÄbER]ÆbERER bERER bERER bER]ÇbER	]ÇbRŒ]ÈbER
]ÉbER]ÊbtËER]SER&   ]Ì! 0 ERµm4      tÍER ER ltÎER ER ltÏER ER ltÐER ER ltÑER tÒER ER ltÓER ER ltÔ]Ì! 0 ER¶m4      tÕER ER ltÖR9R(/ER ER llt×ERtØER·tÙ^<tÚ]�! 4       tÛER ]SER!&   ]EP¸                  ! 4       tÝER´ER" ER# lltÞER´ER$ ER% lltßER& ER' ltàER´ER( ER) lltáER* ER+ ltâER, ER- ltãER. ER/ ltäER0 ER1 ltåER2 ER3 ltæER4 ER5 ltçER6 ER7 ltèR9R(ER8]ØER9R(/ER: ER; lltéER´ER< ER= lltêER> ER? ltëER¸RÎRER@R/ERA ERB llltìERC ERD ltíEREERF/ERG ERH lltî0 ER¹mtïERIR(/ERJ ERK lltðERIR(/ERL ERM lltñRsòERN]SERO&   RsóERP]SERQ&   ERRsôERS]SERT&   ERUtõERºERV ERW lltö/ s÷ERX]SERY&   ERRsøERS]SERZ&   RsùERP]SER[&   ERtúER´ER\ ER] lltûER^ ER_ ltüERºER` ERa lltýER»ERb ERc lltþERdRER@R/ERe ERf lltÿERg ERh lEt ERi ERj lEtERdRER@R/ERk ERl llEtERm ERn lEtER¼EtERq ERr lEtERs ERt lEtERoER½ERpER¾/EtERu]SERv&   ERw ERx lEtERpERyERoERz/Et	ER{ ER| lEt
ERdRER@R/ER} ER~ llEt/ EtER]SER€&   ER�EtER‚ ERƒ lEtER¿ER„ ER… llEtERÀER† ER‡ llEt]
EP"                  ! ERˆ4      Et]Ì! 0 ERÁm4      EtER‰]SERŠ&   ER‹EtERŒEt/ EtER�]SERŽ&   / EtER]SER�&   ER�EtER� ER‘ lEtER’ ER“ lEtER”RWR9R(/ER• ER– llEtER”RWR9R(/ER— ER˜ llEtER¸R9R(/ER™ ERš lllEtR9R(/ER› ERœ llEtER´ER� ERž llEtER¸ERŸ ER  llEt ERÀER¡ ER¢ llEt!ER£ ER¤ lEt"ER¥R(/ER¦ ER§ llEt#ER8]Ø/ER¨ ER© llEt$ER”RWERªRRRR9R(RR(ER«RER8]Ø/ER¬ ER­ llEt%R# (Â  a�  Provider/model catalogs: discovery, caching, and identity helpers.

Origin module; cohesive clusters live in siblings and are re-imported here so
``hermes_cli.models.<name>`` stays the stable import/monkeypatch surface:
``models_catalog_static`` (curated tables, provider registry, aliases), ``models_reasoning_caps``,
``models_local`` (Ollama / LM Studio), ``models_pricing``, ``models_validate``.
)ÚannotationsN)ÚPath)ÚAnyÚOptionalÚTYPE_CHECKING)Ú	TypeGuard)Únormalize_route_base_url©Úopen_credentialed_url)Úget_version_info)ÚCuratedFallbackModelsÚCANONICAL_PROVIDERSÚOPENROUTER_MODELSÚPREFERRED_SILENT_DEFAULT_MODELÚVERCEL_AI_GATEWAY_MODELSÚ_AGGREGATOR_PROVIDERSÚ!_AZURE_FOUNDRY_RESPONSES_PREFIXESÚ_BORROWED_MODEL_PROVIDERSÚ_COPILOT_MODEL_ALIASESÚ_LIVE_FIRST_PICKER_PROVIDERSÚ_MODELS_DEV_PREFERREDÚ_OPENAI_FAST_MODE_PREFIXESÚ_OPENAI_ULTRAFAST_MODELSÚ_PROVIDER_ALIASESÚ_PROVIDER_LABELSÚ_PROVIDER_MODELSÚ_PROVIDER_RETIRED_ALIASESÚ_SILENT_DEFAULT_PROVIDERSÚ_xai_finalize_catalog)Ú_OPENROUTER_CATALOG_URLÚ_seed_reasoning_caps)
Ú_OLLAMA_LOCAL_MODELS_CACHEÚ_OLLAMA_LOCAL_MODELS_CACHE_TTLÚ!_OLLAMA_LOCAL_PROBE_FAILURE_CACHEÚ_OLLAMA_LOCAL_PROBE_REACHABLEÚ_get_ollama_base_urlÚ_get_ollama_native_headersÚ_ollama_local_catalogÚ_ollama_probe_cache_keyÚ_root_for_ollama_native_apiÚfetch_ollama_cloud_modelszhermes-cli/zhttps://api.githubcopilot.comú/modelszvscode/1.104.1Ússl_contextc               ó    € V ^8„  d   QhRRRR/# )é   Úreqzurllib.request.RequestÚtimeoutÚfloat© )Úformats   "Ú6/home/ubuntu/.hermes/hermes-agent/hermes_cli/models.pyÚ__annotate__r5   P   s   € ÷ Pñ PÐ(>ð PÈEñ Pó    c               ó   € \        WVR7      # )z@Open catalog requests without forwarding headers across origins.)r0   r,   r	   )r/   r0   r,   s   &$$r4   Ú_urlopen_model_catalog_requestr8   P   s   € ä  À;ÔOÐOr6   ÚheadersÚopenerc          
     ó,   € V ^8„  d   QhRRRRRRRRR	R/# )
r.   ÚurlÚstrr0   r1   r9   úOptional[dict[str, str]]Úopen_kwargsr   Úreturnr2   )r3   s   "r4   r5   r5   U   s4   € ÷ 
)ñ 
)Ø	ð
)Øð
)Ø*Bð
)Øgjð
)àñ
)r6   c               óô  € \         P                  P                  Y;'       g    / R7      pT;'       g    \        ! V3RV/VB ;_uu_ 4       pVP	                  4       pVP                  R4      R8X  dF   VP                  P                  RR4      P                  4       R8X  d   \        P                  ! V4      p\        P                  ! VP                  4       4      uuRRR4       #   + '       g   i     R# ; i)z½GET ``url`` and parse the JSON body. ``opener`` defaults to the catalog opener (resolved at
call time so monkeypatching ``_urlopen_model_catalog_request`` still applies). Raises on failure.)r9   r0   zAccept-encodingÚgzipzContent-EncodingÚ N)ÚurllibÚrequestÚRequestr8   ÚreadÚ
get_headerr9   ÚgetÚlowerrB   Ú
decompressÚjsonÚloadsÚdecode)r<   r0   r9   r:   r?   r/   ÚrespÚbodys   &$$$,   r4   Ú	_get_jsonrQ   U   s¶   € ô
 �.‰.×
 Ñ
  ¯m¨m¸Ð
 Ó
<€CØ
×
2Ð
2Ô2Ð
2°CÑ	XÀÐ	XÈK×	XÒ	XÐ\`Ø�y‰y‹{ˆØ�>‰>Ð+Ó,°Ô6¸4¿<¹<×;KÑ;KÐL^Ð`bÓ;c×;iÑ;iÓ;kÐouÔ;uÜ—?’? 4Ó(ˆDÜ�zŠz˜$Ÿ+™+›-Ó(÷	 
Y×	X×	XÓ	Xús   ÁBC&Ã&C7	Úerrorsc               ó    € V ^8„  d   QhRRRR/# )r.   Úpathr   r@   úOptional[dict]r2   )r3   s   "r4   r5   r5   c   s   € ÷ 4ñ 4˜4ð 4¸ñ 4r6   c               óâ   €  \        V RR7      ;_uu_ 4       p\        P                  ! V4      pRRR4       \        X\        4      '       d   T# R#   + '       g   i     L*; i  T d     R# i ; i)zLLoad a JSON-object cache file; None when missing, unreadable, or not a dict.ú	utf-8-sig)ÚencodingN)ÚopenrL   ÚloadÚ
isinstanceÚdict)rT   rR   ÚfhÚdatas   &$  r4   Ú_read_json_cacher_   c   s[   € ðÜ�$ ×-Õ-°Ü—9’9˜R“=ˆD÷ .ô ˜d¤D×)Ò)ˆ4Ð3¨tÐ3÷	 .×-ûàô Úðús-   ‚A# —A®A# ÁA 	ÁA# Á A# Á#A.Á-A.c               ó(   € V ^8„  d   QhRRRRRRRR/# )r.   rT   r   r^   r   Údump_kwargsr@   ÚNoner2   )r3   s   "r4   r5   r5   m   s(   € ÷ 1ñ 1˜Dð 1¨ð 1¸Cð 1ÀDñ 1r6   c                óT   € ^ RI Hp ^ RIHp V! V P                  4       V! W3/ VB  R# )u‡   Atomically persist a cache file (creating parents). Raises on failure â€” callers decide
whether a failed cache write is worth logging.)Úatomic_json_write)Úmkdir_under_hermes_homeN)Úutilsrd   Úhermes_constantsre   Úparent)rT   r^   ra   rd   re   s   &&,  r4   Ú_write_json_cacheri   m   s#   € õ (Ý8á˜DŸK™KÔ(Ù�dÑ0 KÔ0r6   c                ó4   € \        V 4      P                  4       # ©N)r=   rJ   ©Úms   &r4   Ú<lambda>rn   w   s   € Ì#ÈaË&Ï,É,Ì.r6   c               ó$   € V ^8„  d   QhRRRRRR/# )r.   Úprimaryú	list[str]Ú	secondaryr@   r2   )r3   s   "r4   r5   r5   w   s"   € ÷ ñ ˜9ð °ð Ð]fñ r6   c                óÈ   € \        V 4      V  Uu0 uF
  q2! V4      kK  	  pppV F5  pV! V4      pWe9  g   K  VP                  V4       VP                  V4       K7  	  V# u upi )z[``primary`` verbatim, then ``secondary`` entries whose ``key`` is new (deduped as it goes).)ÚlistÚaddÚappend)rp   rr   Úkeyrm   ÚmergedÚseenÚks   &&&    r4   Ú_merge_uniquer{   w   s]   € ä˜“=±7Ó";±7¨a 3 q¦6±7ˆDÐ";€FÛˆÙ�‹FˆØŽ=Ø�H‰H�QŒKØ�M‰M˜!Öñ	 ð
 €Mùò #<s   �Ac               ó   € V ^8„  d   QhRR/# )r.   Úbase_urlr=   r2   )r3   s   "r4   r5   r5   ‚   s   € ÷ ñ ¨3ñ r6   c                ó°   € ^ RI Hp V! V 4      pVRJ d   R# VRJ d:   ^ RIpVP                  VP                  4      pRVn        VP                  Vn        V# V# )zHUse the same trust decision for urllib catalogs and HTTPX metadata/chat.)Úresolve_verifyTNF)Úagent.model_metadata_httpr   ÚsslÚ
SSLContextÚPROTOCOL_TLS_CLIENTÚcheck_hostnameÚ	CERT_NONEÚverify_mode)r}   r   Úverifyr�   Úcontexts   &    r4   Ú_custom_provider_ssl_contextr‰   ‚   sU   € å8á˜HÓ%€FØ�ƒ~ÙØ�ƒÛà—.‘. ×!8Ñ!8Ó9ˆØ!&ˆÔØ!Ÿm™mˆÔØˆØ€Mr6   úlist[tuple[str, str]] | NoneÚ_openrouter_catalog_cachec               ó   € V ^8„  d   QhRR/# )r.   r@   r1   r2   )r3   s   "r4   r5   r5   œ   s   € ÷ &ñ & eñ &r6   c                 ó   € ^ RI Hp  V ! 4       # )zdSame TTL as the catalog manifest this list is filtered from (honours ``model_catalog.ttl_minutes``).©Úrefresh_interval_seconds)Úhermes_cli.model_catalogr�   rŽ   s    r4   Ú_openrouter_catalog_disk_ttlr‘   œ   s   € åAá#Ó%Ð%r6   c               ó   € V ^8„  d   QhRR/# ©r.   r@   r   r2   )r3   s   "r4   r5   r5   £   s   € ÷ Kñ K tñ Kr6   c                 ó8   € ^ RI Hp  V ! 4       R,          R,          # )é    ©Úget_hermes_homeÚcachezopenrouter_curated_catalog.json©rg   r—   r–   s    r4   Ú_openrouter_catalog_disk_pathrš   £   s   € Ý0áÓ˜wÕ&Ð)JÕJÐJr6   Úallow_staleFc               ó    € V ^8„  d   QhRRRR/# )r.   r›   Úboolr@   rŠ   r2   )r3   s   "r4   r5   r5   ©   s   € ÷ ñ °$ð ÐC_ñ r6   c                ó8  € \        \        4       4      pVf   R#  V '       gE   \        P                  ! 4       \        VP	                  R^ 4      4      ,
          \        4       8”  d   R# TP	                  R4      p\        T\        4      '       g   R# T Uu. uFW  p\        T\        \        34      '       g   K!  \        T4      ^8X  g   K3  \        T^ ,          4      \        T^,          4      3NKY  	  ppT;'       g    R#   \        \        3 d     R# i ; iu upi )u³   Fresh curated catalog from disk, or None (missing, corrupt, expired, or empty).

``allow_stale`` ignores the TTL â€” the cache-only read path prefers a stale copy over a live GET.NÚ
fetched_atÚcurated)r_   rš   Útimer1   rI   r‘   Ú	TypeErrorÚ
ValueErrorr[   rt   ÚtupleÚlenr=   )r›   ÚobjÚitemsÚitÚouts   $    r4   Ú_read_openrouter_catalog_diskrª   ©   sà   € ô Ô8Ó:Ó
;€CØ
‚{ÙðßœtŸyšy›{¬U°3·7±7¸<ÈÓ3KÓ-LÕLÔOkÓOmÔmÙð �G‰G�IÓ€EÜ�eœT×"Ò"ÙÙ.3Ó
f©e¨´zÀ"ÄtÌUÀm×7TÔ#ÔY\Ð]_ÓY`ÐdeÑYeÔ#ŒC��1•‹Jœ˜B˜q�E›
Ó#©e€CÐ
fØ�;ˆ;�$Ðøô ”zÐ"ô Úðüò
 gs)   ›C? £AC? ÂDÂ7DÃ	(DÃ?DÄDc               ó    € V ^8„  d   QhRRRR/# )r.   r    úlist[tuple[str, str]]r@   rb   r2   )r3   s   "r4   r5   r5   ¼   s   € ÷ Nñ NÐ,Að NÀdñ Nr6   c                óø   €  \        \        4       R \        P                  ! 4       RV  Uu. uF  p\        V4      NK  	  up/4       R# u upi   \         d"   p\
        P                  RT4        Rp?R# Rp?ii ; i)rŸ   r    z0openrouter curated catalog disk write failed: %sN)ri   rš   r¡   rt   Ú	ExceptionÚloggerÚdebug)r    ÚcÚexcs   &  r4   Ú_write_openrouter_catalog_diskr³   ¼   sc   € ðNÜÜ)Ó+Øœ4Ÿ9š9›;¨	ÁWÓ3MÁWÀ´D¸¶GÁWÑ3MÐNö	Pùâ3MøÜô NÜ�‰ÐGÈ×MÒMûðNús'   ‚(A ªA¾A ÁA ÁA9ÁA4Á4A9Ú_ai_gateway_catalog_cachec               ó(   € V ^8„  d   QhRRRRRRRR/# )	r.   Úpricingr   Úkeysútuple[str, str]Údefaultr=   r@   r�   r2   )r3   s   "r4   r5   r5   Ì   s(   € ÷ ñ ˜#ð  _ð ¸sð Àtñ r6   c                óà   a a€ \        S \        4      '       g   R#  \        ;QJ d     VV 3R lV 4       F  '       d   K   R# 	  R# ! VV 3R lV 4       4      #   \        \        3 d     R# i ; i)zNTrue when both pricing fields parse to 0 (missing fields read as ``default``).Fc              3  ó`   <"  € T F#  p\        SP                  VS4      4      ^ 8H  x € K%  	  R# 5i)r•   N)r1   rI   )Ú.0rz   r¹   r¶   s   & €€r4   Ú	<genexpr>Ú_zero_priced.<locals>.<genexpr>Ñ   s&   øé € ÐEÁ¸1”5˜Ÿ™ Q¨Ó0Ó1°QÖ6Ãùs   ƒ+.T)r[   r\   Úallr¢   r£   )r¶   r·   r¹   s   f&fr4   Ú_zero_pricedrÀ   Ì   sX   ù€ ä�gœt×$Ò$Ùðß‹sÕEÁÓE�sŒsÐEŠsÐEˆsÕEÁÓEÓEÐEøÜ”zÐ"ô Úðús'   œ
A §A ¿A ÁA ÁA ÁA-Á,A-c               ó    € V ^8„  d   QhRRRR/# )r.   Úentryr   r@   r�   r2   )r3   s   "r4   r5   r5   Ö   s   € ÷ Sñ S 3ð S¨4ñ Sr6   c                óZ   € \        V \        4      ;'       d    V P                  R4      R8H  # )zWThe gateway bills this catalog row to a subscription the account holds, not to credits.Úbilling_modeÚsubscription©r[   r\   rI   )rÂ   s   &r4   Ú_is_subscription_billedrÇ   Ö   s%   € ä�eœTÓ"×RÐR u§y¡y°Ó'@ÀNÑ'RÐRr6   c               ó$   € V ^8„  d   QhRRRRRR/# )r.   Úmodel_idr=   r¶   údict[str, dict[str, str]]r@   r�   r2   )r3   s   "r4   r5   r5   Û   s'   € ÷ rñ r˜Sð rÐ+Dð rÈñ rr6   c                óŠ   € VP                  V 4      p\        V4      ;'       d!    \        V4      ;'       g    \        VRR4      # )z‚Return True if *model_id* costs no credits: zero-cost prompt AND completion pricing, or a row
the gateway bills to a subscription.Ú1©ÚpromptÚ
completion)rI   r�   rÇ   rÀ   )rÉ   r¶   rÂ   s   && r4   Ú_is_model_freerÐ   Û   s=   € ð �K‰K˜Ó!€EÜ�‹;×qÐqÔ3°EÓ:×pÐp¼lÈ5ÐRjÐloÓ>pÐqr6   c               ó(   € V ^8„  d   QhRRRRRRRR/# )	r.   Ú	model_idsrq   r¶   rÊ   Ú	free_tierr�   r@   ztuple[list[str], list[str]]r2   )r3   s   "r4   r5   r5   â   s2   € ÷ Mñ MØðMØ#<ðMØIMðMà ñMr6   c                ó¼   € V'       d	   V'       g   V . 3# V  Uu. uF  p\        W14      '       g   K  VNK  	  ppY@ Uu. uF  q3V9  g   K  VNK  	  up3# u upi u upi )z˜Split Nous models into (selectable, unavailable): free-tier users may only select free models
(paid ones are returned as unavailable, shown grayed out).)rÐ   )rÒ   r¶   rÓ   ÚmidÚ
selectables   &&&  r4   Úpartition_nous_models_by_tierr×   â   sZ   € ÷
 ŸGØ˜2ˆÐÙ!*ÓK¡˜#¬n¸S×.J—#�#¡€JÐKØ¨	ÓK©	 À
Ñ5JŸ˜©	ÑKÐLÐLùò LùÚKs   ™A±A½AÁ
Ac               ó4   € V ^8„  d   QhRRRRRRRRRR	R
R	RR/# )r.   Útier_keyr=   Úcurated_idsrq   r¶   rÊ   Úportal_base_urlÚforce_refreshr�   Úsynthesize_free_pricingr@   ú+tuple[list[str], dict[str, dict[str, str]]]r2   )r3   s   "r4   r5   r5   í   sO   € ÷ cñ cØðcØ )ðcØ4MðcØ`cðcàðcà59ðcð 1ñcr6   c               ó6  €  \        W4R7      p\        V\        4      '       d   VP	                  V 4      MRp\        V\
        4      '       d   TM. pV U	u. uF  p	\        V	4      ;p
'       g   K  V
NK  	  pp	V'       g   \        V4      \        V4      3# \        V4      pV'       d    V F  pVP                  VRRRR/4       K  	  \        V4      p\        V4      V Uu. uF  qÝV9  g   K  VNK  	  up,           V3#   \         d    Rp Lÿi ; iu up	i u upi )u	  Append the Portal's ``<tier_key>`` recommendations missing from ``curated_ids``.

Curated models show first, Portal-only picks follow. Failures (network, parse, missing field)
silently return the inputs unchanged â€” never block the picker on a Portal-side hiccup.
©rÜ   NrÎ   Ú0rÏ   )	Úfetch_nous_recommended_modelsr®   r[   r\   rI   rt   Ú_extract_model_nameÚ
setdefaultÚset)rÙ   rÚ   r¶   rÛ   rÜ   rÝ   ÚpayloadÚblockÚentriesrÂ   ÚnameÚ
portal_idsÚaugmented_pricingrÕ   ry   s   &&&&$$         r4   Ú"_union_with_portal_recommendationsrì   í   s  € ðÜ/°Ô]ˆô &0°¼×%>Ò%>ˆG�K‰K˜Ô!ÀD€EÜ! %¬×.Ò.‰e°B€GÙ$+ÓT¡G˜5Ô8KÈEÓ8RÐ0R°Ó0R—$�$¡G€JÐTßÜ�[Ó!¤4¨£=Ð1Ð1ä˜W›ÐßÛˆCØ×(Ñ(¨¨x¸¸lÈCÐ.PÖQñ äˆ{Ó€DÜ�Ó±
Ó N±
¨È¹o§ ±
Ñ NÕNÐPaÐbÐbøô ô ØŠðüò Uùò !Os)   ‚C> ÁDÁ/DÃ DÃ-DÃ>DÄDrC   rÜ   c          
     ó,   € V ^8„  d   QhRRRRRRRRR	R
/# ©r.   rÚ   rq   r¶   rÊ   rÛ   r=   rÜ   r�   r@   rÞ   r2   )r3   s   "r4   r5   r5     s;   € ÷ Cñ CØðCØ%>ðCØQTðCàðCà$OñCr6   c          	     ó"   € \        RWVVRR7      # )z£Curated list + pricing plus the Portal's ``freeRecommendedModels``; Portal-only free picks get a
synthetic $0 pricing entry so tier partitioning sees them as free.ÚfreeRecommendedModelsT©rÜ   rÝ   ©rì   ©rÚ   r¶   rÛ   rÜ   s   &&&$r4   Ú&union_with_portal_free_recommendationsrô     s   € ô
 .Ø °Ø#¸TôCð Cr6   c          
     ó,   € V ^8„  d   QhRRRRRRRRR	R
/# rî   r2   )r3   s   "r4   r5   r5     s;   € ÷ Dñ DØðDØ%>ðDØQTðDàðDà$OñDr6   c          	     ó"   € \        RWVVRR7      # )zeCurated list plus the Portal's ``paidRecommendedModels``; ``pricing`` is deliberately left untouched.ÚpaidRecommendedModelsFrñ   rò   ró   s   &&&$r4   Ú&union_with_portal_paid_recommendationsrø     s   € ô .Ø °Ø#¸UôDð Dr6   c               ó$   € V ^8„  d   QhRRRRRR/# )r.   rÚ   rq   r¶   zdict[str, dict[str, Any]]r@   r2   )r3   s   "r4   r5   r5     s(   € ÷ Cñ C°	ð CÐD]ð CÐbkñ Cr6   c                ó"  a	a
aa€ ^ RI Ho ^ RIHo	Hp \        V 4      p. pT;'       g    / P                  4        EF  w  po
WS9   gC   \        S
\        4      '       d-   S
P                  R4      RJ g   S
P                  R4      '       d   KQ  V! S
P                  RR4      S
P                  RR4      S
P                  R	4      4      p\        ;QJ d"    V	V
VV3R
 lR 4       F  '       g   K   RM	  RM! V	V
VV3R
 lR 4       4      pVf   KÐ  \        S
P                  R	4      \        4      '       g   K÷  V'       g   EK  VP                  V^ ,          ) V34       EK   	  \        V 4      \        V4       UUu. uF  w  r…VNK	  	  upp,           # u uppi )a  Curated list plus every paid Nous model the gateway is discounting right now, deepest
discount first. A sale lives only in ``/v1/models`` ``pricing.original``, so without this the
picker badges discounts on curated rows but never shows a discounted model the curated list and
Portal recommendations omit. Free rows stay with ``freeRecommendedModels``; rows the gateway
marks tool-less (``"tools": False``) are skipped because Hermes is tool-calling-first, and
image/video generation rows are skipped because they are not chat models.)Úisfinite)Ú_price_floatÚcompute_sale_discountÚtoolsFÚ
generationrÎ   rC   rÏ   Úoriginalc              3  ó~   <"  € T F2  pS! SP                  V4      R R7      ;oRJ;'       d	    S! S4      x € K4  	  R# 5i)T)ÚpositiveN©rI   )r¼   rw   rü   rÂ   rû   Úrates   & €€€€r4   r½   Ú1union_with_nous_on_sale_models.<locals>.<genexpr>-  sC   øé € ð 
á/�ñ " %§)¡)¨C£.¸4Ô@Ð@ˆTÈÐM×`Ð`ÑRZÐ[_ÓR`Ô`Û/ùs   ƒ(=¬=TrÍ   )Úmathrû   Úhermes_cli.models_pricingrü   rý   rå   r§   r[   r\   rI   Úanyrv   rt   Úsorted)rÚ   r¶   rý   ry   Úon_salerÕ   ÚsaleÚpaidÚ_rü   rÂ   rû   r  s   &&       @@@@r4   Úunion_with_nous_on_sale_modelsr    s,  û€ õ çMäˆ{Ó€DØ%'€GØ—}�} "×+Ñ+×-‰
ˆˆUØŒ;œj¨´×5Ò5¸¿¹À7Ó9KÈuÓ9TÐX]×XaÑXaÐbn×XoÒXoÙÙ$ U§Y¡Y¨x¸Ó%<¸e¿i¹iÈÐVXÓ>YÐ[`×[dÑ[dÐeoÓ[pÓqˆç‹s÷ 
á/ó
�s�sŠs÷ 
á/ó
ó 
ˆð Ô¤
¨5¯9©9°ZÓ+@Ä$× GÔ GÏDÊDØ�N‰N˜T !�W˜H c˜?×+ñ .ô �Ó´&¸´/ÔB±/©¨£±/ÒBÕBÐBùÓBs   Å4FÚintÚ_FREE_TIER_CACHE_TTLzdict[str, tuple[bool, float]]Ú_free_tier_cachec               ó   € V ^8„  d   QhRR/# ©r.   r@   r=   r2   )r3   s   "r4   r5   r5   ;  s   € ÷ ñ ˜cñ r6   c                 ó   € ^ RI Hp  V ! 4       # )z9Stable profile identity for process-local pricing caches.©Úhermes_home_key)rg   r  r  s    r4   Ú_pricing_profile_keyr  ;  s   € å0áÓÐr6   c               ó   € V ^8„  d   QhRR/# )r.   r@   úOptional[bool]r2   )r3   s   "r4   r5   r5   B  s   € ÷ ñ  >ñ r6   c                 ó²   € \         P                  \        4       4      p V e-   \        P                  ! 4       V ^,          ,
          \
        8¼  d   R# V ^ ,          # )zGThis profile's live cached entitlement, or ``None`` if unknown/expired.N)r  rI   r  r¡   Ú	monotonicr  )Úcacheds    r4   Úget_cached_nous_free_tierr  B  s@   € ä×!Ñ!Ô"6Ó"8Ó9€FØ‚~œŸšÓ)¨F°1­IÕ5Ô9MÔMÙØ�!�9Ðr6   Úforce_freshÚcached_onlyc               ó$   € V ^8„  d   QhRRRRRR/# )r.   r  r�   r  r@   r2   )r3   s   "r4   r5   r5   J  s"   € ÷ ñ ¨ð ÀDð ÐUYñ r6   c                óö   € \         P                  ! 4       p\        4       pV '       g   \        4       pVe   V# V'       d   R#  ^ RIHp V! V R7      P                  pWb3\        V&   V#   \         d    Rp Li ; i)u#  True only when the Nous Portal user is KNOWN to be free-tier (unknown/error â†’ False so this
never blocks users). Cached ``_FREE_TIER_CACHE_TTL`` seconds so an upgrade shows within minutes.
``cached_only`` returns the live cached answer or the fail-open ``False`` without contacting Portal.F)Úget_nous_portal_account_info©r  )	r¡   r  r  r  Úhermes_cli.nous_accountr"  Úis_free_tierr®   r  )r  r  ÚnowÚprofile_keyÚcached_resultr"  Úresults   $$     r4   Úcheck_nous_free_tierr*  J  sw   € ô �.Š.Ó
€CÜ&Ó(€KßÜ1Ó3ˆØÒ$Ø Ð ßÙðÝHá-¸+ÔF×SÑSˆð &, MÔ�[Ñ!Ø€Møô ô ØŠðús   ÁA( Á(A8Á7A8z/api/nous/recommended-modelsiX  Ú_NOUS_RECOMMENDED_CACHE_TTLz3dict[tuple[str, str], tuple[dict[str, Any], float]]Ú_nous_recommended_cachec               ó   € V ^8„  d   QhRR/# r“   r2   )r3   s   "r4   r5   r5   l  s   € ÷ Gñ G Tñ Gr6   c                 ó8   € ^ RI Hp  V ! 4       R,          R,          # )r•   r–   r˜   znous_recommended_cache.jsonr™   r–   s    r4   Ú_nous_recommended_disk_pathr/  l  s   € Ý0ÙÓ˜wÕ&Ð)FÕFÐFr6   c               ó    € V ^8„  d   QhRRRR/# )r.   Úbaser=   r@   z#tuple[dict[str, Any], float] | Noner2   )r3   s   "r4   r5   r5   q  s   € ÷ ñ  cð Ð.Qñ r6   c                óê  € \        \        4       \        \        P                  \
        3R7      pT;'       g    / P                  V 4      p\        V\        4      '       d   VP                  R4      MRp\        V\        4      '       d	   V'       g   R#  \        P                  ! 4       \        VP                  R^ 4      4      ,
          pW43#   \        \        \        3 d    \        R4      p Y43# i ; i)zAReturn the last good payload and its age for the freshness check.©rR   r^   NÚtsÚinf)r_   r/  ÚOSErrorrL   ÚJSONDecodeErrorÚUnicodeDecodeErrorrI   r[   r\   r¡   r1   r¢   r£   ÚOverflowError)r1  ÚblobrÂ   r^   Úages   &    r4   Ú_read_nous_recommended_diskr<  q  s¼   € äÔ7Ó9Ä7ÌD×L`ÑL`ÔbtÐBuÔv€DØ�ZˆZ�R×Ñ˜TÓ"€EÜ *¨5´$× 7Ò 7ˆ5�9‰9�VÔ¸T€DÜ�dœD×!Ò!¯ÙðÜ�iŠi‹kœE %§)¡)¨D°!Ó"4Ó5Õ5ˆð ˆ9Ðøô ”z¤=Ð1ô Ü�E‹l‰Øˆ9Ððús   Â5C Ã!C2Ã1C2c               ó$   € V ^8„  d   QhRRRRRR/# )r.   r1  r=   r^   údict[str, Any]r@   rb   r2   )r3   s   "r4   r5   r5     s&   € ÷ Qñ Q sð Q°.ð QÀTñ Qr6   c                ó>  € V'       g   R# \        4       p \        V\        \        P                  \
        3R7      ;'       g    / pRVR\        P                  ! 4       /W0&   \        W#^R7       R#   \         d"   p\        P                  RT4        Rp?R# Rp?ii ; i)zsMerge ``data`` into the per-base disk map atomically; failures are debug-logged (the in-process
cache still works).Nr3  r^   r4  ©Úindentz3nous recommended-models disk cache write failed: %s)
r/  r_   r6  rL   r7  r8  r¡   ri   r¯   r°   )r1  r^   rT   r:  r²   s   &&   r4   Ú_write_nous_recommended_diskrB    s   € ÷ ÙÜ&Ó(€DðQÜ ¬g´t×7KÑ7KÔM_Ð-`Ôa×gÐgÐegˆØ˜d D¬$¯)ª)«+Ð6ˆ‰
Ü˜$¨Q×/øÜô QÜ�‰ÐJÈC×PÒPûðQús   –,A0 Á+A0 Á0BÁ;BÂBç      @c               ó(   € V ^8„  d   QhRRRRRRRR/# )	r.   rÛ   r=   r0   r1   rÜ   r�   r@   r>  r2   )r3   s   "r4   r5   r5   �  s,   € ÷ "ñ "Øð"Ø(-ð"ØGKð"àñ"r6   c               ó~  € T ;'       g    RP                  R4      p\        P                  ! 4       p\        4       V3p\        P                  V4      pV'       g&   Ve"   WF^,          ,
          \        8  d
   V^ ,          # \        V4      pV'       g9   Ve5   ^ V^,          u;8:  d   \        8  d   M MVw  r‰W„V	,
          3\        V&   V#  \        V \         2VRRRR/R7      p\        V\        4      '       g   / pT'       d   \        Y84       MTe
   T^ ,          MTpY„3\        T&   T#   \         d    / p L>i ; i)a;  Fetch the Portal's public ``/api/nous/recommended-models`` payload (no auth).

Reuse successful results for ``_NOUS_RECOMMENDED_CACHE_TTL`` seconds, including across
process restarts. ``force_refresh`` bypasses both caches. Stale disk data remains a fallback
on live failure; reading it never renews its freshness.
úhttps://portal.nousresearch.comÚ/ÚAcceptúapplication/jsonzAccept-EncodingrB   ©r0   r9   )Úrstripr¡   r  r  r,  rI   r+  r<  rQ   ÚNOUS_RECOMMENDED_MODELS_PATHr[   r\   r®   rB  )
rÛ   r0   rÜ   r1  r&  Ú	cache_keyr  Údiskr^   r;  s
   &&$       r4   râ   râ   �  s-  € ð ×@Ð@Ð@×HÑHÈÓM€DÜ
�.Š.Ó
€CÜ%Ó'¨Ð.€IÜ$×(Ñ(¨Ó3€Fß˜VÒ/°CÀ½)µOÔFaÔ4aØ�a�yÐÜ& tÓ,€Dß˜TÒ-°!°t¸AµwÖ2\ÔA\×2\Ø‰	ˆØ.2¸#µIÐ->Ô 	Ñ*ØˆðÜØˆfÔ1Ð2Ð3¸WØÐ1Ð3DÀfÐMô
ˆô ˜$¤×%Ò%ØˆD÷ Ü$ TÕ0àÒ*ˆt�AŽw°ˆØ*.¨Ô˜IÑ&Ø€Køô ô ØŠðús   Ã2D, Ä,D<Ä;D<c               ó   € V ^8„  d   QhRR/# r  r2   )r3   s   "r4   r5   r5   ²  s   € ÷ 	1ñ 	1 #ñ 	1r6   c                 ó  €  ^ RI Hp Hp V! R4      ;'       g    / p\        VP	                  R4      ;'       g    R4      P                  4       pT;'       g    \        V 4      P                  R4      #   \         d     R# i ; i)zEBest-effort lookup of the Portal base URL the user is authed against.)ÚDEFAULT_NOUS_PORTAL_URLÚget_provider_auth_stateÚnousrÛ   rC   rG  rF  )Úhermes_cli.authrQ  rR  r=   rI   ÚstriprK  r®   )rQ  rR  ÚstateÚportals       r4   Ú_resolve_nous_portal_urlrX  ²  sr   € ð1ßTá'¨Ó/×5Ð5°2ˆÜ�U—Y‘YÐ0Ó1×7Ð7°RÓ8×>Ñ>Ó@ˆØ×6Ð6œ#Ð5Ó6×>Ñ>¸sÓCÐCøÜô 1Ú0ð1ús!   ‚A2 ™A2 ¹A2 ÁA2 Á2BÂ Bc               ó    € V ^8„  d   QhRRRR/# )r.   rÂ   r   r@   úOptional[str]r2   )r3   s   "r4   r5   r5   ¾  s   € ÷ ^ñ ^˜sð ^ }ñ ^r6   c                óÐ   € \        V \        4      '       d   V P                  R4      MRp\        V\        4      '       d'   VP	                  4       '       d   VP	                  4       # R# )zGPull the ``modelName`` field from a recommended-model entry, else None.Ú	modelNameN)r[   r\   rI   r=   rU  )rÂ   Ú
model_names   & r4   rã   rã   ¾  sM   € ä+5°e¼T×+BÒ+B�—‘˜;Ô'È€JÜ!+¨J¼×!<Ò!<À×AQÑAQ×ASÒASˆ:×ÑÓÐ]ÐY]Ð]r6   ÚvisionrÓ   rÛ   c          
     ó,   € V ^8„  d   QhRRRRRRRRRR	/# )
r.   r^  r�   rÓ   r  rÛ   r=   rÜ   r@   rZ  r2   )r3   s   "r4   r5   r5   Ä  s;   € ÷ sñ sØðsØ(6ðsØPSðsàðsà$1ñsr6   c                ó   aaa€ T;'       g    \        4       p\        WCR7      oS'       g   R# Vf    \        4       pV '       d   RMRoV'       d   RMRp\	        VVV3R lV 4       R4      #   \         d    Rp L?i ; i)	u¾   The Portal's recommended model for an auxiliary task: free tier â†’ free pick only; paid tier â†’
paid pick, falling back to the free one when the Portal returned ``null`` (staged rollouts).rà   NFÚVisionÚ
Compactionc           	   3  ó|   <"  € T F1  p\        SP                  V R S R24      4      ;o'       g   K-  Sx € K3  	  R# 5i)ÚRecommendedÚModelN)rã   rI   )r¼   ÚtÚkindÚnræ   s   & €€€r4   r½   Ú1get_nous_recommended_aux_model.<locals>.<genexpr>Ô  s=   øé € Ðk™E�qÔ+>¸w¿{¹{ÈaÈSÐP[Ð\`Ð[aÐafÐKgÓ?hÓ+iÐ&i aÓ&i—’›Eùs   ƒ*<²
<)Úfree)r  rj  )rX  râ   r*  r®   Únext)	r^  rÓ   rÛ   rÜ   r1  Útiersrg  rh  ræ   s	   $$$$  @@@r4   Úget_nous_recommended_aux_modelrm  Ä  sx   ú€ ð
 ×8Ð8Ô6Ó8€DÜ+¨DÔN€GßÙØÒð	Ü,Ó.ˆI÷ ‰8 <€Dß"‰IÐ(8€EÜÖk™EÓkÐmqÓrÐrøô	 ô 	ØŠIð	ús   ³
A- Á-A=Á<A=Ú
openrouterc               ó    € V ^8„  d   QhRRRR/# ©r.   Úproviderr=   r@   r2   )r3   s   "r4   r5   r5   ×  s   € ÷ 
*ñ 
*°ð 
*Èñ 
*r6   c                ón   €  ^ RI Hp V! V 4      pV'       d   V#  \        #   \         d	     \        # i ; i)u«   Silent-default model id: the cached remote catalog's ``"default": true`` label (never hits the
network â€” safe on hot paths), else :data:`PREFERRED_SILENT_DEFAULT_MODEL`.)Úget_default_model_from_cache)r�   rs  r®   r   )rq  rs  Úlabeleds   &  r4   Ú"get_preferred_silent_default_modelru  ×  sC   € ðÝIÙ.¨xÓ8ˆßØˆNð ô *Ð)øô ô ØÜ)Ð)ðús   ‚! ˜! ¡4³4c               ó    € V ^8„  d   QhRRRR/# ©r.   rÉ   rZ  r@   r�   r2   )r3   s   "r4   r5   r5   ä  s   € ÷ 3ñ 3¨-ð 3¸Dñ 3r6   c                óà   € \        \        T ;'       g    R4      4      pVP                  R4      ^ ,          P                  4       pVP	                  R4      '       g   R# RV9   ;'       g    RV9   # )uh  Return True for Anthropic frontier-tier models (Opus + Fable).

Both tiers are the priciest Anthropic offerings and are unsafe defaults
for a freshly-authenticated provider picker or any other silent fallback:
paid users landing on a frontier tier have no opportunity to opt out
before the choice pins their main model and inherits into every cron job
that doesn't override ``model.provider``.

Anchored on the ``claude-`` family prefix, then the ``opus-`` / ``fable-``
tier token (after vendor-strip and lowercase normalization), so the
predicate survives future Anthropic releases (``claude-opus-5-0``,
``claude-fable-6``, etc.) and rejects community / distill models whose
slug merely *contains* the substring ``opus`` (e.g. ``qwopus3.6-27b-coder``).
Sonnet and Haiku are deliberately NOT classified as frontier here â€” they
remain reasonable auto-default candidates.
rC   Ú:úclaude-Fzopus-zfable-)Ú_strip_vendor_prefixr=   ÚsplitrJ   Ú
startswith)rÉ   Úrawr1  s   &  r4   Ú_is_anthropic_frontier_tierr  ä  s]   € ô" œs 8§> >¨rÓ2Ó
3€CØ�9‰9�S‹>˜!Õ×"Ñ"Ó$€DØ�?‰?˜9×%Ò%ÙØ�t‰O×2Ð2 ¨TÑ!1Ð2r6   c               ó$   € V ^8„  d   QhRRRRRR/# )r.   rÒ   rq   rq  r=   r@   r2   )r3   s   "r4   r5   r5   ü  s"   € ÷  ñ  ¨ð  ¸cð  ÐUXñ  r6   c                óÂ   € V '       g   R# \        V4      pW 9   d   V# V  Uu. uF  p\        V4      '       d   K  VNK  	  ppV'       d
   V^ ,          # V ^ ,          # u upi )uS  Pick a cost-safe silent default from an available-models list.

Shared policy for every surface that must choose a model on the user's
behalf without an interactive confirmation (GUI onboarding
recommended-default, empty-model runtime fallback, provider-set-but-
model-missing resolution):

1. If the catalog-labeled preferred default (see
   :func:`get_preferred_silent_default_model`) is present in
   ``model_ids``, return it.
2. Else, return the first entry that is NOT an Anthropic frontier tier
   (Opus / Fable â€” see :func:`_is_anthropic_frontier_tier`). Catalog
   ordering is preserved, so a freshly-released cheaper model still
   wins over a leftover Sonnet.
3. Else (every entry is a frontier tier), return ``model_ids[0]`` so the
   picker is never empty â€” defensive last resort only.
4. Else (empty list), return ``""``.

This hardened fallback closes the hole where a Portal-augmented list
that didn't carry the catalog label fell through to ``model_ids[0]``
(currently ``anthropic/claude-fable-5``) and billed the most expensive
Anthropic flagship for traffic the user never opted into.
rC   )ru  r  )rÒ   rq  Ú	preferredrÕ   Únon_frontiers   &&   r4   Úpick_silent_default_modelr„  ü  s\   € ÷0 ÙÜ2°8Ó<€IØÔØÐÙ#,ÓU¡9˜CÔ4OÐPS×4T—C�C¡9€LÐUßØ˜A�ÐØ�Q�<Ðùò Vs
   ¢AºAc               ó   € V ^8„  d   QhRR/# ©r.   r@   r>  r2   )r3   s   "r4   r5   r5     s   € ÷ *ñ *¨ñ *r6   c                 óº  € ^ RI Hp Hp ^ RIHp \        4       pVP                  R4      ;'       g    / p\        RR7      p V! R4      ;'       g    / P                  RR4      ;'       g    RpVP                  4       pV'       d   \        M\        pV! W4V4      w  r4VP                  W7RR7      pV'       dN   \        W4RR	7      w  r9V U
u. uF'  p
\        VP                  V
4      4      '       d   K%  V
NK)  	  up
;'       g    TpV'       d   RMV P!                  W44      pR
RRT;'       g    \#        VRR7      R\%        V4      /#   \         d    Rp Lçi ; iu up
i )ak  The model a Nous account lands on without choosing one, honouring the account's tier.

Curated catalog plus the Portal's recommendations for the tier, narrowed to the org's policy,
then (free tier) to the rows the tier may select, then :func:`pick_silent_default_model`.
Contacts the Portal for a fresh tier read, so never call it on a hot path. Returns
``{"provider": "nous", "model": str, "free_tier": bool}``; ``model`` may be ``""`` when nothing
is selectable (callers degrade). Shared by ``GET /api/model/recommended-default`` and the
sign-in completion in ``hermes_cli.anon_auth`` so both land on the same model.
)Úmodel_picker_usageÚmodels_pricing)rR  rS  Tr#  rÛ   rC   )Úrescue_empty)rÓ   rq  Úmodel©rq  rÓ   )Ú
hermes_clirˆ  r‰  rT  rR  Úget_curated_nous_model_idsÚget_pricing_for_providerr*  rI   r®   Únous_policy_allowed_idsrô   rø   Úrestrict_to_nous_policyr×   rÇ   Úwindow_plan_defaultr„  r�   )rˆ  ÚmprR  rÒ   r¶   rÓ   Ú
portal_urlÚpolicy_allowedÚunionÚ_unavailablerÕ   r‹  s               r4   Úrecommended_nous_default_modelr˜    sE  € ÷ DÝ7Ü*Ó,€IØ×)Ñ)¨&Ó1×7Ð7°R€GÜ$°Ô6€IðÙ-¨fÓ5×;Ð;¸×@Ñ@ÐARÐTVÓW×]Ð]Ð[]ˆ
ð ×/Ñ/Ó1€Nß6?Õ2ÔEk€EÙ˜y°:Ó>Ñ€IØ×*Ñ*¨9ÐSWÐ*ÓX€IßÜ"?À	Ð^bÔ"cÑˆ	á$-Ó_¡I˜SÔ5LÈWÏ[É[ÐY\ÓM]×5^—S�S¡IÑ_×lÐlÐclˆ	ß‰BÐ!3×!GÑ!GÈ	Ó![€EØ˜ ¨×)gÐ)gÔ2KÈIÐ`fÔ2gØœ˜i›ð*ð *øô ô ØŠ
ðüò `s*   ÁE ÁE Á*E Ã
"EÃ1EÅEÅEc               ó    € V ^8„  d   QhRRRR/# rp  r2   )r3   s   "r4   r5   r5   @  s   € ÷ 
'ñ 
'¨Sð 
'°Sñ 
'r6   c                ó²   € \         P                  ! V . 4      pV \        9   d$   \        V 4      pV'       d   W!9   g	   V'       g   V# V'       d
   V^ ,          # R# )uŒ   Cost-safe default model for a provider, or "" â€” the NON-INTERACTIVE fallback when a provider
is configured but no model was ever selected.rC   )r   rI   r   ru  )rq  Úmodelsr‚  s   &  r4   Úget_default_model_for_providerrœ  @  sL   € ô ×!Ò! (¨BÓ/€FØÔ,Ô,Ü6°xÓ@ˆ	÷ ˜)Ô-·VØÐßˆ6�!�9Ð& BÐ&r6   c               ó    € V ^8„  d   QhRRRR/# ©r.   r¶   r   r@   r�   r2   )r3   s   "r4   r5   r5   M  s   € ÷ @ñ @ sð @¨tñ @r6   c                ó   € \        V RR4      # )rÎ   rá   rÍ   ©rÀ   ©r¶   s   &r4   Ú_openrouter_model_is_freer¢  M  s   € Ü˜Ð!9¸3Ó?Ð?r6   c               ó    € V ^8„  d   QhRRRR/# )r.   Úitemr   r@   r�   r2   )r3   s   "r4   r5   r5   Q  s   € ÷ Cñ C¨3ð C°4ñ Cr6   c                óŽ   € \        V \        4      '       d   V P                  R4      MRp\        V\        4      '       d   RV9   # R# )a9  True when ``supported_parameters`` advertises ``tools`` (hermes-agent is tool-calling-first).
Permissive when the field is absent/malformed: some OpenRouter-compatible gateways (Nous Portal,
private mirrors) don't populate it, and the picker must not silently empty for them.

Ported from Kilo-Org/kilocode#9068.
Úsupported_parametersNrþ   T©r[   r\   rI   rt   )r¤  Úparamss   & r4   Ú _openrouter_model_supports_toolsr©  Q  s=   € ô 2<¸DÄ$×1GÒ1GˆT�X‰XÐ,Ô-ÈT€FÜ *¨6´4× 8Ò 8ˆ7�fÑÐB¸dÐBr6   z*dict[str, Optional[dict[str, Any]]] | NoneÚ _openrouter_reasoning_caps_cachezfloat | NoneÚ$_openrouter_reasoning_caps_failed_atÚ_nous_reasoning_caps_cacheÚ_nous_reasoning_caps_failed_at)ÚCODEX_ASTRA_EFFORTSÚclamp_effortÚis_astra_modelc               ó$   € V ^8„  d   QhRRRRRR/# )r.   ÚeffortrZ  Úsupported_effortsúOptional[list[str]]r@   r2   )r3   s   "r4   r5   r5   m  s$   € ÷ 4ñ 4Øð4Ø.Að4ØFSñ4r6   c                ó   € \        W4      # )a   Thin wrapper over :func:`agent.reasoning_effort.clamp_effort`: keep a supported level verbatim,
else the nearest WEAKER supported level (never silently escalate cost), else the weakest; unknown
supported-sets and bespoke level names pass through unchanged.)Ú_clamp_effort)r²  r³  s   &&r4   Ú#clamp_reasoning_effort_to_supportedr·  m  s   € ô
 ˜Ó3Ð3r6   c               ó$   € V ^8„  d   QhRRRRRR/# )r.   r²  r   Ú	supportedrq   r@   r=   r2   )r3   s   "r4   r5   r5   u  s!   € ÷ 	ñ 	¨#ð 	¸)ð 	Èñ 	r6   c                óº   € \        T ;'       g    R4      P                  4       P                  4       p W9  d$   \        W4      p W9  d   RV9   d   RMV^ ,          p V # )z×Copilot/GitHub Models effort for a non-empty *supported* list: the level itself when listed,
else the nearest WEAKER listed level; bespoke names the ladder can't place fall to ``medium``
(or the first listed level).Úmedium)r=   rU  rJ   r¶  )r²  r¹  s   &&r4   Úclamp_github_reasoning_effortr¼  u  sU   € ô �×#Ð#˜8Ó$×*Ñ*Ó,×2Ñ2Ó4€FØÔÜ˜vÓ1ˆØÔ"Ø!)¨YÔ!6‘X¸IÀa½LˆFØ€Mr6   c               ó$   € V ^8„  d   QhRRRRRR/# )r.   r<   r=   r0   r1   r@   z0Optional[tuple[list, dict[str, dict[str, Any]]]]r2   )r3   s   "r4   r5   r5   �  s"   € ÷ "ñ " 3ð "°ð "ÐCsñ "r6   c                óv  €  \        WRR/VR7      pTP                  R. 4      p\        T\        4      '       g   R# T Uu/ uFY  p\        T\
        4      '       g   K  \        TP                  R4      ;'       g    R4      P                  4       ;p'       g   KW  YebK[  	  ppYG3#   \         d     R# i ; iu upi )u›   GET an OpenAI-style ``/models`` listing â†’ ``(raw data array, {id: item})``, or None when the
endpoint is unreachable or the payload has no ``data`` list.rH  rI  )r0   r9   r:   Nr^   ÚidrC   )rQ   r®   rI   r[   rt   r\   r=   rU  )r<   r0   r:   ræ   Ú
live_itemsr¤  rÕ   Ú
live_by_ids   &&&     r4   Ú_fetch_live_catalog_indexrÂ  �  sº   € ðÜ˜C¸8ÐEWÐ:XÐagÔhˆð —‘˜V RÓ(€JÜ�j¤$×'Ò'Ùá(óÙ(�d¬J°t¼T×,BŒ	ÌsÐSW×S[ÑS[Ð\`ÓSa×SgÐSgÐegÓOh×OnÑOnÓOpÐHpÈÓHpŒ	ˆŠ	™jð ð ð Ð!Ð!øô ô Úðüò
s)   ‚B$ Á B6ÁB6Á:B6ÂB6Â$B3Â2B3Ú
cache_onlyc               ó(   € V ^8„  d   QhRRRRRRRR/# )r.   r0   r1   rÜ   r�   rÃ  r@   r¬   r2   )r3   s   "r4   r5   r5   ‘  s2   € ÷ Cñ CØðCØ,0ðCØFJðCØWlñCr6   c               ó$  € ^ RI HpHp \        P                  \
        ,          pV! VR4      pVe   V'       g   \        V4      # V'       g2   \        VR7      pV'       d   V'       g   V! VRV4       \        V4      # V'       d   \        \        4      #  ^ RI	H
p V! 4       p	V	'       d   \        V	4      M\        \        4      p
\        \        V \        4      pVf   \        T;'       g    T
4      # Vw  rÍ\        \        V4      p\         f   Ve   Vs. p\#        R4      pV
 Fo  w  ppVP%                  V4      pVe   \'        V4      '       g   K.  VV8X  d   RpM$\)        VP%                  R4      4      '       d   R	MR
pVP+                  VV34       Kq  	  V'       g   \        T;'       g    T
4      # V^ ,          ^,          '       g   V^ ,          ^ ,          R3V^ &   V! VRV4       \-        V4       \        V4      #   \         d    Rp	 ELli ; i)z¾Return the curated OpenRouter picker list, refreshed from the live catalog when possible.

``cache_only`` never opens a socket: memory, then disk (stale accepted), then the in-repo snapshot.)Úprofile_slot_getÚprofile_slot_setr‹   N)r›   )Úget_curated_openrouter_modelsrn  r¹   r¶   rj  rC   Úrecommended)Úhermes_cli.models_profile_cacherÆ  rÇ  ÚsysÚmodulesÚ__name__rt   rª   r   r�   rÈ  r®   rÂ  r   r8   r    rª  ru  rI   r©  r¢  rv   r³   )r0   rÜ   rÃ  rÆ  rÇ  Ú_mer  rN  rÈ  ÚremoteÚfallbackÚliverÀ  rÁ  Úseededr    Úsilent_defaultÚpreferred_idr  Ú	live_itemÚdescs   &$$                  r4   Úfetch_openrouter_modelsr×  ‘  sÐ  € ÷ SÜ
�+‰+”hÕ
€CÙ˜cÐ#>Ó?€FàÒ§-Ü�F‹|Ð÷ Ü,¸ÔDˆßßÙ  Ð&AÀ4ÔHÜ˜“:ÐßÜÔ%Ó&Ð&ðÝJÙ.Ó0ˆ÷  &Œt�FŒ|¬4Ô0AÓ+B€Hä$Ô%<¸gÔGeÓf€DØ‚|Ü�F×&Ð&˜hÓ'Ð'Ø!Ñ€Jô "Ô"9¸:ÓF€FÜ'Ò/°FÒ4FØ+1Ð(à%'€GÜ7¸ÓE€NÛ#‰ˆ�aØ—N‘N <Ó0ˆ	àÒÔ$DÀY×$OÒ$OÙð ˜>Ô)Ø‰Dä6°y·}±}ÀYÓ7O×PÒP‘6ÐVXˆDØ�‰˜ dÐ+Ö,ñ $÷ Ü�F×&Ð&˜hÓ'Ð'Ø�1�:�a�=Œ=Ø˜a•j •m ]Ð3ˆ�‰
Ù�SÐ5°wÔ?Ü" 7Ô+Ü�‹=ÐøôK ô Ø‹ðús   ÂG> Ç>HÈHc               ó    € V ^8„  d   QhRRRR/# ©r.   rÜ   r�   r@   rq   r2   )r3   s   "r4   r5   r5   ×  s   € ÷ Tñ T ð T°ñ Tr6   c                óN   € \        V R7       UUu. uF  w  rVNK	  	  upp# u uppi )z,Return just the OpenRouter model-id strings.rà   )r×  ©rÜ   rÕ   r  s   $  r4   rÒ   rÒ   ×  ó#   € ä5ÀMÕRÔSÑR‘F�C‹CÑRÒSÐSùÓSó   �!c               ó   € V ^8„  d   QhRR/# ©r.   r@   rq   r2   )r3   s   "r4   r5   r5   Ü  s   € ÷ <ñ < Iñ <r6   c                 ó˜   €  ^ RI Hp  V ! 4       p\        T;'       g    \        P
                  ! R. 4      4      #   \         d    Rp L9i ; i)z‚Curated Nous Portal model ids: the remote catalog manifest, else the in-repo
``_PROVIDER_MODELS["nous"]`` snapshot. Always a list.)Úget_curated_nous_modelsNrS  )r�   rá  r®   rt   r   rI   )rá  rÏ  s     r4   rŽ  rŽ  Ü  sK   € ðÝDÙ(Ó*ˆô �×:Ð:Ô*×.Ò.¨v°rÓ:Ó;Ð;øô ô ØŠðús   ‚9 ¹A	ÁA	c               ó    € V ^8„  d   QhRRRR/# rž  r2   )r3   s   "r4   r5   r5   ç  s   € ÷ ;ñ ; sð ;¨tñ ;r6   c                ó   € \        V RR4      # )Úinputrá   )rä  Úoutputr   r¡  s   &r4   Ú_ai_gateway_model_is_freeræ  ç  s   € Ü˜Ð!4°cÓ:Ð:r6   c               ó$   € V ^8„  d   QhRRRRRR/# )r.   r0   r1   rÜ   r�   r@   r¬   r2   )r3   s   "r4   r5   r5   ë  s$   € ÷  ñ  Øð Ø,0ð Ø=Rñ r6   c          
     óÄ  € \         e   V'       g   \        \         4      # ^ RIHp \        \        4      p\        VP                  R4       R2V \        4      pVf   \        \         ;'       g    T4      # Vw  rVV UUu. uF9  w  ruWv9   g   K  T\        Wg,          P                  R4      4      '       d   RMR3NK;  	  pppV'       g   \        \         ;'       g    T4      # \        R VP                  4        4       R4      p	V	'       d+   V	R	3.V U
Uu. uF  w  r«W©8w  g   K  W«3NK  	  upp
,           pMV^ ,          ^ ,          R	3V^ &   Vs \        V4      # u uppi u upp
i )
zYReturn the curated AI Gateway picker list, refreshed from the live catalog when possible.N©ÚAI_GATEWAY_BASE_URLrG  r+   r¶   rj  rC   c              3  ó    "  € T FD  w  rVP                  R 4      '       g   K  \        VP                  R4      4      '       g   K@  Vx € KF  	  R# 5i)zmoonshotai/r¶   N)r}  ræ  rI   )r¼   rÕ   r¤  s   &  r4   r½   Ú*fetch_ai_gateway_models.<locals>.<genexpr>  s?   é € ð 	^Ñ0‘�Ø�N‰N˜=×)ô 
Ü.GÈÏÉÐQZÓH[×.\÷ 
ŠÓ0ùs   ‚A¢AÁ
ArÉ  )r´   rt   rg   rê  r   rÂ  rK  r8   ræ  rI   rk  r§   )r0   rÜ   rê  rÐ  rÑ  r  rÁ  Úpidr    Úfree_moonshotrÕ   rÖ  s   &$          r4   Úfetch_ai_gateway_modelsrï  ë  s[  € ô
 !Ò,·]ÜÔ-Ó.Ð.å4äÔ,Ó-€HÜ$Ð(;×(BÑ(BÀ3Ó(GÐ'HÈÐ%PÐRYÔ[yÓz€DØ‚|ÜÔ-×9Ð9°Ó:Ð:Ø�M€Añ ô5á‰FˆC #Ñ"3ô 	[ˆÔ1°*µ/×2EÑ2EÀiÓ2P×QÒQ‰fÐWYÓZÙð ñ 5÷ ÜÔ-×9Ð9°Ó:Ð:ô ñ	^˜j×.Ñ.Ô0ó 	^àó€M÷ Ø! =Ð1Ð2ÑSZÔ5sÑSZÁiÀcÐ^aÑ^r´k°s³kÑSZÒ5sÕs‰à˜a•j •m ]Ð3ˆ�‰
Ø 'ÐÜ�‹=Ðùó!5ùó 6ts   Á>
EÂ0EÄ
EÄ"Ec               ó    € V ^8„  d   QhRRRR/# rÙ  r2   )r3   s   "r4   r5   r5     s   € ÷ Tñ T¨4ð T¸Iñ Tr6   c                óN   € \        V R7       UUu. uF  w  rVNK	  	  upp# u uppi )z,Return just the AI Gateway model-id strings.rà   )rï  rÛ  s   $  r4   Úai_gateway_model_idsrò    rÜ  rÝ  Úcustomúset[str]Ú_KNOWN_PROVIDER_NAMESc               ó   € V ^8„  d   QhRR/# ©r.   r@   rô  r2   )r3   s   "r4   r5   r5     s   € ÷ ñ ¨ñ r6   c                 ó‚  a€ R0p  ^ RI Hp ^ RIHo V! 4       pVP	                  R/ 4      p\        V\        4      '       d*   V P                  V3R lVP                  4        4       4       VP	                  R. 4      p\        V\        4      '       d   V P                  V3R lV 4       4       V #   \         d     T # i ; i)z;Return routable custom-provider IDs configured by the user.ró  ©Úload_config)Úcustom_provider_slugÚ	providersc              3  óÀ   <"  € T FS  w  r\        V\        4      '       g   K  S! \        VP                  R 4      ;'       g    T4      \        V4      4      x € KU  	  R# 5i)ré   N©r[   r\   r=   rI   )r¼   rw   rÂ   rû  s   &  €r4   r½   Ú2_configured_custom_provider_ids.<locals>.<genexpr>(  sM   øé € ð WÙ):™:˜3¼jÈÔPT×>Uô UÑ+¬C°·	±	¸&Ó0A×0HÐ0HÀSÓ,IÌ3ÈsË8×TÐTÛ):ùs   ƒA¢AÁAÚcustom_providersc              3  ó¨   <"  € T FG  p\        V\        4      '       g   K  S! \        VP                  R 4      ;'       g    R4      4      x € KI  	  R# 5i)ré   rC   Nrþ  )r¼   rÂ   rû  s   & €r4   r½   rÿ  ,  sD   øé € ð sÙPVÀuÔZdÐejÔlp×ZqÔBÑ$¤S¨¯©°6Ó):×)@Ð)@¸bÓ%A×BÐBÓPVùs   ƒA A¿A)Úhermes_cli.configrú  Úhermes_cli.providersrû  rI   r[   r\   Úupdater§   rt   Ú_CONFIG_ERRORS)Úidsrú  Úconfigrü  Úlegacyrû  s        @r4   Ú_configured_custom_provider_idsr	    s¶   ø€ àˆ*€CðÝ1Ý=á“ˆØ—J‘J˜{¨BÓ/ˆ	Ü�i¤×&Ò&Ø�J‰Jô WØ)2¯©Ô):óWô Wà—‘Ð.°Ó3ˆÜ�fœd×#Ò#Ø�J‰Jô sÙPVósô sð €Jøô ô ØØ€Jðús   †:B/ ÁA,B/ Â/B>Â=B>c               ó    € V ^8„  d   QhRRRR/# )r.   rí  r=   r@   r�   r2   )r3   s   "r4   r5   r5   3  s   € ÷ ñ  3ð ¨4ñ r6   c                óH  €  ^ RI HpHp V R8X  d,   \        \	        4       ;'       g    RP                  4       4      # V R8X  d   ^ RIHp V! V! R4      4      # V! V 4      p\        VP                  R4      ;'       g    VP                  R4      4      #   \         d     R	# i ; i)
r•   )Úget_auth_statusÚhas_usable_secretró  rC   rn  )Ú_scoped_key_envÚOPENROUTER_API_KEYÚ	logged_inÚ
configuredF)
rT  r  r  r�   Ú_get_custom_base_urlrU  Úhermes_cli.model_switchr  rI   r®   )rí  r  r  r  Ústatuss   &    r4   Ú_provider_has_credentialsr  3  sŽ   € ðßFà�(Œ?ÜÔ-Ó/×5Ð5°2×<Ñ<Ó>Ó?Ð?Ø�,ÔÝ?Ù$¡_Ð5IÓ%JÓKÐKÙ  Ó%ˆÜ�F—J‘J˜{Ó+×GÐG¨v¯z©z¸,Ó/GÓHÐHøÜô Úðús'   ‚$B §B ¼B Á$B Á<B ÂB!Â B!c               ó   € V ^8„  d   QhRR/# )r.   r@   zlist[dict[str, str]]r2   )r3   s   "r4   r5   r5   B  s   € ÷ Pñ PÐ"6ñ Pr6   c                 ó~  € ^ RI Hp  / p\        P                  ! 4        F&  w  r#VP	                  V. 4      P                  V4       K(  	  V ! 4        Uu. uF  qDP                  NK  	  upR.,            Uu. uF:  pRVR\        P                  ! WU4      RVP                  V. 4      R\        V4      /NK<  	  up# u upi u upi )zh``{id, label, aliases, authenticated}`` per listed provider (shared with ``hermes model`` / ``/model``).)Úlisted_canonical_providersró  r¿  ÚlabelÚaliasesÚauthenticated)
Ú hermes_cli.models_catalog_staticr  r   r§   rä   rv   Úslugr   rI   r  )r  Úaliases_forÚaliasÚ	canonicalÚprí  s         r4   Úlist_available_providersr"  B  sÂ   € åKØ(*€KÜ-×3Ò3Ö5ÑˆØ×Ñ˜y¨"Ó-×4Ñ4°UÖ;ñ 6ñ %?Ô$@ÓAÑ$@˜q—F”FÑ$@ÑAÀXÀJÖNóPñ OˆCð	 �#ØÔ%×)Ò)¨#Ó3Ø�{—‘ s¨BÓ/ØÔ6°sÓ;ó		=ñ
 OñPð Pùò BùòPs   ÁB5Á2A B:Ú
custom_idsc               ó(   € V ^8„  d   QhRRRRRRRR/# )r.   r~  r=   Úcurrent_providerr#  zOptional[set[str]]r@   r¸   r2   )r3   s   "r4   r5   r5   Q  s,   € ÷ (ñ (Øð(Ø$'ð(Ø8Jð(ØVeñ(r6   c               ó  € V P                  4       pVP                  R4      pV^ 8”  Ed_   VRV P                  4       P                  4       pW4^,           R P                  4       pV'       Ed   V'       Ed   V\        9   Ed   VR8X  dó   Vf   \	        4       MTpVP                  4       p\        VR0,
          \        RR7       FQ  p	VP                  V	P                  4        R24      '       g   K-  W“\        V	4      ^,           R P                  4       3u # 	  RV9   d]   R VP                  R^4       4       w  r«V
'       d:   V'       d2   RV
P                  4        2V9   d   RV
P                  4        2V3# RV3# \        V4      V3# W3# )ac  Parse ``/model`` input into ``(provider, model)``. The colon is a provider delimiter only when
the left side is a known provider/alias, so ``anthropic/claude-3.5-sonnet:beta`` stays a model.
``custom_ids`` is the caller's already-loaded set of configured ``custom:<name>`` ids (default:
read from config) so one decision never consults two config sources.ry  Nró  T)rw   Úreversec              3  ó@   "  € T F  qP                  4       x € K  	  R # 5irk   )rU  )r¼   Úparts   & r4   r½   Ú$parse_model_input.<locals>.<genexpr>g  s   é € Ð0cÑJbÀ$·±·°ÓJbùs   ‚úcustom:)
rU  ÚfindrJ   rõ  r	  r	  r¥   r}  r|  Únormalize_provider)r~  r%  r#  ÚstrippedÚcolonÚprovider_partÚ
model_partr  ÚloweredÚ	custom_idÚcustom_nameÚactual_models   &&$         r4   Úparse_model_inputr6  Q  sr  € ð �y‰y‹{€HØ�M‰M˜#Ó€EØˆq…yØ   %Ð(×.Ñ.Ó0×6Ñ6Ó8ˆØ a�i˜jÐ)×/Ñ/Ó1ˆ
ßˆ=ŸZ˜Z¨MÔ=RÕ,RØ Ô(ØBLÒBTÔ<Ô>ÐZd�
à"Ÿ.™.Ó*�Ü!'¨
°h°ZÕ(?ÄSÐRV×!W�IØ×)Ñ)¨Y¯_©_Ó->Ð,?¸qÐ*A×BÔBØ(´3°y³>ÀAÕ3EÐ3GÐ*H×*NÑ*NÓ*PÐPÒPñ "Xð
 ˜*Ô$Ù0cÈ*×JZÑJZÐ[^Ð`aÔJbÓ0cÑ-�Kß"§|Ø$ [×%6Ñ%6Ó%8Ð$9Ð:¸jÔHØ&-¨k×.?Ñ.?Ó.AÐ-BÐ$CÀ\Ð#RÐRØ (¨*Ð5Ð5Ü& }Ó5°zÐBÐBØÐ'Ð'r6   c               ó   € V ^8„  d   QhRR/# r  r2   )r3   s   "r4   r5   r5   p  s   € ÷ Eñ E˜cñ Er6   c                 ód   € \        \        4       P                  RR4      4      P                  4       # )z8The custom endpoint ``model.base_url`` from config.yaml.r}   rC   )r=   Ú_get_model_config_dictrI   rU  r2   r6   r4   r  r  p  s'   € äÔ%Ó'×+Ñ+¨J¸Ó;Ó<×BÑBÓDÐDr6   c               ó    € V ^8„  d   QhRRRR/# )r.   rq  r=   r@   r>  r2   )r3   s   "r4   r5   r5   u  s   € ÷ ñ ¨ð °ñ r6   c                óŒ  € \        T ;'       g    R4      P                  4       pV'       g   / #  ^ RIHp V! 4       P	                  R/ 4      p\        V\        4      '       dQ   VP	                  V4      ;'       g     VP	                  VP                  4       4      p\        V\        4      '       d   V# / #   \         d     / # i ; i)z:Return config.yaml providers.<provider>, or an empty dict.rC   rù  rü  )	r=   rU  r  rú  rI   r[   r\   rJ   r  )rq  rw   rú  Úproviders_cfgrÂ   s   &    r4   Ú_get_provider_config_dictr=  u  s§   € ä
ˆh�nˆn˜"Ó
×
#Ñ
#Ó
%€CßØˆ	ðÝ1Ù#›×)Ñ)¨+°rÓ:ˆÜ�m¤T×*Ò*Ø!×%Ñ% cÓ*×LÐL¨m×.?Ñ.?ÀÇ	Á	ÃÓ.LˆEÜ˜%¤×&Ò&Ø�ð €Iøô ô ØØ€Iðús   ¯A
B4 Á:7B4 Â4CÃCc               ó   € V ^8„  d   QhRR/# r†  r2   )r3   s   "r4   r5   r5   †  s   € ÷ 	ñ 	 ñ 	r6   c                 ó˜   €  ^ RI Hp  V ! 4       P                  R/ 4      p\        V\        4      '       d   V#  / #   \
         d     / # i ; i)z7Return the main model config mapping, or an empty dict.rù  r‹  )r  rú  rI   r[   r\   r®   )rú  Ú	model_cfgs     r4   r9  r9  †  sV   € ðÝ1Ù“M×%Ñ% g¨rÓ2ˆ	Ü�i¤×&Ò&ØÐð 'ð €Iøô ô ØØ€Iðús   ‚4: ºA	ÁA	c               ó    € V ^8„  d   QhRRRR/# )r.   r}   r=   r@   r�   r2   )r3   s   "r4   r5   r5   ’  s   € ÷ hñ h°cð h¸dñ hr6   c                ó$  € \        T ;'       g    R 4      P                  4       P                  4       P                  R4      pV'       g   R# \        P
                  P                  V4      P                  P                  R4      P                  R4      # )rC   rG  F)z
/anthropicz/anthropic/v1)	r=   rU  rJ   rK  rD   ÚparseÚurlparserT   Úendswith)r}   Ú
normalizeds   & r4   Ú'_base_url_looks_like_anthropic_messagesrG  ’  sg   € Ü�X—^�^ Ó$×*Ñ*Ó,×2Ñ2Ó4×;Ñ;¸CÓ@€JßÙÜ�<‰<× Ñ  Ó,×1Ñ1×8Ñ8¸Ó=×FÑFÐGfÓgÐgr6   Úafter_idc               ó$   € V ^8„  d   QhRRRRRR/# )r.   r}   rZ  rH  r@   r=   r2   )r3   s   "r4   r5   r5   ™  s'   € ÷ 	Oñ 	O Mð 	OÀ}ð 	OÐ`cñ 	Or6   c               ó4  € \        T ;'       g    R4      P                  4       P                  R4      pY"P                  R4      '       d   RMR,           pRR/pV'       d   WR&   TR	V9   d   R
MR	,           \        P
                  P                  V4      ,           # )zíAnthropic ``/v1/models`` page URL. The endpoint is cursor-paginated with a default page of
20 (smaller than the live catalog), so every request asks for the maximum page size and
``after_id`` continues from a previous page's ``last_id``.zhttps://api.anthropic.comrG  ú/v1r+   z
/v1/modelsÚlimitÚ1000rH  Ú?Ú&)r=   rU  rK  rE  rD   rC  Ú	urlencode)r}   rH  Úendpointr<   r¨  s   &$   r4   Ú_anthropic_models_urlrR  ™  s�   € ô �8×:Ð:Ð:Ó;×AÑAÓC×JÑJÈ3ÓO€HØ
×#4Ñ#4°U×#;Ò#;‘iÀÕ
N€CØ�vÐ€FßØ%ˆzÑØ˜ œ‘#¨Õ-´·±×0FÑ0FÀvÓ0NÕNÐNr6   c               ó$   € V ^8„  d   QhRRRRRR/# )r.   Úpager   Úseen_cursorsrô  r@   rZ  r2   )r3   s   "r4   r5   r5   ¨  s!   € ÷ 	ñ 	 ð 	°Hð 	Àñ 	r6   c                óð   € \        V \        4      '       d   V P                  R4      RJd   R# V P                  R4      p\        V\        4      '       d   V'       d   W!9   d   R# VP	                  V4       V# )z�``last_id`` to continue from, or None when the page is final or the server repeats a
cursor (which would otherwise loop forever).Úhas_moreTNÚlast_id)r[   r\   rI   r=   ru   )rT  rU  rX  s   && r4   Ú_anthropic_next_cursorrY  ¨  s\   € ô �dœD×!Ò! T§X¡X¨jÓ%9ÀÓ%EÙØ�h‰h�yÓ!€GÜ�gœs×#Ò#¯7°gÔ6MÙØ×Ñ�WÔØ€Nr6   c               ó$   € V ^8„  d   QhRRRRRR/# )r.   rq  rZ  rÜ   r�   r@   r¬   r2   )r3   s   "r4   r5   r5   ´  s(   € ÷ %ñ %Øð%ð ð%ð ñ	%r6   c               óò   € \        V 4      pVR8X  d   \        VR7      # \        V4      pV'       d   V Uu. uF  qDR3NK  	  up# \        P                  ! V. 4      pV Uu. uF  qDR3NK  	  up# u upi u upi )zÝReturn ``(model_id, description)`` tuples for a provider's model list.

Tries to fetch the live model list from the provider's API first,
falling back to the static ``_PROVIDER_MODELS`` catalog if the API
is unreachable.
rn  rà   rC   )r-  r×  Úprovider_model_idsr   rI   )rq  rÜ   rF  rÑ  rm   r›  s   &$    r4   Úcurated_models_for_providerr]  ´  s~   € ô $ HÓ-€JØ�\Ô!Ü&°]ÔCÐCô ˜jÓ)€Dßñ "&Ó&¡˜A�B“¡Ñ&Ð&ô ×!Ò! *¨bÓ1€FÙ#Ó$™V˜�‹G™VÑ$Ð$ùò	 'ùò %s   ¶A/Á A4c               ó    € V ^8„  d   QhRRRR/# )r.   rq  r=   r@   rô  r2   )r3   s   "r4   r5   r5   Ï  s   € ÷ /ñ /˜Sð / Xñ /r6   c                óª   € T ;'       g    R P                  4       P                  4       p\        V 4      pW3 Uu0 uF  q3'       g   K  VkK  	  up# u upi ©rC   )rU  rJ   r-  )rq  rw   rF  rz   s   &   r4   Ú_provider_keysra  Ï  sJ   € Ø�>ˆ>�r×
 Ñ
 Ó
"×
(Ñ
(Ó
*€CÜ# HÓ-€JØÑ(Ó.Ñ(�!«A�AˆAÑ(Ñ.Ð.ùÒ.s   ¹	AÁAc               ó    € V ^8„  d   QhRRRR/# )r.   rq  r=   r@   ztuple[str, ...]r2   )r3   s   "r4   r5   r5   Õ  s   € ÷ cñ c cð c¨oñ cr6   c                óz   € \        \        P                  ! V . 4      4      \        P                  ! V R4      ,           # )zCActive picker models plus retired aliases recognized for detection.r2   )r¤   r   rI   r   rŒ  s   &r4   Ú_provider_catalog_namesrd  Õ  s0   € äÔ!×%Ò% h°Ó3Ó4Ô7P×7TÒ7TÐU]Ð_aÓ7bÕbÐbr6   c               ó$   € V ^8„  d   QhRRRRRR/# )r.   Ú
name_lowerr=   rü  rô  r@   r�   r2   )r3   s   "r4   r5   r5   Ú  s!   € ÷ 8ñ 8¨3ð 8¸8ð 8Èñ 8r6   c                óx   a € \         ;QJ d    V 3R  lV 4       F  '       g   K   R# 	  R# ! V 3R  lV 4       4      # )c              3  ón   <"  € T F*  p\        V4       F  pSVP                  4       8H  x € K  	  K,  	  R # 5irk   )rd  rJ   )r¼   rq  r‹  rf  s   &  €r4   r½   Ú-_model_in_provider_catalog.<locals>.<genexpr>Û  s5   øé € ð 8á!ˆHÜ,¨XÖ6ˆEð 	�e—k‘k“mÖ#á6ñ 	$Û!ùs   ƒ25TF)r  )rf  rü  s   f&r4   Ú_model_in_provider_catalogrj  Ú  s>   ø€ ß‹3ô 8á!ó8�3Œ3ð 8Š3ð 8ˆ3ô 8á!ó8ó 8ð 8r6   c               ó$   € V ^8„  d   QhRRRRRR/# )r.   rf  r=   Úcurrent_keysrô  r@   úOptional[tuple[str, str]]r2   )r3   s   "r4   r5   r5   á  s$   € ÷ ñ ØðØ#+ðØ0Iñr6   c                óR  aaa€  ^ RI Hp TP                  T 4      oSf   R# R T3R llpS\        ,          \
        ,          o. SOT3R l\         4       OT3R l\         4       OT3R l\
         4       OpT F  pT! T4      ;p'       g   K  YV3u # 	  R#   \         d     R# i ; i)zDResolve short aliases (e.g. sonnet/opus) using static catalogs only.)ÚMODEL_ALIASESNc               ó    € V ^8„  d   QhRRRR/# )r.   rq  r=   r@   rZ  r2   )r3   s   "r4   r5   Ú1_resolve_static_model_alias.<locals>.__annotate__í  s   € ÷ kñ k˜ð k ñ kr6   c                óà   <a€ V \         9   d   SP                   R SP                   2MSP                  oSP                  4       o\	        V3R l\
        P                  ! V . 4       4       R4      # )rG  c              3  ót   <"  € T F-  qP                  4       P                  S4      '       g   K)  Vx € K/  	  R # 5irk   )rJ   r}  )r¼   rm   Úprefixs   & €r4   r½   Ú>_resolve_static_model_alias.<locals>._match.<locals>.<genexpr>ð  s'   øé € ÐcÑ B˜1ÇgÁgÃi×FZÑFZÐ[a×Fb—Q’QÓ Bùs   ƒ&8®
8N)r   ÚvendorÚfamilyrJ   rk  r   rI   )rq  rt  Úidentitys   &@€r4   Ú_matchÚ+_resolve_static_model_alias.<locals>._matchí  s[   ù€ Ø;CÔG\Ô;\�H—O‘OÐ$ A h§o¡oÐ%6Ñ7Ðbj×bqÑbqˆØ—‘“ˆÜÔcÔ 0× 4Ò 4°X¸rÔ BÓcÐeiÓjÐjr6   c              3  ó8   <"  € T F  qS9  g   K  Vx € K  	  R # 5irk   r2   )r¼   r!  Úskips   & €r4   r½   Ú._resolve_static_model_alias.<locals>.<genexpr>ö  s   øé € ÐFÑ$4˜qÀ¹ŸšÓ$4ùó   ƒ�
c              3  ó8   <"  € T F  qS9   g   K  Vx € K  	  R # 5irk   r2   ©r¼   r!  rl  s   & €r4   r½   r}  ÷  s   øé € Ð	@Ñ*�°<Ñ.?�!Š!Ó*ùr~  c              3  ó8   <"  € T F  qS9   g   K  Vx € K  	  R # 5irk   r2   r€  s   & €r4   r½   r}  ø  s   øé € Ð	DÑ.�°|Ñ2C�!Š!Ó.ùr~  )r  ro  r®   rI   r   r   r   )	rf  rl  ro  ry  Ú
candidatesrq  Úmatchedrx  r|  s	   &f     @@r4   Ú_resolve_static_model_aliasr„  á  sÇ   ú€ ðÝ9ð × Ñ  Ó,€HØÒÙ÷kð kð Ô/Õ/Ô2KÕK€DðFØ	ðFÜFÕ$4ÓFðFä	@Õ*Ó	@ðFô 
EÕ.Ó	DðF€Jó ˆÙ˜XÓ&Ð&ˆ7×&Ð&ØÐ$Ò$ñ ñ øô- ô Úðús   …B ÂB&Â%B&c               ó$   € V ^8„  d   QhRRRRRR/# ©r.   r]  r=   r%  r@   rm  r2   )r3   s   "r4   r5   r5   ÿ  s)   € ÷ Gñ GØðGØ'*ðGØ/HñGr6   c                óÐ  € T ;'       g    RP                  4       pV'       g   R# VP                  4       p\        V4      p\        W44      pV'       d   V# \        P
                  ! W34      pVR9  dO   \        P
                  ! V. 4      pV\        9   d-   V'       d%   Wd9  d   T\        V4      ;'       g
    V^ ,          3# \        W44      '       d   R# \        \        W!4      R4      # )u¿   Auto-detect a provider from static catalogs only â†’ ``(provider_id, model_name)`` (the name may
be remapped by a static alias or a bare provider name), or ``None`` without a confident match.rC   N>   ró  rn  )rU  rJ   ra  r„  r   rI   r   r   rœ  rj  rk  Ú_static_catalog_matches)r]  r%  ré   rf  rl  Úalias_matchÚresolved_providerÚdefault_modelss   &&      r4   Ú detect_static_provider_for_modelrŒ  ÿ  sÏ   € ð ×Ð˜"×#Ñ#Ó%€DßÙà—‘“€JÜ!Ð"2Ó3€Lä-¨jÓG€KßØÐô *×-Ò-¨jÓEÐØÐ 8Ô8Ü)×-Ò-Ð.?ÀÓDˆØÔ 0Ô0·^ÐHYÔHmð &Ô'EÐFWÓ'X×'mÐ'mÐ\jÐklÕ\mÐnÐnô " *×;Ò;ÙäÔ'¨Ó?ÀÓFÐFr6   c               ó    € V ^8„  d   QhRRRR/# ©r.   ré   r=   r%  r2   )r3   s   "r4   r5   r5     s   € ÷ ñ  #ð ¸ñ r6   c              #  ód  "  € V P                  4       p\        V4      pVR8w  d\   VP                  R4      '       gE   \         F:  pWC9   g   V\        9   g   V\
        9   d   K!  \        W$04      '       g   K5  W@3x € K<  	  \
         F$  pWC9  g   K  \        W$04      '       g   K  W@3x € K&  	  R# 5i)a$  Yield every ``(provider_id, name)`` whose static catalog lists *name*, in ladder order.

Several first-party providers list the same slug (``gpt-5.6-luna`` on ``openai-api`` AND
``openai-codex``); the first is only a guess, so callers that gate on credentials need the
siblings too (#102775).ró  r+  N)rJ   ra  r}  r   r   r   rj  )ré   r%  rf  rl  rí  s   &&   r4   rˆ  rˆ    s—   é € ð —‘“€JÜ!Ð"2Ó3€Lð ˜8Ô#Ð,<×,GÑ,GÈ	×,RÒ,Rß#ˆCØÔ" cÔ-BÔ&BÀcÔMfÔFfÙÜ)¨*°e×<Ô<Ø�kÔ!ñ	 $÷ )ˆØÖ"Ô'AÀ*Èe×'TÔ'TØ�+Ôó )ùs   ‚9B0¼6B0Á7B0ÂB0Â%B0c               ó   € V ^8„  d   QhRR/# r÷  r2   )r3   s   "r4   r5   r5   8  s   € ÷ ñ  (ñ r6   c                 óV  €  ^ RI Hp  V ! 4       ;'       g    / P                  R4      p\        V\        4      '       g   \        4       # V Uu0 uF6  p\        V4      P                  4       P                  4       ;p'       g   K4  VkK8  	  up# u upi   \         d    \        4       u # i ; i)z›Provider ids (incl. ``custom:*``) from the user's ``providers:`` config block; empty when config
is unreadable (callers fall through to built-in catalogs).rù  rü  )
r  rú  rI   r[   r\   rå   r=   rU  rJ   r®   )rú  rü  rí  rw   s       r4   Ú_configured_provider_idsr’  8  s†   € ðÝ1á “]×(Ð( b×-Ñ-¨kÓ:ˆ	Ü˜)¤T×*Ò*Ü“5ˆLÙ(ÓN™y˜´C¸³H·N±NÓ4D×4JÑ4JÓ4LÐ-L¨SÓ-L—�™yÑNÐNùÒNøÜô Ü‹uŠðús4   ‚B –1B ÁB Á1BÂBÂB ÂB ÂB(Â'B(c               ó    € V ^8„  d   QhRRRR/# )r.   r]  r=   r@   rm  r2   )r3   s   "r4   r5   r5   F  s   € ÷ ñ ¨ð Ð1Jñ r6   c                ó&  € RV 9  d   R# V P                  R^4      w  rVP                  4       P                  4       VP                  4       r!V'       d	   V'       g   R# \        4       pV\        P
                  ! W4      3 F  pWC9   g   K  WB3u # 	  R# )a�  Route an explicit ``vendor/model`` prefix (``nous/deepseek-v4-pro``, ``ollama/qwen3.5:4b``) to
a provider the user defined in ``providers:`` (by raw name or alias) instead of the default.

``nous/deepseek-v4-pro`` or ``ollama/qwen3.5:4b`` should route to the named provider instead of falling
back to the configured default (which silently sends non-default models to the wrong endpoint, #87189).
rG  N)r|  rU  rJ   r’  r   rI   )r]  rv  r‹  r  Ú	candidates   &    r4   Ú_resolve_provider_prefixr–  F  s�   € ð �*ÔÙØ×$Ñ$ S¨!Ó,�M€FØ—L‘L“N×(Ñ(Ó*¨E¯K©K«MˆEßŸÙÜ)Ó+€Jð Ô/×3Ò3°FÓCÓDˆ	ØÖ"ØÐ%Ò%ñ Eñ r6   c               ó$   € V ^8„  d   QhRRRRRR/# r†  r2   )r3   s   "r4   r5   r5   \  s$   € ÷ +*ñ +*Øð+*Ø'*ð+*Ø/Hñ+*r6   c                ó˜  € ^ RI HpHpHp T ;'       g    RP	                  4       pV'       g   R# V! WQ4      pVe   We8w  d   W3# R# V! WQ4      '       d   R# T;'       g    RP	                  4       P                  4       R9   pRp\        WQ4       F�  p	V	f    R# V	^ ,          V8X  g   V! V	^ ,          4      '       d   V	u # \        P                  ! VP                  4       VP                  4       4      V	^ ,          8X  d   V	u # T;'       g    T	p\        P                  RWY^ ,          4       KŸ  	  V'       d   V'       d   V# \        V4      # )ub  Auto-detect the best provider for a model name: the current provider's live catalog, static
catalogs (bare provider name â†’ its default; direct catalog match), then the OpenRouter catalog,
then a configured ``vendor/`` prefix.

Never hands back a provider the user holds no credentials for: an unauthenticated guess is
skipped and the ladder continues (``None`` = stay on the current provider). Exceptions: the user
NAMED the provider (``/model nous``), or there is no current provider yet (``auto``) â€” then the
first guess is returned so the credential step fails loudly instead of silently ignoring input.)Úcurrent_provider_catalog_matchÚcurrent_provider_owns_vendorÚprovider_has_credentialsrC   Nz=Skipping auto-switch of '%s' to %s: no credentials configured>   rC   Úauto)Úhermes_cli.models_detectr™  rš  r›  rU  rJ   Ú_detection_candidatesr   rI   r¯   r°   r–  )
r]  r%  r™  rš  r›  ré   ÚservedÚno_selectionÚfirst_guessr•  s
   &&        r4   Údetect_provider_for_modelr¢  \  s.  € ÷`ñ `ð ×Ð˜"×#Ñ#Ó%€DßÙñ
 ,¨DÓC€FØÒØ-3¬^Ð Ð)ÐEÀÐEñ $ D×;Ò;Ùà$×*Ð*¨×1Ñ1Ó3×9Ñ9Ó;¸|ÑK€LØ€KÜ*¨4ÖBˆ	ØÒÚØ�Q�<Ð+Ô+Ñ/GÈ	ÐRSÍ×/UÒ/UØÒÜ× Ò  §¡£¨t¯z©z«|Ó<À	È!ÅÔLØÒØ!×.Ð. YˆÜ�‰ÐTÐVZÐfgÕ\hÖiñ C÷ ŸØÐô $ DÓ)Ð)r6   c               ó    € V ^8„  d   QhRRRR/# rŽ  r2   )r3   s   "r4   r5   r5   Š  s   € ÷ ñ  ð °sñ r6   c              #  ó`  "  € \        W4      pV'       d#   Vx € \        W4       F  pW28w  g   K  Vx € K  	  \        V P                  4       \	        V4      4      '       d   Rx € R# \        V 4      pV'       d   VR8X  d   W@8X  d   Rx € R# RV3x € \        V 4      pV'       d   Vx € R# R# 5i)z‚Yield ``(provider, model)`` guesses in ladder order; ``None`` means the current provider's own
catalog owns the name (stop, stay).Nrn  )rŒ  rˆ  rj  rJ   ra  Ú_find_openrouter_slugr–  )ré   r%  Ústatic_matchÚsiblingÚor_slugÚprefixeds   &&    r4   rž  rž  Š  s¡   é € ô 4°DÓK€LßØÒô /¨tÖFˆGØÖ&Ø”ñ Gô " $§*¡*£,´Ð?OÓ0P×QÒQØŠ
Ùô $ DÓ)€GßØ˜|Ô+°´ØŠJÙØ˜WÐ%Ò%ô (¨Ó-€HßØŒñ ùs   ‚)B.°A>B.c               ó    € V ^8„  d   QhRRRR/# )r.   r]  r=   r@   rZ  r2   )r3   s   "r4   r5   r5   ¨  s   € ÷ 	ñ 	 cð 	¨mñ 	r6   c                óÐ   a€ V P                  4       P                  4       oS'       g   R# \        4       p\        V3R lV 4       R4      ;'       g    \        V3R lV 4       R4      # )zYFull OpenRouter slug for a bare or partial model name (exact slug first, then bare part).Nc              3  óV   <"  € T F  pSVP                  4       8X  g   K  Vx € K   	  R # 5irk   )rJ   ©r¼   rÕ   rf  s   & €r4   r½   Ú(_find_openrouter_slug.<locals>.<genexpr>¯  s    øé € Ð>™S�c J°#·)±)³+Ñ$=�cŠc›Sùó   ƒ)Ÿ
)c              3  ó–   <"  € T F>  pR V9   g   K  SVP                  R ^4      ^,          P                  4       8X  g   K:  Vx € K@  	  R# 5i)rG  N)r|  rJ   r­  s   & €r4   r½   r®  °  s=   øé € Ða¡˜ s¨c¡z”°jÀCÇIÁIÈcÐSTÓDUÐVWÕDX×D^ÑD^ÓD`Ñ6`—’£ùs   ƒ	A	‘)A	¿
A	)rU  rJ   rÒ   rk  )r]  r  rf  s   & @r4   r¥  r¥  ¨  sY   ø€ à×!Ñ!Ó#×)Ñ)Ó+€JßÙÜ
‹+€CäÔ>™SÓ>ÀÓE÷ 	ið 	iÜÔa¡ÓaÐcgÓhðr6   c               ó    € V ^8„  d   QhRRRR/# ©r.   rq  rZ  r@   r=   r2   )r3   s   "r4   r5   r5   ´  s   € ÷ 9ñ 9 ð 9°3ñ 9r6   c                ó~   € T ;'       g    RP                  4       P                  4       p\        P                  ! W4      # )u•   Normalize provider aliases to canonical ids. ``"auto"`` passes through â€” use
``hermes_cli.auth.resolve_provider()`` to resolve it from credentials.rn  )rU  rJ   r   rI   )rq  rF  s   & r4   r-  r-  ´  s4   € ð ×*Ð*˜l×1Ñ1Ó3×9Ñ9Ó;€JÜ× Ò  Ó8Ð8r6   c               ó    € V ^8„  d   QhRRRR/# r²  r2   )r3   s   "r4   r5   r5   »  s   € ÷ Fñ F˜]ð F¨sñ Fr6   c                ó¾   € T ;'       g    RP                  4       pVP                  4       pVR8X  d   R# \        V4      p\        P                  ! Y!;'       g    R4      # )z9Return a human-friendly label for a provider id or alias.rn  rœ  ÚAutoÚ
OpenRouter)rU  rJ   r-  r   rI   )rq  r   rF  s   &  r4   Úprovider_labelr¸  »  sR   € à×(Ð(˜L×/Ñ/Ó1€HØ—‘Ó!€JØ�VÔÙÜ# JÓ/€JÜ×Ò 
×,DÐ,D¸ÓEÐEr6   c               ó    € V ^8„  d   QhRRRR/# rw  r2   )r3   s   "r4   r5   r5   Å  s   € ÷ eñ e Mð e°dñ er6   c                óæ   € \        \        T ;'       g    R4      4      P                  R4      ^ ,          p\        V4      ;'       d,    RV9  ;'       d    VP	                  \        \        4      4      # )u„   OpenAI flagship eligible for Priority Processing. Codex-series excluded â€” the Codex Responses
API doesn't accept ``service_tier``.rC   ry  Úcodex)r{  r=   r|  r�   r}  r¤   r   )rÉ   r1  s   & r4   Ú_is_openai_fast_modelr¼  Å  sW   € ô  ¤ H§N N°Ó 3Ó4×:Ñ:¸3Ó?ÀÕB€DÜ�‹:×dÐd˜'¨Ñ-×dÐd°$·/±/Ä%ÔHbÓBcÓ2dÐdr6   c               ó    € V ^8„  d   QhRRRR/# ©r.   rÉ   r=   r@   r2   )r3   s   "r4   r5   r5   Ì  s   € ÷ 7ñ 7 3ð 7¨3ñ 7r6   c                ó¨   € \        T ;'       g    R4      P                  4       P                  4       pRV9   d   VP                  R^4      ^,          # T# )ua   Lowercase and strip a ``vendor/`` prefix (``anthropic/claude-opus-4-6`` â†’ ``claude-opus-4-6``).rC   rG  )r=   rU  rJ   r|  )rÉ   r~  s   & r4   r{  r{  Ì  sE   € ä
ˆh�nˆn˜"Ó
×
#Ñ
#Ó
%×
+Ñ
+Ó
-€CØ#&¨#¤:ˆ3�9‰9�S˜!Ó˜QÕÐ6°3Ð6r6   c               ó    € V ^8„  d   QhRRRR/# rw  r2   )r3   s   "r4   r5   r5   Ò  s   € ÷ 3ñ 3 }ð 3¸ñ 3r6   c                ó�   € ^ RI Hp \        V 4      ;'       g/    \        V 4      ;'       g    T! \	        T ;'       g    R4      4      # )zDReturn whether Hermes should expose the /fast toggle for this model.©Úis_grok_46_familyrC   )Úagent.model_metadatarÃ  Ú_is_anthropic_fast_modelr¼  r=   )rÉ   rÃ  s   & r4   Úmodel_supports_fast_moderÆ  Ò  sC   € å6ô 	! Ó*÷ 	2ð 	2Ü  Ó*÷	2ð 	2áœS § ¨RÓ0Ó1ð3r6   c               ó    € V ^8„  d   QhRRRR/# rw  r2   )r3   s   "r4   r5   r5   Ü  s   € ÷ 2ñ 2 }ð 2¸ñ 2r6   c                ó   € ^ RI Hp V! V 4      # )u²   Accepts the Anthropic Fast Mode ``speed`` param (Opus 4.8 / Opus 5 / Opus 5.5 only) â€”
deliberately NOT a general "fast model" check. The list lives in ``agent.model_metadata``.)Úis_anthropic_fast_mode_model)rÄ  rÉ  )rÉ   rÉ  s   & r4   rÅ  rÅ  Ü  s   € õ Bá'¨Ó1Ð1r6   c               ó(   € V ^8„  d   QhRRRRRRRR/# )r.   rÉ   rZ  rq  r}   r@   r�   r2   )r3   s   "r4   r5   r5   ä  s,   € ÷ 0ñ 0Øð0Ø'4ð0Ø@Mð0ØRVñ0r6   c                ó’  € ^ RI Hp ^ RIHp \	        V 4      '       d   RR/pM.T! \        T ;'       g    R4      4      '       d   RR/pMRR	R
R	RR/pV'       d   \        V4      V9  d   R# T! \        T;'       g    R4      4      P                  ;'       g    RP                  4       pV'       * ;'       g    WeP                  4       9   # )zNOnly the first-party endpoint that bills for fast mode may receive its params.)rD  rÂ  Ú	anthropiczapi.anthropic.comrC   Úxaizapi.x.aiÚopenaizapi.openai.comú
openai-apiúopenai-codexzchatgpt.comF)
Úurllib.parserD  rÄ  rÃ  rÅ  r=   r-  ÚhostnamerJ   Úvalues)rÉ   rq  r}   rD  rÃ  ÚallowedÚhosts   &&&    r4   Ú_fast_mode_route_supportedrÖ  ä  sµ   € õ &å6ä ×)Ò)ØÐ 3Ð4‰Ù	œ3˜xŸ~˜~¨2Ó.×	/Ò	/Ø˜*Ð%‰ð Ð&ØÐ*Ø˜Mð
ˆ÷
 Ô& xÓ0¸Ô?ÙÙ”S˜Ÿ˜ RÓ(Ó)×2Ñ2×8Ð8°b×?Ñ?ÓA€DØŒ8×/Ð/�tŸ~™~Ó/Ñ/Ð/r6   c               ó    € V ^8„  d   QhRRRR/# rw  r2   )r3   s   "r4   r5   r5   û  s   € ÷ ,ñ , }ð ,¸ñ ,r6   c                ó”   € ^ RI Hp \        T! \        T ;'       g    R4      4      4      P	                  R4      ^ ,          pV\
        9   # )zXOpenAI Ultrafast (``service_tier: "ultrafast"``) is published per model, not per family.)Ú"strip_codex_context_variant_suffixrC   ry  )rÄ  rÙ  r{  r=   r|  r   )rÉ   rÙ  r1  s   &  r4   Úmodel_supports_ultrafastrÚ  û  s?   € åGäÑ BÄ3ÀxÇ~À~ÐSUÓCVÓ WÓX×^Ñ^Ð_bÓcÐdeÕf€DØÔ+Ñ+Ð+r6   rq  r}   Útierc          
     ó,   € V ^8„  d   QhRRRRRRRRRR/# )r.   rÉ   rZ  rq  r}   rÛ  r@   zdict[str, Any] | Noner2   )r3   s   "r4   r5   r5     s=   € ÷ eñ eØðeØ*7ðeØJWðeà
ðeð ñer6   c               óÞ   € \        V 4      '       g   R# V'       g	   V'       d   \        WV4      '       g   R# VR8X  d   \        V 4      '       d   RR/# R# \        V 4      '       d   RR/# RR/# )u$  Fast/priority request_overrides â€” ``{"speed": "fast"}`` (Anthropic Fast Mode) or
``{"service_tier": "priority"}`` (OpenAI / xAI Priority Processing) â€” or None if unsupported.
``tier="ultrafast"`` asks for OpenAI Ultrafast instead: ``{"service_tier": "ultrafast"}`` on an
Ultrafast model, None elsewhere (never a silent downgrade to a different paid tier).
With ``provider``/``base_url`` the route is gated too (``_fast_mode_route_supported``) so proxies
never see the params. Single fast-mode gate for ``/fast`` and ``agent.fast_mode`` windows.NÚ	ultrafastÚservice_tierÚspeedÚfastÚpriority)rÆ  rÖ  rÚ  rÅ  )rÉ   rq  r}   rÛ  s   &$$$r4   Úresolve_fast_mode_overridesrã    sk   € ô $ H×-Ò-Ùß—HÔ&@ÀÐU]×&^Ò&^ÙØˆ{ÔÜ0HÈ×0RÒ0R� Ð,Ð\ÐX\Ð\Ü 8¸× BÒ BˆG�VÐÐdÈÐYcÐHdÐdr6   c               ó   € V ^8„  d   QhRR/# r  r2   )r3   s   "r4   r5   r5     s   € ÷ ñ °Sñ r6   c                ó  € ^ RI HpHp V  Fa  p\        T;'       g    R4      P	                  4       pV'       d   V! V4      ^ ,          '       g   KE   V! V4      ^ ,          pT'       g   K_  Tu # 	  R#   \
         d     Ku  i ; i)z¤Exchange stored GitHub tokens in order; the first that validates AND exchanges wins (every
entry is tried so a later valid token survives an earlier malformed one).)Úexchange_copilot_tokenÚvalidate_copilot_tokenrC   )Úhermes_cli.copilot_authræ  rç  r=   rU  r®   )Ú
raw_tokensræ  rç  r~  Ú	api_tokens   &    r4   Ú!_first_exchangeable_copilot_tokenrë    sz   € ÷ WãˆÜ�#—)�)˜‹n×"Ñ"Ó$ˆßÑ0°Ó5°a×8Ô8Ùð	Ù.¨sÓ3°AÕ6ˆI÷ ‰9ØÒñ ñ øô	 ô 	Úð	ús   ÁA2Á2BÂ Bc               ó   € V ^8„  d   QhRR/# rß  r2   )r3   s   "r4   r5   r5   (  s   € ÷ Eñ E Iñ Er6   c                 ó<  € \         P                  P                  R4      p \         P                  P                  V 4      '       g   . # \	        V RRRR7      ;_uu_ 4       pRP                  R VP                  4       P                  4        4       4      pRRR4       XP                  4       '       d   \        P                  ! V4      M/ pVP                  R	4      p\        V\        4      '       d   \        VP                  4       4      # . #   + '       g   i     L€; i)
u©   ``copilotTokens`` from the GitHub Copilot CLI's own plaintext store (JSONC â€” strip
``//``-comment lines), written by ``copilot login`` on hosts without an OS keychain.z~/.copilot/config.jsonÚrrW   Úignore)rX   rR   Ú
c              3  ór   "  € T F-  qP                  4       P                  R 4      '       d   K)  Vx € K/  	  R# 5i)z//N)Úlstripr}  )r¼   Úlines   & r4   r½   Ú-_copilot_cli_config_tokens.<locals>.<genexpr>/  s)   é € ð [Ù3�T¿;¹;»=×;SÑ;SÐTX×;Y�DŠDÓ3ùs   ‚&7­
7NÚcopilotTokens)ÚosrT   Ú
expanduserÚisfilerY   ÚjoinrG   Ú
splitlinesrU  rL   rM   rI   r[   r\   rt   rÓ  )Ú
cli_configr]   Úraw_textr^   Útokenss        r4   Ú_copilot_cli_config_tokensrþ  (  sÏ   € ô —‘×#Ñ#Ð$<Ó=€JÜ�7‰7�>‰>˜*×%Ò%Øˆ	Ü	ˆj˜#¨¸H×	EÕ	EÈØ—9‘9ñ [ØŸW™W›Y×1Ñ1Ô3ó[ó [ˆ÷ 
Fð $,§>¡>×#3Ò#3Œ4�:Š:�hÔ¸€DØ�X‰X�oÓ&€FÜ$.¨v´t×$<Ò$<Œ4�—‘“Ó ÐDÀ"ÐD÷ 
F×	Eús   Á5DÄD	c               ó   € V ^8„  d   QhRR/# r  r2   )r3   s   "r4   r5   r5   6  s   € ÷ ñ ¨#ñ r6   c                 ó~   € R R lp R V R 3pV F  p V! 4       pT'       g   K  Tu # 	  R#   \          d     K+  i ; i)ae  Best-effort GitHub token for the Copilot catalog: env vars / ``gh auth token`` via
``resolve_api_key_provider_credentials``, then ``auth.json`` ``credential_pool.copilot[]``, then
``~/.copilot/config.json`` ``copilotTokens`` (the ACP CLI's own store). Without the latter two,
keyless users see the picker fall back to the stale curated list on a silent 401.c               ó   € V ^8„  d   QhRR/# r  r2   )r3   s   "r4   r5   Ú6_resolve_copilot_catalog_api_key.<locals>.__annotate__;  s   € ÷ oñ o˜ñ or6   c                 ó>   € ^ RI Hp  \        R V ! R4       4       4      # )r•   ©Úread_credential_poolc              3  ót   "  € T F.  p\        V\        4      '       g   K  VP                  R 4      x € K0  	  R# 5i)Úaccess_tokenNrÆ   )r¼   rÂ   s   & r4   r½   ÚH_resolve_copilot_catalog_api_key.<locals>._pool_token.<locals>.<genexpr>>  s0   é € ð 1oÙ3R¨%ÔV`ÐafÔhl×VmÔ%ˆE�I‰I�n×%Ð%Ó3Rùs   ‚8Ÿ8Úcopilot)rT  r  rë  r  s    r4   Ú_pool_tokenÚ5_resolve_copilot_catalog_api_key.<locals>._pool_token;  s(   € Ý8ä0ñ 1oÙ3GÈ	Ô3Ró1oó oð 	or6   c                 ó&   € \        R 4      ^ ,          # )r	  )Ú_api_key_credentialsr2   r6   r4   rn   Ú2_resolve_copilot_catalog_api_key.<locals>.<lambda>B  s   € Ô$ YÓ/°Ö2r6   c                 ó(   € \        \        4       4      # rk   )rë  rþ  r2   r6   r4   rn   r  D  s   € Ô1Ô2LÓ2NÔOr6   rC   )r®   )r
  ÚsourcesÚsourceÚtokens       r4   Ú _resolve_copilot_catalog_api_keyr  6  sW   € õ
oñ 	3ØÙOð€Gó
 ˆð	Ù“HˆE÷ ‰5ØŠLñ ñ øô	 ô 	Úð	ús   ”-­<»<c               ó    € V ^8„  d   QhRRRR/# r¾  r2   )r3   s   "r4   r5   r5   P  s   € ÷ ñ ˜sð  sñ r6   c                ó”   € \        V 4      P                  4       P                  4       p ^ RIHp V! V4      #   \
         d    Tu # i ; i)z³Case-insensitive dedup key folded through the picker-search alias table, so a bare live wire
id and its curated public slug (Kimi ``k3`` / ``kimi-k3``) don't both survive a merge.)Úmodel_alias_canonical)r=   rU  rJ   Úhermes_cli.model_searchr  r®   )rÉ   rw   r  s   &  r4   Ú_model_dedup_keyr  P  sF   € ô ˆh‹-×
Ñ
Ó
×
%Ñ
%Ó
'€CðÝAÙ$ SÓ)Ð)øÜô ØŠ
ðús   ©7 ·AÁAc               ó$   € V ^8„  d   QhRRRRRR/# )r.   rq  r=   r    rq   r@   r2   )r3   s   "r4   r5   r5   [  s!   € ÷ 
;ñ 
; Sð 
;°9ð 
;Àñ 
;r6   c                ó˜   €  ^ RI Hp V! V 4      pV'       g   \        V4      # \	        \	        . V4      V4      #   \         d    . p L8i ; i)zµmodels.dev entries first (their order), then curated-only extras, case-insensitively deduped
while preserving curated casing. Curated unchanged when models.dev is unreachable/empty.)Úlist_agentic_models)Úagent.models_devr  r®   rt   r{   )rq  r    r  Úmdevs   &&  r4   Ú_merge_with_models_devr  [  sM   € ðÝ8Ù" 8Ó,ˆ÷ Ü�G‹}ÐÜœ r¨4Ó0°'Ó:Ð:øô	 ô ØŠðús   ‚9 ¹A	ÁA	c               ó    € V ^8„  d   QhRRRR/# rp  r2   )r3   s   "r4   r5   r5   h  s   € ÷ 'ñ '¨ð '°ñ 'r6   c                ó  € \         P                  ! RR4      P                  4       P                  R4      pV'       d   V#  \	        4       p\        VP                  R4      ;'       g    R4      P                  4       P                  4       p\        V 4      \        V4      8H  pVR9   dT   V'       dL   \        VP                  R4      ;'       g    R4      P                  4       P                  R4      pV'       d   V# R#   \         d     R# i ; i)uì   OpenAI endpoint for model discovery, mirroring runtime precedence so discovery probes the SAME
endpoint inference uses: ``$OPENAI_BASE_URL`` â†’ config ``model.base_url`` (when the configured
provider matches) â†’ the canonical default.ÚOPENAI_BASE_URLrC   rG  rq  r}   zhttps://api.openai.com/v1©rÎ  rÏ  )
rö  ÚgetenvrU  rK  r9  r=   rI   rJ   r-  r®   )rq  Úenv_rawr@  Úcfg_providerÚsame_providerÚcfg_urls   &     r4   Ú_openai_discovery_base_urlr(  h  sÞ   € ô �iŠiÐ)¨2Ó.×4Ñ4Ó6×=Ñ=¸cÓB€GßØˆð	Ü*Ó,ˆ	Ü˜9Ÿ=™=¨Ó4×:Ð:¸Ó;×AÑAÓC×IÑIÓKˆÜ*¨8Ó4Ô8JÈ<Ó8XÑXˆØÐ3Ô3¿Ü˜)Ÿ-™-¨
Ó3×9Ð9°rÓ:×@Ñ@ÓB×IÑIÈ#ÓNˆGßØ�ñ 'øô ô ØÙ&ðús+   Á &C= Á'AC= Â0C= Ã+C= Ã9C= Ã=DÄDc               ó$   € V ^8„  d   QhRRRRRR/# ©r.   rF  r=   rÜ   r�   r@   rq   r2   )r3   s   "r4   r5   r5   |  s&   € ÷ Mñ M˜sð M°4ð M¸Iñ Mr6   c                óÒ   € ^ RI Hp Rp ^ RIHpHp V! RR7      pVP                  R4      VP                  R4      r7V! V^ 4      '       d   RpT! YsR7      #   \         d    Rp Li ; i)	r•   )Úget_codex_model_idsN)Ú_codex_access_token_is_expiringÚ!resolve_codex_runtime_credentialsT)Ú	read_onlyÚapi_keyr}   )r  r}   )Úhermes_cli.codex_modelsr,  rT  r-  r.  rI   r®   )rF  rÜ   r,  r}   r-  r.  Úcredsr  s   &&      r4   Ú_codex_catalogr3  |  sl   € Ý;ð €Hðßfá1¸DÔAˆØ!&§¡¨9Ó!5°u·y±yÀÓ7L�hÙ*¨<¸×;Ò;ØˆLñ ¨LÔLÐLøô ô ØŠðús   ŠAA ÁA&Á%A&g     Àr@g      >@z2Optional[tuple[float, float, Optional[list[str]]]]Ú_copilot_acp_session_memoc               ó    € V ^8„  d   QhRRRR/# )r.   rÜ   r�   r@   r´  r2   )r3   s   "r4   r5   r5   —  s   € ÷ ñ ¨tð Ð8Kñ r6   c                ój  € \         P                  ! 4       p\        pV '       g)   Ve%   W^ ,          ,
          V^,          8  d
   V^,          # ^ RIHp  V! R4      P                  4       ;'       g    RpY'       d   \        M\        V3sV#   \         d    \        P                  RRR7       Rp L>i ; i)u  Enabled models from a signed-in ``copilot --acp`` session, memoized for a few minutes â€”
successes AND failures. Model-switch validation (``models_validate._static_catalog``) reads
this uncached on every ``/model`` switch, and each miss is a CLI spawn + handshake (up to the
probe timeout), so without the memo every switch paid a subprocess. A failed probe is
memoized much more briefly so a user who signs in to the CLI right after a miss is picked up
on the next switch (or immediately via ``/model --refresh``, which clears this memo).N©Úget_provider_profileúcopilot-acpz*copilot-acp session model discovery failedT©Úexc_info)r¡   r  r4  rü  r8  Úfetch_modelsr®   r¯   r°   Ú_COPILOT_ACP_SESSION_MEMO_TTLÚ_COPILOT_ACP_SESSION_FAIL_TTL)rÜ   r&  Úmemor8  rÑ  s   &    r4   Ú_copilot_acp_session_modelsr@  —  sœ   € ô �.Š.Ó
€CÜ$€Dß˜TÒ-°#¸Q½µ-À$ÀqÅ'Ô2IØ�A�wˆÝ.ðÙ# MÓ2×?Ñ?ÓA×IÐIÀTˆð "%ÆtÕ&CÔQnÐptÐ uÐØ€Køô	 ô Ü�‰ÐAÈDˆÔQØŠðús   ÁB Á0B Â$B2Â1B2c               ó$   € V ^8„  d   QhRRRRRR/# ©r.   rF  r=   rÜ   r�   r@   r´  r2   )r3   s   "r4   r5   r5   ®  s'   € ÷ 	Fñ 	F ð 	F°Tð 	FÐ>Qñ 	Fr6   c                óÚ   € V R 8X  d   \        V4      ;p'       d   V#  \        \        4       4      pV'       d   V#  \	        \
        P                  ! R. 4      4      #   \         d     L-i ; i)r9  r	  )r@  Ú_fetch_github_modelsr  r®   r   r   rI   )rF  rÜ   rÑ  s   && r4   Ú_copilot_catalogrE  ®  sn   € Ø�]Ô"Ô0KÈMÓ0ZÐ(Z¨Ö(ZØˆðÜ#Ô$DÓ$FÓGˆßØˆKð ô !Ô!1×!5Ò!5°iÀÓ!DÓEÐEøô ô Ùðús   žA ÁA*Á)A*c               ó$   € V ^8„  d   QhRRRRRR/# rB  r2   )r3   s   "r4   r5   r5   º  s"   € ÷ 0ñ 0˜cð 0°$ð 0Ð;Nñ 0r6   c                óF  €  ^ RI Hp ^ RIHpHp V! 4       ;_uu_ 4        V! 4       pRRR4       X'       d5   V! VP                  RR4      VP                  RR4      R7      pV'       d   V# \        4       ;'       g    R#   + '       g   i     L`; i  \         d     L4i ; i)r•   )Úbackground_caller)Úfetch_nous_modelsÚ resolve_nous_runtime_credentialsNr0  rC   r}   )r0  Úinference_base_url)Úhermes_cli.anon_challengerH  rT  rI  rJ  rI   r®   rŽ  )rF  rÜ   rH  rI  rJ  r2  rÑ  s   &&     r4   Ú_nous_catalogrM  º  s„   € ð
Ý?ßWÙ× Õ Ù4Ó6ˆE÷ !çÙ$¨U¯Y©Y°yÀ"Ó-EÐZ_×ZcÑZcÐdnÐprÓZsÔtˆDßØ�ô &Ó'×/Ð/¨4Ð/÷ !× ûô ô Ùðús2   ‚B ŸA?§B ·1B Á)B Á?B	Â
B ÂB ÂB c               ó    € V ^8„  d   QhRRRR/# )r.   rF  r=   r@   r¸   r2   )r3   s   "r4   r5   r5   Ê  s   € ÷ ñ  Sð ¨_ñ r6   c                ó  €  ^ RI Hp V! V 4      p\        VP                  R4      ;'       g    R4      P	                  4       \        VP                  R4      ;'       g    R4      P	                  4       3#   \
         d    Ru # i ; i)za``(api_key, base_url)`` from ``resolve_api_key_provider_credentials``; empty strings on any miss.)Ú$resolve_api_key_provider_credentialsr0  rC   r}   ©rC   rC   )rT  rP  r=   rI   rU  r®   )rF  rP  r2  s   &  r4   r  r  Ê  sr   € ðÝHá4°ZÓ@ˆÜ�5—9‘9˜YÓ'×-Ð-¨2Ó.×4Ñ4Ó6¼¸E¿I¹IÀjÓ<Q×<WÐ<WÐUWÓ8X×8^Ñ8^Ó8`Ð`Ð`øÜô ØŠðús   ‚*A4 ­0A4 ÁA4 Á4BÂBc               ó$   € V ^8„  d   QhRRRRRR/# rB  r2   )r3   s   "r4   r5   r5   Õ  s"   € ÷ ñ  sð ¸4ð ÐDWñ r6   c                ó�   € \        V 4      w  r#V'       d	   V'       g   R#  \        W#4      ;'       g    R#   \         d     R# i ; i)zOLive /v1/models for a simple api-key provider (stepfun, gmi); None on any miss.N)r  Úfetch_api_modelsr®   )rF  rÜ   r0  r}   s   &&  r4   Ú_api_key_provider_liverU  Õ  sA   € ä,¨ZÓ8Ñ€GßŸÙðÜ Ó2×:Ð:°dÐ:øÜô Úðús   ¡6 ³6 ¶AÁAc               ó$   € V ^8„  d   QhRRRRRR/# rB  r2   )r3   s   "r4   r5   r5   à  s'   € ÷ Sñ S ð S°Tð SÐ>Qñ Sr6   c                ó¢   € \        W4      pV'       g   V# \        \        P                  ! V . 4      4      pV'       d   \	        W#\
        R7      # T# )u]  Step Plan live list merged with the curated catalog (the ``_anthropic_catalog`` pattern).

The StepFun inference endpoint is the Step Plan API, whose ``/models`` returns a subset of
the full catalog: it omits models served by the Standard API (e.g. ``step-3.7-flash``),
so a healthy live response would shadow curated-only models from every picker surface
(#41147). Live rows first, then curated-only additions â€” and when the probe declines
(no credentials / failure) ``None`` falls through to the generic profile path, whose
``merge_profile_catalog`` already serves the curated floor as a placeholder.
©rw   )rU  rt   r   rI   r{   r  )rF  rÜ   rÑ  r    s   &&  r4   Ú_stepfun_catalogrY  à  sC   € ô " *Ó<€DßØˆÜÔ#×'Ò'¨
°BÓ7Ó8€GßAHŒ=˜Ô,<Ô=ÐRÈdÐRr6   c               ó$   € V ^8„  d   QhRRRRRR/# r*  r2   )r3   s   "r4   r5   r5   ñ  s&   € ÷ Bñ B 3ð B°tð BÀ	ñ Br6   c                ó   € \        4       pR ;r4\        \        VP                  RR 4      ;'       g    R 4      4      R8X  dg   \        VP                  RR 4      ;'       g    R 4      P	                  4       p\        VP                  RR 4      ;'       g    R 4      P	                  4       p\        T;'       g    RT;'       g    RR7      p\        \        P                  ! R. 4      4      pV'       g   \        V4      # V'       d   V# \        We4      # )rC   rq  rÌ  r}   r0  N)r}   r0  )
r9  r-  r=   rI   rU  Ú_fetch_anthropic_modelsrt   r   r   r{   )rF  rÜ   r@  Úcfg_base_urlÚcfg_api_keyrÑ  r    s   &&     r4   Ú_anthropic_catalogr_  ñ  sÜ   € Ü&Ó(€IØ!#Ð#€LÜœ#˜iŸm™m¨J¸Ó;×AÐA¸rÓBÓCÀ{ÔRÜ˜9Ÿ=™=¨°RÓ8×>Ð>¸BÓ?×EÑEÓGˆÜ˜)Ÿ-™-¨	°2Ó6×<Ð<¸"Ó=×CÑCÓEˆÜ"¨L×,@Ð,@¸DÈ+×J]ÐJ]ÐY]Ô^€DÜÔ#×'Ò'¨°RÓ8Ó9€Gßô % WÓ-Ð-÷  ˆ4ÐA¤]°7Ó%AÐAr6   c               ó$   € V ^8„  d   QhRRRRRR/# rB  r2   )r3   s   "r4   r5   r5     s"   € ÷  )ñ  ) ð  )°Dð  )Ð=Pñ  )r6   c                ó.  € \         P                  ! R R4      P                  4       pV'       g   R# \        V 4      p^ RIHp  \        W#4      pV'       g   R# V! V4      '       g   V# V Uu0 uF  qfP                  4       kK  	  pp\        \        P                  ! V . 4      4      pV Uu. uF  qfP                  4       V9   g   K  VNK  	  p	pV	P                  R V 4       4       T	;'       g    T;'       g    T#   \         d    Rp L¼i ; iu upi u upi )ÚOPENAI_API_KEYrC   N)Úis_official_openai_hostc              3  óL   "  € T F  p\        V4      '       g   K  Vx € K  	  R # 5irk   )r°  ©r¼   rm   s   & r4   r½   Ú"_openai_catalog.<locals>.<genexpr>!  s   é € Ð;¡˜A¬¸×):—a’a£ùs   ‚$š
$)rö  r#  rU  r(  r  rc  rT  r®   rJ   rt   r   rI   Úextend)
rF  rÜ   r0  r1  rc  rÑ  rm   Ú
live_lowerr    Ú
discovereds
   &&        r4   Ú_openai_catalogrj    s÷   € Ü�iŠiÐ(¨"Ó-×3Ñ3Ó5€GßÙÜ% jÓ1€Dõ =ðÜ Ó.ˆ÷ ÙÙ" 4×(Ò(ØˆÙ%)Ó*¡T —'‘'–)¡T€JÐ*ÜÔ#×'Ò'¨
°BÓ7Ó8€Gñ %Ó@™W˜¯©«	°ZÑ(?—!�!™W€JÐ@ð ×ÑÑ;¡Ó;Ô;Ø×(Ð(˜×(Ð( DÐ(øô ô ØŠðüò +ùò As$   ÁC: Á+DÂ)DÃDÃ:D
Ä	D
c               ó$   € V ^8„  d   QhRRRRRR/# rB  r2   )r3   s   "r4   r5   r5   %  s'   € ÷ Jñ J ð J°Dð JÐ=Pñ Jr6   c                ó¶  € \        4       pV'       g   R # \        4       p\        VP                  RR4      ;'       g    R4      P	                  4       ;'       gV    \
        P                  ! RR4      ;'       g7    \
        P                  ! RR4      ;'       g    \
        P                  ! RR4      p\        V4      '       d   RMR p\        WBVR7      ;'       g    R # )Nr0  rC   ÚCUSTOM_API_KEYrb  r  Úanthropic_messages)Úapi_mode)	r  r9  r=   rI   rU  rö  r#  rG  rT  )rF  rÜ   r}   r@  r0  ro  s   &&    r4   Ú_custom_catalogrp  %  s»   € Ü#Ó%€HßÙÜ&Ó(€Iô 	ˆI�M‰M˜) RÓ(×.Ð.¨BÓ/×5Ñ5Ó7÷ 	/ð 	/Ü�9Š9Ð% rÓ*÷	/ð 	/ä�9Š9Ð% rÓ*÷	/ð 	/ô �9Š9Ð)¨2Ó.ð	 ô
 (OÈx×'XÒ'XÑ#Ð^b€HÜ˜G¸ÔA×IÐIÀTÐIr6   c               ó$   € V ^8„  d   QhRRRRRR/# rB  r2   )r3   s   "r4   r5   r5   4  s"   € ÷ ñ  ð °Tð Ð>Qñ r6   c                óB   €  ^ RI Hp V! 4       #   \         d     R# i ; i)r•   )Úbedrock_model_ids_or_noneN)Úagent.bedrock_adapterrs  r®   )rF  rÜ   rs  s   && r4   Ú_bedrock_catalogru  4  s%   € ðÝCá(Ó*Ð*øÜô Úðús   ‚ ��c               ó$   € V ^8„  d   QhRRRRRR/# rB  r2   )r3   s   "r4   r5   r5   >  s"   € ÷ ñ  sð ¸4ð ÐDWñ r6   c                óh  €  ^ RI Hp ^ RIHp V! V \	        4       R7      p\        VP                  R4      ;'       g    R4      P                  4       P                  R4      pVP                  R4      pV'       d	   V'       g   R# V! WV4      w  rxV'       d   V'       d   V# R#   \         d     R# i ; i)	uw  Live ``GET <base>/models`` of the configured Azure Foundry resource (#27989).

Deployments are per-resource, so the static catalog is intentionally empty and the plugin
profile ships ``base_url=""`` â€” which is why the generic profile fetch never fires. Resolve
through the runtime resolver so the picker targets the same resource inference hits
(``model.base_url`` / ``AZURE_FOUNDRY_BASE_URL``) with the same credential: an API key string,
or the Entra ID token-provider callable that ``azure_detect`` already accepts. Anthropic-style
``/anthropic`` routes serve no ``/models``; the probe never raises, so any miss keeps ``[]``.
)Ú_probe_openai_models)Ú_resolve_azure_foundry_runtime)Úrequested_providerr@  r}   rC   rG  r0  N)
Úhermes_cli.azure_detectrx  Úhermes_cli.runtime_providerry  r9  r=   rI   rU  rK  r®   )	rF  rÜ   rx  ry  Úruntimer}   Ú
credentialÚokr  s	   &&       r4   Ú_azure_foundry_catalogr€  >  s�   € ðÝ@ÝNá0ÀJÔZpÓZrÔsˆÜ�w—{‘{ :Ó.×4Ð4°"Ó5×;Ñ;Ó=×DÑDÀSÓIˆØ—[‘[ Ó+ˆ
ßŸZÙÙ& xÓ<‰ˆßŸSˆsÐ* dÐ*øÜô Úðús.   ‚:B" ½<B" Á:B" ÂB" ÂB" Â B" Â"B1Â0B1c                ó   € \        VR 7      # ©rà   )rÒ   ©rF  rÜ   s   &&r4   rn   rn   Z  s	   € ´IÈMÕ4Zr6   rÐ  r	  r9  rS  ÚstepfunÚgmirÌ  z
ai-gatewayc                ó*   € \        4       ;'       g    R # rk   )Ú_fetch_ai_gateway_modelsrƒ  s   &&r4   rn   rn   b  s   € Ô4LÓ4N×4VÐ4VÐRVÐ4Vr6   Ú	deepinfrac                ó.   € \        VR 7      ;'       g    . # r‚  )Ú_fetch_deepinfra_modelsrƒ  s   &&r4   rn   rn   e  s   € Ô3JÐYfÔ3g×3mÐ3mÐkmÐ3mr6   zollama-cloudc                ó.   € \        VR 7      ;'       g    R# )rà   N)r*   rƒ  s   &&r4   rn   rn   f  s   € Ô6OÐ^kÔ6l×6tÐ6tÐptÐ6tr6   rÎ  rÏ  Úbedrockúazure-foundryr>  Ú_PROVIDER_CATALOG_FETCHERSc               ó    € V ^8„  d   QhRRRR/# )r.   rF  r=   r@   r´  r2   )r3   s   "r4   r5   r5   w  s   € ÷ eñ e cð eÐ.Añ er6   c                ó  € ^ RI Hp V! V 4      pV'       g   R# VP                  R8X  d5    VP                  4       p\        YV'       d   \        V4      4      # R4      # VP                  R8X  d   VP                  '       g    \        VP                  4      ;'       g    R# \        V 4      w  rV\        YYV;'       g    VP                  ;'       g    R4      #   \         d#   p\
        P                  RY4       Rp Rp?LÄRp?ii ; i)a  Generic live fetch for any provider registered in providers/ with ``auth_type="api_key"``.

Live results are merged with the curated list so models the live endpoint omits still appear:
curated-first by default so the newest curated models lead when the live API lags;
``_LIVE_FIRST_PICKER_PROVIDERS`` (OpenCode Zen/Go, authoritative live API) live-first so stale
curated entries stop polluting the top. Plugin providers without a static entry use the
profile's ``fallback_models`` as the curated list (Fireworks lists an image model first).
r7  NÚexternal_processz0external_process catalog fetch failed for %s: %sr0  )rü  r8  Ú	auth_typer<  r®   r¯   r°   Úmerge_profile_catalogrt   r}   Úfallback_modelsr  Úprobe_profile_catalog)rF  r8  ÚprofilerÑ  r²   r0  r}   s   &      r4   Ú_profile_live_catalogr—  w  sâ   € õ /á" :Ó.€GßÙð
 ×ÑÐ.Ô.ð	Ø×'Ñ'Ó)ˆDô % ZÏ¼$¸t»*ÓWÐWÐRVÓWÐWØ×Ñ Ô*¨w×/?×/?Ð/?Ü�G×+Ñ+Ó,×4Ð4°Ð4Ü,¨ZÓ8Ñ€GÜ  °g×?cÐ?cÈ7×K[ÑK[×?cÐ?cÐ_cÓdÐdøô ô 	Ü�L‰LÐKÈZÔ]Ø�Dûð	ús   «C ÃDÃ"C?Ã?Dc               ó(   € V ^8„  d   QhRRRRRRRR/# )r.   rF  r=   r0  rZ  r}   r@   r´  r2   )r3   s   "r4   r5   r5   ˜  s*   € ÷ 	<ñ 	< cð 	<¸]ð 	<ÐVcð 	<Ðh{ñ 	<r6   c                óz   € RpV'       d    VP                  W#R7      p\        WV4      #   \         d    Rp Li ; i)uÇ   ``profile.fetch_models`` gated on a key (no key â†’ no doomed probe) and merged with the curated
list; a raising catalog override degrades like a None return â€” fallback_models, not an empty picker.N©r0  r}   )r<  r®   r“  )rF  r–  r0  r}   rÑ  s   &&&& r4   r•  r•  ˜  sI   € ð €Dßð	Ø×'Ñ'°Ð'ÓKˆDô ! °dÓ;Ð;øô ô 	ØŠDð	ús   Œ* ª:¹:c               ó$   € V ^8„  d   QhRRRRRR/# )r.   rF  r=   rÑ  r´  r@   r2   )r3   s   "r4   r5   r5   ¤  s#   € ÷ <ñ < cð <Ð:Mð <ÐReñ <r6   c                óh  € V'       g+   VP                   '       d   \        VP                   4      MRpMv\        \        P                  ! V . 4      4      ;'       g     \        VP                   ;'       g    R4      pV'       g   TpM$V \
        9   d   W$3MWB3w  rV\        WV\        R7      p\        W4      # )u  Combine a profile's live catalog with its curated list the way the ``/model`` picker does, so
first-time setup (``model_setup_flows._api_key_provider_model_list``) offers the same rows the
picker will later show. Empty live â†’ ``fallback_models`` (None when the profile has none).NrX  r2   )	r”  r   rt   r   rI   r   r{   r  Ú_drop_delisted_opencode_models)rF  r–  rÑ  Úrowsr    rp   rr   s   &&&    r4   r“  r“  ¤  s’   € ÷ ØAH×AX×AXÐAXÔ$ W×%<Ñ%<Ô=Ð^b‰äÔ'×+Ò+¨J¸Ó;Ó<×cÐcÄÀW×E\ÑE\×EbÐEbÐ`bÓ@cˆßØ‰Dà4>ÔB^Ô4^ $¡ÐelÐdsÑˆGÜ  Ô9IÔJˆDÜ)¨*Ó;Ð;r6   c               ó$   € V ^8„  d   QhRRRRRR/# )r.   rF  r=   rž  r´  r@   r2   )r3   s   "r4   r5   r5   ´  s#   € ÷ ñ ¨sð Ð:Mð ÐReñ r6   c                ó\   € V'       d$   V \         9   d   \        V4      ! R V 4       4      # V# )a%  The relay still LISTS delisted ids it no longer serves, and the curated floor (merged back in
as the secondary half, or served alone when there is no key) carries retired ids too. Filter the
FINAL rows for the live-first Zen/Go pickers so no path can offer a slug that 401s (#111749,
#115496).c              3  ón   "  € T F+  p\        V4      P                  4       \        9  g   K'  Vx € K-  	  R # 5irk   )r=   rJ   Ú_OPENCODE_FREE_EXCLUDED_MODELSre  s   & r4   r½   Ú1_drop_delisted_opencode_models.<locals>.<genexpr>º  s$   é € Ðb¡T ¬S°«V¯\©\«^ÔCaÑ-aŸ!š!£Tùs   ‚$5«
5)r   Útype)rF  rž  s   &&r4   r�  r�  ´  s)   € ÷
 �
Ô:Ô:Ü�DŒzÑb¡TÓbÓbÐbØ€Kr6   c                ó   € ^ RI Hp V! V 4      # )zHDrop generation ids from a chat-catalog list, keeping its list subclass.)Úwithout_generation_models)Úhermes_cli.chat_catalogr¦  )r›  r¦  s   & r4   Ú_chat_catalog_rowsr¨  ¾  s   € åAÙ$ VÓ,Ð,r6   c               ó    € V ^8„  d   QhRRRR/# rp  r2   )r3   s   "r4   r5   r5   Ä  s   € ÷ $Oñ $O¨ð $O°ñ $Or6   c                óð  €  \        4       p\        TP                  R4      ;'       g    R4      P	                  4       P                  4       pT'       d	   T '       g   R#  \        T 4      pT\        T4      8w  d   R#  \        TP                  R4      ;'       g    R4      P	                  4       P                  R4      pT'       g   R#  ^ RIH	p ^ RI
Hp \        T! T4      RR4      p\        TP                  T4      RR4      pYx3 U	u0 uF  q™'       g   K  \        T	4      kK  	  p
p	\        T4      T
9   d   R# T#   \         d     R# i ; i  \         d     R# i ; iu up	i   \         d    Tu # i ; i)a²  ``model.base_url`` when it points the *configured* provider at a relay/proxy, else "".

Discovery must probe the same endpoint inference uses (#121387): when ``model.base_url``
differs from the provider's own endpoint, the vendor's canonical host is NOT the catalog to list.
Mirrors the ``$OPENAI_BASE_URL`` -> ``model.base_url`` -> canonical precedence of
``_openai_discovery_base_url`` for every built-in provider, not just OpenAI.
rC   rq  r}   rG  ©ÚPROVIDER_REGISTRYr7  rK  )r9  r®   r=   rI   rU  rJ   r-  rK  rT  r¬  rü  r8  Úgetattrr   )rq  r@  r%  rF  r}   r¬  r8  Úprofile_urlÚregistry_urlÚur   s   &          r4   Ú_configured_relay_base_urlr±  Ä  s[  € ðÜ*Ó,ˆ	ô �y—}‘} ZÓ0×6Ð6°BÓ7×=Ñ=Ó?×EÑEÓG€LßŸxÙðÜ'¨Ó1ˆ
ØÔ+¨LÓ9Ô9Ùð :ô �9—=‘= Ó,×2Ð2°Ó3×9Ñ9Ó;×BÑBÀ3ÓG€HßÙðÝ5Ý2äÑ2°:Ó>À
ÈBÓOˆÜÐ0×4Ñ4°ZÓ@ÐBVÐXZÓ[ˆØ;FÑ:UÓ[Ñ:U°QÓYZÔ0Ô-¨aÖ0Ñ:Uˆ	Ð[ô *¨(Ó3°yÔ@ˆ2ÐNÀhÐNøô5 ô Úðûô ô Úðüò \øÜô ØŠðúsN   ‚
D< ÁE Ã	A E% Ä		E ÄE Ä&E% Ä<EÅ
EÅEÅEÅ E% Å%E5Å4E5c               ó$   € V ^8„  d   QhRRRRRR/# )r.   rF  r=   Úrelayr@   r´  r2   )r3   s   "r4   r5   r5   ë  s"   € ÷ ñ  Sð °ð Ð9Lñ r6   c                ó,  €  ^ RI Hp V! V 4      pVe   \        VRR4      R8w  d   R# \        V 4      w  rEVP	                  WAR7      pT;'       g    .  Uu. uF  qw'       g   K  \        V4      NK  	  up;'       g    R# u upi   \         d     R# i ; i)a   Live catalog probed at a configured ``model.base_url`` relay, or None to fall through.

Returns only the relay's live ids (no curated merge): a relay user must see the relay's
catalog, and a failed/empty probe degrades to the canonical fetchers untouched.
r7  Nr’  rC   r0  rš  )rü  r8  r­  r  r<  r=   r®   )rF  r³  r8  r–  r0  r  rÑ  rm   s   &&      r4   Ú_relay_model_catalogrµ  ë  s�   € ð
Ý2á& zÓ2ˆØŠ?œg g¨{¸BÓ?À9ÔLÙÜ)¨*Ó5‰
ˆØ×#Ñ#¨GÐ#ÓDˆØ!%§ ¨ Ó2¡˜1³””�A–¡Ñ2×:Ð:°dÐ:ùÒ2øÜô Úðús4   ‚$B ¨-B Á	A?Á#A?Á2	B Á<B Á?B ÂBÂBc               ó$   € V ^8„  d   QhRRRRRR/# )r.   rF  r=   Úfetcherr   r@   rq   r2   )r3   s   "r4   r5   r5   
  s&   € ÷ oñ o ð o¨cð o°iñ or6   c                ó  € Ve   \         M\        ! \        P                  ! V . 4      4      pV \        9  d   \        \        W4      4      # \        V \        W4      4      p\        V R9   d   \        V4      4      # T4      # )zëThe local, no-egress catalog tail: curated static list (+ models.dev merge where preferred).

Shared by the normal path's final fallback and by the configured-relay degrade path, which
must never reach a live vendor fetcher (#121387).
>   rÍ  ú	xai-oauth)	r   rt   r   rI   r   r¨  r�  r  r   )rF  r·  Úcurated_staticrx   s   &&  r4   Ú_static_catalogr»  
  sw   € ð  07Ò/BÕ+ÌÐLÔN^×NbÒNbÐcmÐoqÓNrÓs€NØÔ.Ô.Ü!Ô"@ÀÓ"\Ó]Ð]ä+¨JÔ8NÈzÓ8jÓk€FÜ¸zÐMaÔ?aÔ3°FÓ;ÓnÐnÐgmÓnÐnr6   c               ó$   € V ^8„  d   QhRRRRRR/# )r.   rq  rZ  rÜ   r�   r@   rq   r2   )r3   s   "r4   r5   r5   "  s"   € ÷ 0ñ 0 ð 0À$ð 0ÐS\ñ 0r6   c               ó:  € \        T ;'       g    R4      P                  4       P                  4       pVR8X  d   \        V4      # \	        V 4      p\        T ;'       g    R4      pV'       dI   V\        9  d>   \        W44      pV'       d   \        V4      # \        V\        P                  V4      4      # \        P                  V4      pVe   V! W14      pVe   \        V4      #  \        V4      pVe   \        V4      # \        W64      #   \         d    Rp L)i ; i)z»Best known model catalog for a provider: per-provider live fetchers, then the generic profile
fetch, then the static list (merged with models.dev for ``_MODELS_DEV_PREFERRED`` providers).rC   ÚollamaN)r=   rU  rJ   r'   r-  r±  Ú_RELAY_AWARE_CATALOG_FETCHERSrµ  r¨  r»  rŽ  rI   r—  r®   )rq  rÜ   Ú	requestedrF  r³  Úrelayedr·  r›  s   &$      r4   r\  r\  "  s  € ô �H—N�N Ó#×)Ñ)Ó+×1Ñ1Ó3€IØ�HÔÜ$ ]Ó3Ð3ä# HÓ-€Jô ' x§~ ~°2Ó6€Eß�Ô#@Ô@Ü& zÓ9ˆßÜ% gÓ.Ð.Ü˜zÔ+E×+IÑ+IÈ*Ó+UÓVÐVÜ(×,Ñ,¨ZÓ8€GØÒÙ˜Ó3ˆØÒÜ% fÓ-Ð-ðÜ& zÓ2ˆð ÒÜ! &Ó)Ð)ä˜:Ó/Ð/øô ô ØŠðús   Ã%D
 Ä
DÄDi  rå   Ú_swr_refresh_inflightc               ó(   € V ^8„  d   QhRRRRRRRR/# )	r.   Úfpr=   r›  rq   ÚatúOptional[float]r@   r\   r2   )r3   s   "r4   r5   r5   Z  s.   € ÷ Wñ W�Sð W )ð W°ð WÈDñ Wr6   c                óV   € RT RVf   \         P                   ! 4       MTR\        V4      /# )zROne provider row of the disk cache: credential fingerprint, write time, model ids.rÄ  rÅ  r›  )r¡   rt   )rÄ  r›  rÅ  s   &&&r4   Ú_cache_entryrÈ  Z  s%   € à�"�d¨2ª:œDŸIšIœK¸2¸xÌÈfËÐVÐVr6   c          
     ó,   € V ^8„  d   QhRRRRRRRRR	R
/# )r.   rÄ  r=   rÑ  rq   Úexistingr   rÅ  rÆ  r@   rU   r2   )r3   s   "r4   r5   r5   _  s0   € ÷ <ñ <˜3ð < ið <¸3ð <ÀOð <Ð_mñ <r6   c                ó¾   € \        V\        4      '       g   \        WV4      # \        W 4      '       d   VP	                  R4      '       g   R# / \        WV4      CRR/C# )zõRow to store for a ``provider_model_ids`` result, or ``None`` to keep *existing*: a curated
fallback never replaces the account's real catalog for the same credentials, and when it is
stored it is flagged so it expires on the short fallback TTL.rÐ  NT)r[   r   rÈ  Ú_cache_entry_validrI   )rÄ  rÑ  rÊ  rÅ  s   &&&&r4   Ú_live_result_entryrÍ  _  sT   € ô �dÔ1×2Ò2Ü˜B bÓ)Ð)Ü˜(×'Ò'°·±¸Z×0HÒ0HÙØ;Œl˜2 RÓ(Ð;¨*°dÑ;Ð;r6   c               ó   € V ^8„  d   QhRR/# )r.   r@   r�   r2   )r3   s   "r4   r5   r5   j  s   € ÷ @ñ @¨ñ @r6   c                 óš   € \        4       p \        V 4      ;'       g    Rp\        \        V 4      V4      p\        P
                  ! V4      RJ # )z¤Whether the configured local Ollama root answered the native ``/api/tags`` probe (an empty
catalog from a reachable server is authoritative; a failed probe is not).NT)r%   r&   r(   r)   r$   rI   )r}   r9   Ú	probe_keys      r4   Ú_ollama_native_probe_reachablerÑ  j  sF   € ô $Ó%€HÜ(¨Ó2×:Ð:°d€GÜ'Ô(CÀHÓ(MÈwÓW€IÜ(×,Ò,¨YÓ7¸4Ð?Ð?r6   c               ó    € V ^8„  d   QhRRRR/# )r.   rM  r=   r@   rb   r2   )r3   s   "r4   r5   r5   s  s   € ÷ %qñ %q #ð %q¸4ñ %qr6   c                ó   a aaaaa€ ^ RI HpHp V! 4       f   S MV! 4       S 3o\        ;_uu_ 4        S\        9   d    RRR4       R# \        P                  S4       RRR4       V 3R loR VV VV3R llo\        P                  ! 4       o\        P                  ! VV3R lRRS  2R	7      P                  4        R#   + '       g   i     Lh; i)
uZ  Fire-and-forget daemon refresh of *cache_key*'s cache entry, at most one in flight per key.
Failures are swallowed â€” the stale entry stays served until a later refresh succeeds.
``refresh_fn`` (no-args â†’ fresh entry dict or None) lets ``custom:<base_url>`` keys from
:func:`cached_fetch_api_models` reuse the same inflight-dedupe scaffolding.)Úget_hermes_home_overrider  Nc                 óÐ   <€ \        SR R7      p V '       g   SR8X  dI   \        4       '       d9   \        S4      p\        Y;'       g    . \	        4       P                  S4      4      # R# )Trà   r¾  N)r\  rÑ  Ú_credential_fingerprintrÍ  Ú_load_provider_models_cacherI   )rÑ  rÄ  rM  s     €r4   Ú_default_refreshÚ,_spawn_swr_refresh.<locals>._default_refresh‚  sR   ø€ Ü! )¸4Ô@ˆß�I Ô)Ô.L×.NÒ.NÜ(¨Ó3ˆBÜ% b¯*¨*°"Ô6QÓ6S×6WÑ6WÐXaÓ6bÓcÐcÙr6   c               ó   € V ^8„  d   QhRR/# ©r.   r@   rb   r2   )r3   s   "r4   r5   Ú(_spawn_swr_refresh.<locals>.__annotate__‰  s   € ÷ <ñ <�dñ <r6   c            	     ó®  <€  S;'       g    S! 4       p V '       d   \        SV 4       \        ;_uu_ 4        \
        P                  S4       RRR4       R#   \         d    \        P                  R SRR7        LSi ; i  + '       g   i     R# ; i  \        ;_uu_ 4        \
        P                  S4       RRR4       i   + '       g   i     i ; i; i)zSWR refresh failed for %sTr:  N)Ú_store_cache_entryr®   r¯   r°   Ú_swr_refresh_lockrÂ  Údiscard)rÂ   rØ  rM  Úinflight_keyÚ
refresh_fns    €€€€r4   Ú_refreshÚ$_spawn_swr_refresh.<locals>._refresh‰  sž   ø€ ð
	<Ø×3Ð3Ð#3Ð3Ó6ˆEßô # 9¨eÔ4÷ #Ö"Ü%×-Ñ-¨lÔ;÷ #Ñ"øô ô 	PÜ�L‰LÐ4°iÈ$ˆLÖOð	Pú÷ #×"Ð"û×"Ö"Ü%×-Ñ-¨lÔ;÷ #×"×"Ð"ýsK   ƒA œA ¶A?Á#A<Á9B Á;A<Á<B Á?B	ÂCÂ"C	Â8	CÃCÃCc                 ó&   <€ SP                  S 4      # rk   )Úrun)rã  Úctxs   €€r4   rn   Ú$_spawn_swr_refresh.<locals>.<lambda>˜  s   ø€  C§G¡G¨HÔ$5r6   Tzmodel-cache-swr-)ÚtargetÚdaemonré   )rg   rÔ  r  rß  rÂ  ru   ÚcontextvarsÚcopy_contextÚ	threadingÚThreadÚstart)rM  râ  rÔ  r  rØ  rã  rç  rá  s   ff  @@@@r4   Ú_spawn_swr_refreshrð  s  sž   ý€ ÷ KÙ 8Ó :Ò B‘9ÉÓIZÐ\eÐHf€Lß	Ö	ØÔ0Ô0Ø÷ 
Ñ	ô 	×!Ñ! ,Ô/÷ 
õ
÷<ó <ô ×
"Ò
"Ó
$€CÜ×ÒÕ5¸dÐK[Ð\eÐ[fÐIgÔh×nÑnÖp÷7 
×	ús   ±B=ÁB=Â=C	c               ó   € V ^8„  d   QhRR/# r“   r2   )r3   s   "r4   r5   r5   ›  s   € ÷ <ñ < Tñ <r6   c                 ó*   € ^ RI Hp  V ! 4       R,          # )r•   r–   zprovider_models_cache.jsonr™   r–   s    r4   Ú_provider_models_cache_pathró  ›  s   € Ý0ÙÓÐ;Õ;Ð;r6   c               ó    € V ^8„  d   QhRRRR/# rp  r2   )r3   s   "r4   r5   r5      s   € ÷ a<ñ a< cð a<¨cñ a<r6   c           	     óŽ  a€ ^ RI p. o ^ RIHp VP                  V 4      pVe¦   \	        VRR*4      ;'       g    R* F7  pSP                  V R\        P                  P                  VR4       24       K9  	  \	        VRR4      ;'       g    RpV'       d5   SP                  V R\        P                  P                  VR4       24        ^ RI	H
p T! T 4      pTeq   TP                  R8X  d`   . TP                  OTP                  N FA  pT'       g   K  SP                  T R\        P                  P                  TR4       24       KC  	  T R+9   d    SP                  R	\        T 4       24       T R
8X  d+    ^ RIHp SP                  R	T! \#        4       R
4       24       T R8X  Ed}   \%        R4      p	T	P                  R4      ;'       g    T	P                  R4      ;'       g    Rp
\#        4       pSR\        P                  P                  RR4       2RT	P                  RR4      ;'       g-    T	P                  RR4      ;'       g    T	P                  RR4       2RT	P                  RR4       2RT
 2.,          oT
'       d>   SP                  T
 R\        P                  P                  \'        T
4      R4       24       SRTP                  RR4       RTP                  RR4       2R\(        P*                  ! T	P                  R/ 4      R\&        R7      ,           .,          oR T3R  llpT R!8X  d!   ^ R"IHp SP                  R#T! 4        24       MU ^ R$IHp R, F  pT! Yþ! 4       T,          4       K  	  R- F+  p\        P4                  P7                  T4      pT! TT4       K-  	  R%P9                  S4      P;                  R&R'R(7      pTP=                  T^R)7      P?                  4       #   \         d     EL3i ; i  \         d     ELÂi ; i  \         d     EL¯i ; i  \         d     EL�i ; i  \         d     LÉi ; i).ag  Short hash of the credentials ``provider_model_ids(provider)`` would see right now.

API-key providers include their configured values and credential-file mtimes. Codex uses the
stable principal selected by its read-only resolver: routine token and pool-state writes must
not discard an account-scoped catalog, while a real account switch must invalidate it.
Nr«  Úapi_key_env_varsÚ=rC   Úbase_url_env_varr7  r‘  zeffective_base=r�  )Ú_config_base_url_for_providerr¾  Úkey_envÚapi_key_envzOLLAMA_HOST=ÚOLLAMA_HOSTzproviders.ollama.base_url=r}   Úapir<   zproviders.ollama.api_key=r0  zproviders.ollama.key_env=zmodel.provider=rq  z|model.base_url=zproviders.ollama.extra_headers=Úextra_headersT)Ú	sort_keysr¹   c               ó    € V ^8„  d   QhRRRR/# )r.   r  r=   r@   rb   r2   )r3   s   "r4   r5   Ú-_credential_fingerprint.<locals>.__annotate__æ  s   € ÷ ñ ˜3ð ¨ñ r6   c                óØ   <€  SP                  V  R \        P                  ! V4      P                   24       R#   \         d    SP                  T  R24        R# \
         d     R# i ; i)Ú@z@missingN)rv   rö  ÚstatÚst_mtime_nsÚFileNotFoundErrorr®   )r  rT   Úpartss   &&€r4   Ú_mtime_partÚ,_credential_fingerprint.<locals>._mtime_partæ  s[   ø€ ð	Ø�L‰L˜E˜7 !¤B§G¢G¨D£M×$=Ñ$=Ð#>Ð?Ö@øÜ ô 	-Ø�L‰L˜E˜7 (Ð+×,Üô 	Úð	ús   ƒ49 ¹A)ÁA)Á$A)Á(A)rÐ  )Ú!codex_catalog_credential_identityzcodex_identity=r–   Ú|úutf-8Úreplacer3  ©Údigest_sizer2   r"  )z	auth.jsonzcredentials.json)z~/.codex/auth.jsonz~/.claude/.credentials.jsonz#~/.config/github-copilot/hosts.jsonz~/.minimax/credentials.json) ÚhashlibrT  r¬  rI   r­  rv   rö  Úenvironr®   rü  r8  r’  Úprocess_command_env_varsÚprocess_args_env_varr(  r|  rù  r9  r=  r=   rL   Údumpsr1  r
  rg   r—   rT   r÷  rù  ÚencodeÚblake2bÚ	hexdigest)rq  r  r¬  ÚpcfgÚevÚbevr8  r–  rù  Úprovider_cfgrú  r@  r  r
  r—   ÚrelrT   r:  r  s   &                 @r4   rÖ  rÖ     s  ø€ ó à€Eð
Ý5Ø ×$Ñ$ XÓ.ˆØÒÜ˜dÐ$6¸Ó;×AÐA¸rÒA�Ø—‘ ˜t 1¤R§Z¡Z§^¡^°B¸Ó%;Ð$<Ð=Ö>ñ Bä˜$Ð 2°BÓ7×=Ð=¸2ˆCßØ—‘ ˜u A¤b§j¡j§n¡n°S¸"Ó&=Ð%>Ð?Ô@ðÝ2Ù& xÓ0ˆØÒ 7×#4Ñ#4Ð8JÔ#JØW˜×8Ñ8ÐW¸'×:VÑ:VÓW�ß‘2Ø—L‘L B 4 q¬¯©¯©¸¸BÓ)?Ð(@Ð!AÖBñ Xð Ð+Ô+ð	Ø�L‰L˜?Ô+EÀhÓ+OÐ*PÐQÔRð �?Ô"ð	ÝQØ�L‰L˜?Ñ+HÔI_ÓIaÐcrÓ+sÐ*tÐuÔvð �8ÕÜ0°Ó:ˆØ×"Ñ" 9Ó-×VÐV°×1AÑ1AÀ-Ó1P×VÐVÐTVˆÜ*Ó,ˆ	ØØœ2Ÿ:™:Ÿ>™>¨-¸Ó<Ð=Ð>Ø(Ø×Ñ 
¨BÓ/×mÐm°<×3CÑ3CÀEÈ2Ó3N×mÐmÐR^×RbÑRbÐchÐjlÓRmÐnðpà'¨×(8Ñ(8¸ÀBÓ(GÐ'HÐIØ'¨ yÐ1ð
õ 	
ˆ÷ Ø�L‰L˜G˜9 A¤b§j¡j§n¡n´S¸³\À2Ó&FÐ%GÐHÔIØØ˜iŸm™m¨J¸Ó;Ð<Ð<LÈYÏ]É]Ð[eÐgiÓMjÐLkÐlØ-Ü�jŠj˜×)Ñ)¨/¸2Ó>È$ÔX[Ô\õ]ð
õ 	
ˆ÷ð ð �>Ô!ÝMà�‰�Ñ'HÓ'JÐ&KÐLÕMð	Ý8Û8�Ù˜C Ó!2°SÕ!8Ö9ñ 9óZˆCä—7‘7×%Ñ% cÓ*ˆDÙ˜˜dÖ#ñZð
 �8‰8�E‹?×!Ñ! '°)Ð!Ó<€Dð �?‰?˜4¨Qˆ?Ó/×9Ñ9Ó;Ð;øô] ô Úðûô ô Úðûô ô 	Úð	ûô ô 	Úð	ûôN ô 	Ùð	úsr   ‰.O. ¸AO. Â

O. Â4O. Ã
AP  Ä8P  ÅP Å9)P$ Í#P6 Ï.O=Ï<O=Ð PÐPÐP!Ð P!Ð$P3Ð2P3Ð6QÑQc               ó   € V ^8„  d   QhRR/# )r.   r@   r\   r2   )r3   s   "r4   r5   r5     s   € ÷ ñ  Tñ r6   c                 ód   €  \        \        4       4      ;'       g    / #   \         d    / u # i ; i)z/Return the full cache dict, or {} on any error.)r_   ró  r®   r2   r6   r4   r×  r×    s2   € ðÜÔ ;Ó =Ó>×DÐDÀ"ÐDøÜô ØŠ	ðús   ‚ œ Ÿ/®/c               ó    € V ^8„  d   QhRRRR/# )r.   r^   r\   r@   rb   r2   )r3   s   "r4   r5   r5     s   € ÷ ñ  dð ¨tñ r6   c                óX   €  \        \        4       V RR7       R#   \         d     R# i ; i)u<   Persist the cache dict. Best-effort â€” silent on any error.Nr@  )ri   ró  r®   ©r^   s   &r4   Ú_save_provider_models_cacher"    s)   € ðÜÔ5Ó7¸Àd×KøÜô Úðús   ‚ š)¨)c               ó$   € V ^8„  d   QhRRRRRR/# )r.   rM  r=   rÂ   r\   r@   rb   r2   )r3   s   "r4   r5   r5     s&   € ÷ 
Eñ 
E #ð 
E¨dð 
E°tñ 
Er6   c                óL   a a€ ^ RI Hp R V V3R llpV! \        4       V4       R# )z½Write one row into the disk cache, re-reading it under the thread + cross-process locks: a slow
fetch worker or another process must never write back the snapshot it loaded before fetching.©Úwrite_under_cache_lockc               ó   € V ^8„  d   QhRR/# rÛ  r2   )r3   s   "r4   r5   Ú(_store_cache_entry.<locals>.__annotate__  s   € ÷ +ñ +�tñ +r6   c                 ó<   <€ \        4       p SV S&   \        V 4       R # rk   )r×  r"  )r˜   rM  rÂ   s    €€r4   Ú	write_rowÚ%_store_cache_entry.<locals>.write_row  s   ø€ Ü+Ó-ˆØ ˆˆiÑÜ# EÖ*r6   N)Úhermes_cli.models_cache_lockr&  ró  )rM  rÂ   r&  r*  s   ff  r4   rÞ  rÞ    s#   ù€ õ D÷+ñ +ñ
 Ô6Ó8¸)ÖDr6   c               ó    € V ^8„  d   QhRRRR/# r²  r2   )r3   s   "r4   r5   r5   !  s   € ÷ fñ f ]ð f°sñ fr6   c                ó´   € \        T ;'       g    R4      P                  4       P                  4       pVR8X  d   V# \        V 4      ;'       g    T ;'       g    R# )ze``ollama`` stays a raw slug (its alias would canonicalize to ``custom``); everything else normalizes.rC   r¾  )r=   rU  rJ   r-  )rq  rÀ  s   & r4   Ú_normalized_cache_slugr/  !  sN   € ä�H—N�N Ó#×)Ñ)Ó+×1Ñ1Ó3€IØ! XÔ-ˆ9ÐeÔ4FÀxÓ4P×4dÐ4dÐU]×UcÐUcÐacÐer6   c               ó$   € V ^8„  d   QhRRRRRR/# )r.   rq  rZ  r‹  r=   r@   r�   r2   )r3   s   "r4   r5   r5   '  s&   € ÷ rñ r°ð rÀcð rÈdñ rr6   c                óD   € \        V 4      R9   ;'       d    \        V4      # )zEAstra names cannot confer API/OAuth entitlement through picker state.>   rÎ  rÏ  rÐ  )r/  r°  )rq  r‹  s   &&r4   Ú!_model_requires_account_discoveryr2  '  s"   € ä! (Ó+Ð/WÑW×qÐqÔ\jÐkpÓ\qÐqr6   Úttl_secondsÚnon_blockingc          
     ó,   € V ^8„  d   QhRRRRRRRRRR	/# )
r.   rq  rZ  rÜ   r�   r3  r  r4  r@   rq   r2   )r3   s   "r4   r5   r5   ,  s4   € ÷ ?ñ ?Øð?Ø/3ð?àð?àAEð?àR[ñ?r6   c          	     ó  € \        V 4      pV'       g   . # VR8H  p\        4       p\        V4      pVP                  V4      p\        P                  ! 4       p	V'       g@   \        W‡W•VR7      p
V
e.   V
R8X  d   \        V4       \        \        VR,          4      4      # V'       d^   V'       gV   \        V4       \        W‡VR7      '       d6   \        VR,           Uu. uF  p\        WK4      '       d   K  VNK  	  up4      # . # \        WAR7      pV'       de   \        W|W‰4      pVf6   \        VR,           Uu. uF  p\        WK4      '       d   K  VNK  	  up4      # \        WM4       \        \        V4      4      # V'       d¯   \        4       '       d   \        V\        V. V	4      4       . # \!        V\"        4      ;'       d    VP                  R4      V8H  pV'       dP   \!        VP                  R4      \        4      '       d+   VR,          '       d   \        \        VR,          4      4      # . # \        W‡4      '       d6   \        VR,           Uu. uF  p\        WK4      '       d   K  VNK  	  up4      # . # u upi u upi u upi )aó  Disk-cached :func:`provider_model_ids`: fresh cache hit, else live fetch persisting a non-empty
result. Always returns a list.

``non_blocking`` marks the GUI read path (``model.options``): it NEVER waits on a provider probe.
A same-credentials row of any age is served as-is and a daemon thread warms the next open; a
cold/mismatched row returns ``[]`` so the caller keeps its curated list. One degraded provider
(hanging or timing-out ``/v1/models``) therefore delays nothing but itself (#114215).r¾  )Ú	is_ollamar3  Ústaler›  ©Úallow_emptyrà   rÄ  )r/  r×  rÖ  rI   r¡   Ú_disk_serve_tierrð  r¨  rt   rÌ  r2  r\  rÍ  rÞ  rÑ  rÈ  r[   r\   )rq  rÜ   r3  r4  rF  r7  r˜   rÄ  rÂ   r&  rÛ  r‹  rÑ  ÚfreshÚ
same_credss   &$$$           r4   Úcached_provider_model_idsr>  ,  s-  € ô (¨Ó1€JßØˆ	Ø˜hÑ&€Iä'Ó)€EÜ	  Ó	,€BØ�I‰I�jÓ!€EÜ
�)Š)‹+€CçÜ ¨3ÐQ\Ô]ˆØÒØ�wŒÜ" :Ô.Ü%¤d¨5°­?Ó&;Ó<Ð<çŸMô 	˜:Ô&Ü˜e°Y×?Ó?Ü%Ø#(¨¦?ó'MÙ#2˜%Ü8¸×K÷ �¡?ñ'Mó Nð Nð ˆ	ä˜jÔF€DßÜ" 2¨UÓ8ˆØŠ=ä%¸%À¾/ó  'G¹/°ÔQrÐs}÷  RF§u u¹/ñ  'Gó  Hð  HÜ˜:Ô-Ü!¤$ t£*Ó-Ð-çÜ)×+Ò+ä˜z¬<¸¸BÀÓ+DÔEØˆIô   ¤tÓ,×FÐF°·±¸4³ÀBÑ1Fˆ
ßœ* U§Y¡Y¨xÓ%8¼$×?Ò?ÀEÈ(ÇOÄOÜ%¤d¨5°­?Ó&;Ó<Ð<Øˆ	ô ˜%×$Ò$Ü!°e¸H¶oó  #C±o¨UÔMnÐoy÷  NB§5 5±oñ  #Có  Dð  	DØ€Iùò='Mùò 'Gùò& #Cs$   ÃI8Ã3I8Ä6I=ÅI=ÉJÉ)Jc               ó    € V ^8„  d   QhRRRR/# )r.   rq  rZ  r@   rb   r2   )r3   s   "r4   r5   r5   n  s   € ÷  ñ  ¨-ð  À4ñ  r6   c                óø   a a€  \         P                  ! 4        \        P                  ! 4        \        P                  ! 4        Rs^ RIHp \        4       oR VV 3R llpV! SV4       R#   \         d     R# i ; i)zŠDrop one provider's cache entry, or wipe the whole cache (``provider=None``). Used by
``/model --refresh`` and ``hermes model --refresh``.Nr%  c               ó   € V ^8„  d   QhRR/# rÛ  r2   )r3   s   "r4   r5   Ú1clear_provider_models_cache.<locals>.__annotate__�  s   € ÷ 		3ñ 		3˜Dñ 		3r6   c                 ó´   <€ Sf)   SP                  4       '       d   SP                  4        R # \        4       p \        S4      pW9   d   W \	        V 4       R # R # rk   )ÚexistsÚunlinkr×  r/  r"  )r˜   rF  rT   rq  s     €€r4   Ú
clear_fileÚ/clear_provider_models_cache.<locals>.clear_file�  sK   ø€ ØÒØ—;‘;—=’=Ø—K‘K”MÙÜ/Ó1ˆEÜ/°Ó9ˆJØÔ"ØÐ%Ü+¨EÖ2ñ #r6   )	r!   Úclearr#   r$   r4  r,  r&  ró  r®   )rq  r&  rF  rT   s   f  @r4   Úclear_provider_models_cacherI  n  si   ù€ ðô 	#×(Ò(Ô*Ü)×/Ò/Ô1Ü%×+Ò+Ô-ð
 %)Ð!ÝGÜ*Ó,ˆ÷		3ñ 		3ñ 	˜t ZÖ0øÜô Úðús   „A$A* Á*A9Á8A9c               ó   € V ^8„  d   QhRR/# ©r.   r@   r¸   r2   )r3   s   "r4   r5   r5   ‘  s   € ÷ ñ °_ñ r6   c                 óÐ  €  ^ RI Hp  ^ RIHp V! R4       Fº  p\	        V\
        4      '       d   VP                  R4      V 8w  d   K1  \        VP                  R4      ;'       g    R4      P                  4       pV'       g   Km  T\        VP                  R4      ;'       g    VP                  R4      ;'       g    R4      P                  4       3u # 	  R	#   \         d     R	# i ; i)
u¢   Read-only API-key pool credential for model discovery (``resolve_anthropic_token()`` ignores
``api_key`` pool entries â€” its runtime contract is OAuth-oriented).)ÚAUTH_TYPE_API_KEYr  rÌ  r’  r  rC   r}   rK  rQ  )
Úagent.credential_poolrM  rT  r  r[   r\   rI   r=   rU  r®   )rM  r  rÂ   r  s       r4   Ú+_resolve_anthropic_pool_catalog_credentialsrO  ‘  sÃ   € ðÝ;Ý8á)¨+Ö6ˆEÜ˜e¤T×*Ò*¨e¯i©i¸Ó.DÐHYÔ.YÙÜ˜Ÿ	™	 .Ó1×7Ð7°RÓ8×>Ñ>Ó@ˆEß‰uØœc %§)¡)¨JÓ"7×"`Ð"`¸5¿9¹9ÐEYÓ;Z×"`Ð"`Ð^`Óa×gÑgÓiÐiÒiñ 7ð €Møô ô ØØ€Mðús0   ‚A!C Á$C ÂC Â!C Â:C ÃC ÃC%Ã$C%r0  c               ó(   € V ^8„  d   QhRRRRRRRR/# )r.   r0   r1   r}   rZ  r0  r@   r´  r2   )r3   s   "r4   r5   r5   £  s,   € ÷ =ñ =Øð=Ø'4ð=ØFSð=àñ=r6   c               ó€  €  ^ RI HpHp TpT;'       g    RP	                  4       ;'       g    T! 4       pT'       g   \        4       w  reT'       g   R# RR/pT! T4      pT'       d.   RT 2TR&   ^ RIHp	Hp
H	p R	P                  Yš,           4      TR
&   MYgR&   \        T4      p  \        YÀTR7      pTP-                  R. 4       Uu. uF%  pTP-                  R4      '       g   K  TR,          NK'  	  pp\/        4       p\1        \2        4       FU  p\5        TT4      pTf    MD\        \        TTR7      YR7      pTP7                  R TP-                  R. 4       4       4       KW  	  \+        \8        P;                  T4      4      p\=        TR R7      #   \         d     R# i ; i  \        P                  P                   dÈ   pT'       d   TP                   R8X  g   h  TP#                  4       P%                  RR7      P'                  4       pM  \(         d    Rp Mi ; iRT9   d   RT9   g   h R	P                  X	 Uu. uF  pTX8w  g   K  TNK  	  Mu upi up\+        X
4      ,           4      TR
&   \        YÀTR7      p Rp?ELÒRp?ii ; iu upi   \(         d"   p\>        PA                  RT4        Rp?R# Rp?ii ; i)zÔSorted model ids from the Anthropic /v1/models endpoint, or None. Credentials: explicit
``api_key``, else ``resolve_anthropic_token()`` (env / OAuth / Claude Code), else a read-only
API-key credential_pool entry.)Úresolve_anthropic_tokenÚ_is_oauth_tokenNrC   úanthropic-versionú
2023-06-01úBearer ÚAuthorization)Ú_COMMON_BETASÚ_OAUTH_ONLY_BETASÚ_CONTEXT_1M_BETAÚ,zanthropic-betaú	x-api-keyrJ  i�  rï  r3  zlong context betaznot yet availabler^   r¿  )rH  c              3  ód   "  € T F&  qP                  R 4      '       g   K  VR ,          x € K(  	  R# 5i©r¿  Nr  re  s   & r4   r½   Ú*_fetch_anthropic_models.<locals>.<genexpr>Ú  s"   é € ÐOÑ+? aÇ5Á5ÈÇ;œ'˜!˜DŸ'š'Ó+?ùs   ‚0Ÿ0c                ó    € R V 9  RV 9  RV 9  V 3# )ÚopusÚsonnetÚhaikur2   rl   s   &r4   rn   Ú)_fetch_anthropic_models.<locals>.<lambda>Ý  s   € ¨V¸1©_¸hÈaÑ>OÐQXÐ`aÑQaÐcdÑ,er6   rX  z$Failed to fetch Anthropic models: %s)!Úagent.anthropic_credentialsrR  rS  ÚImportErrorrU  rO  Úagent.anthropic_adapterrX  rY  rZ  rù  rR  rQ   rD   ÚerrorÚ	HTTPErrorÚcoderG   rN   rJ   r®   rt   rI   rå   ÚrangeÚ_ANTHROPIC_MODELS_MAX_PAGESrY  rg  r\   Úfromkeysr	  r¯   r°   )r0   r}   r0  rR  rS  Úresolved_base_urlr  r9   Úis_oauthrX  rY  rZ  r<   r^   Úhttp_errÚ	body_textÚbrm   r›  rU  Ú_pageÚcursorÚes   &$$                    r4   r\  r\  £  st  € ðßXð !ÐØ�]ˆ]˜×!Ñ!Ó#×@Ð@Ñ'>Ó'@€Eßô $OÓ#PÑ ˆßÙà2°LÐA€GÙ˜uÓ%€HßØ%,¨U¨GÐ#4ˆ�Ñ ß^Ñ^Ø$'§H¡H¨]Õ-NÓ$OˆÐ Ò!à$�Ñä
Ð 1Ó
2€Cðð	DÜ˜S¸7ÔCˆDð  $(§8¡8¨F°BÔ#7ÓGÑ#7˜a¸1¿5¹5À¿;”'�!�D—'�'Ñ#7ˆÐGÜ!$£ˆÜÔ6Ö7ˆEÜ+¨D°,Ó?ˆFØŠ~ÙÜÔ2Ð3DÈvÔVÐ`gÔyˆDØ�M‰MÑO¨4¯8©8°F¸BÔ+?ÓOÖOñ 8ô ”d—m‘m FÓ+Ó,ˆä�fÑ"eÔfÐføôe ô Úðûô2 �|‰|×%Ñ%ô 	D÷  §¡°#Ô!5ØðØ$ŸM™M›O×2Ñ2¸(Ð2ÓC×IÑIÓK‘	øÜô Ø’	ðúà'¨9Ô4Ð9LÐPYÔ9YØØ(+¯©Ù)ÓC™M�q¨QÐ2BÑ-B—�šMùÔCÄdÐK\ÓF]Õ]ó)ˆGÐ$Ñ%ô ˜S¸7ÔCŽDûð	Düò Høô ô Ü�‰Ð;¸QÔ?Ýûðús–   ‚F Â%F# Â2J ÃJÃ$JÃ1BJ ÆF ÆF Æ#J	ÇJÇ.HÈJÈHÈJÈHÈ!JÈ=	I
ÉI
É-JÉ>J ÊJ	Ê	J ÊJ=ÊJ8Ê8J=c               ó    € V ^8„  d   QhRRRR/# )r.   ræ   r   r@   úlist[dict[str, Any]]r2   )r3   s   "r4   r5   r5   ã  s   € ÷ _ñ _˜Cð _Ð$8ñ _r6   c                óä   € \        V \        4      '       d   V P                  R . 4      MT p\        V\        4      '       d+   V Uu. uF  p\        V\        4      '       g   K  VNK  	  up# . # u upi r!  r§  )ræ   r^   r¤  s   &  r4   Ú_payload_itemsry  ã  sV   € Ü&0°¼$×&?Ò&?ˆ7�;‰;�v˜rÔ"ÀW€DÜ@JÈ4ÔQU×@VÒ@V™TÓ<™T�T¤Z°´d×%;�DˆD™TÑ<Ð^Ð\^Ð^ùÒ<s   ÁA-Á"A-Úis_agent_turnTc               ó    € V ^8„  d   QhRRRR/# )r.   rz  r�   r@   zdict[str, str]r2   )r3   s   "r4   r5   r5   è  s   € ÷ 
Añ 
A¨dð 
A¸nñ 
Ar6   c           	     ót   €  ^ RI Hp V! V R7      #   \         d    R\        RRRRRT '       d   R	MR
/u # i ; i)z*Standard headers for Copilot API requests.)Úcopilot_request_headers)rz  zEditor-Versionú
User-AgentzHermesAgent/1.0zOpenai-Intentzconversation-editszx-initiatorÚagentÚuser)rè  r}  rf  ÚCOPILOT_EDITOR_VERSION)rz  r}  s   $ r4   Úcopilot_default_headersr‚  è  sN   € ðAÝCÙ&°]ÔCÐCøÜô AàÔ4ØÐ+ØÐ1Ø§m™7¸ð	Aò 	AðAús   ‚ ‘7¯7¶7Úignore_picker_flagc               ó$   € V ^8„  d   QhRRRRRR/# )r.   r¤  r>  rƒ  r�   r@   r2   )r3   s   "r4   r5   r5   ø  s$   € ÷ ñ Ø
ðØ15ðØBFñr6   c               ó¢  € \        V P                  R 4      ;'       g    R4      P                  4       '       g   R# V'       g   V P                  R4      RJ d   R# V P                  R4      p\        V\        4      '       dR   \        VP                  R4      ;'       g    R4      P                  4       P                  4       pV'       d
   VR8w  d   R# V P                  R4      p\        V\        4      '       dR   V Uu0 uF(  p\        V4      P                  4       ;p'       g   K&  VkK*  	  ppV'       d   V\        ,          '       g   R# R# u upi )	r¿  rC   FÚmodel_picker_enabledÚcapabilitiesr¤  ÚchatÚsupported_endpointsT)r=   rI   rU  r[   r\   rJ   rt   Ú_COPILOT_CHAT_ENDPOINTS)r¤  rƒ  r‡  Ú
model_typer‰  rQ  ru  Ú	endpointss   &$      r4   Ú#_copilot_catalog_item_is_text_modelr�  ø  sþ   € äˆt�x‰x˜‹~×#Ð# Ó$×*Ñ*×,Ò,Ùß $§(¡(Ð+AÓ"BÀeÓ"KÙØ—8‘8˜NÓ+€LÜ�,¤×%Ò%Ü˜×)Ñ)¨&Ó1×7Ð7°RÓ8×>Ñ>Ó@×FÑFÓHˆ
ß˜*¨Ô.ÙØŸ(™(Ð#8Ó9ÐÜÐ%¤t×,Ò,Ù':Ó[Ñ':˜8ÄCÈÃM×DWÑDWÓDYÐ?Y¸qÓ?Y—Q�QÑ':ˆ	Ð[ß˜YÔ)@×@Ô@ÙÙùò \s   Ã=#EÄ%Ec               ó$   € V ^8„  d   QhRRRRRR/# )r.   r§   rw  rƒ  r�   r@   r2   )r3   s   "r4   r5   r5   	  s#   € ÷ ñ Ð 4ð ÈTð Ð^rñ r6   c               ó  € . p\        4       pV  Fs  p\        VP                  R4      ;'       g    R4      P                  4       pWS9   d   K=  \	        WAR7      '       g   KQ  VP                  V4       VP                  V4       Ku  	  V# )z;Chat-capable catalog rows, deduped by id, in catalog order.r¿  rC   ©rƒ  )rå   r=   rI   rU  r�  ru   rv   )r§   rƒ  r›  Úseen_idsr¤  rÉ   s   &$    r4   Ú_copilot_text_modelsr’  	  sq   € à#%€FÜ›€HÛˆÜ�t—x‘x “~×+Ð+¨Ó,×2Ñ2Ó4ˆØÔÙÜ2°4×_Ó_ÙØ�‰�XÔØ�‰�dÖñ ð €Mr6   úOptional[list[dict[str, Any]]]Ú_github_model_catalog_cacherZ  Ú_github_model_catalog_cache_keyg        r1   Ú _github_model_catalog_cache_timei,  c               ó$   € V ^8„  d   QhRRRRRR/# )r.   r0  rZ  r0   r1   r@   r“  r2   )r3   s   "r4   r5   r5   #	  s$   € ÷ #ñ #Øð#Ø,1ð#Ø<Zñ#r6   c           	     ój  € \         eO   \        V 8X  dD   \        P                  ! 4       \        ,
          \
        8  d   \        P                  ! \         4      # . pV '       d#   VP                  / \        4       CRRV  2/C4       VP                  \        4       4       V F  p \        \        \        WR7      4      p\        T4      pT'       g   T'       d   \        TRR7      pT'       g   KP  \        P                  ! T4      s T s\        P                  ! 4       sTu # 	  R#   \         d     K“  i ; i)z=Fetch the live GitHub Copilot model catalog for this account.NrW  rV  rJ  Tr�  )r”  r•  r¡   r  r–  Ú_GITHUB_MODEL_CATALOG_CACHE_TTLÚcopyÚdeepcopyrv   r‚  ry  rQ   ÚCOPILOT_MODELS_URLr®   r’  )r0  r0   Úattemptsr9   r§   r›  s   &&    r4   Úfetch_github_model_catalogrž  #	  sû   € ô 	$Ò/Ü+¨wÔ6Ü�^Š^ÓÔ @Õ@ÔDcÔcä�}Š}Ô8Ó9Ð9à%'€HßØ�‰Ð[Ô2Ó4Ð[°oÈÐQXÐPYÐGZÑ[Ô\Ø‡O�OÔ+Ó-Ô.ãˆð	Ü"¤9Ô-?ÈÔ#bÓcˆEô & eÓ,ˆßŸ%ô
 *¨%ÀDÔIˆFß‰6Ü*.¯-ª-¸Ó*?Ð'Ø.5Ð+Ü/3¯~ª~Ó/?Ð,ØŠMñ! ñ" øô ô 	Úð	ús   Â"D#Ä#D2Ä1D2zdict[str, int]Ú_copilot_context_cacheÚ_copilot_context_cache_timeÚ_copilot_context_cache_keyc               ó$   € V ^8„  d   QhRRRRRR/# )r.   rÉ   r=   r0  rZ  r@   zOptional[int]r2   )r3   s   "r4   r5   r5   R	  s!   € ÷ ñ ¨ð °mð È}ñ r6   c                ó¦  € ^ RI Hp V! V4      p\        '       dJ   \        V8X  d?   \        P                  ! 4       \
        ,
          \        8  d   \        P                  V 4      # \        VR7      pV'       g   R# / pV F§  p\        VP                  R4      ;'       g    R4      P                  4       pVP                  R4      ;'       g    / P                  R4      ;'       g    / P                  R4      pV'       g   K‚  \        V\        4      '       g   Kš  V^ 8”  g   K£  W…V&   K©  	  Vs\        P                  ! 4       sVsVP                  V 4      # )	z�``max_prompt_tokens`` for a Copilot model from the live /models API (cached in-process 1h; a
miss on a fresh cache does not re-fetch), or None.©Úfingerprint_secret_value©r0  Nr¿  rC   r‡  ÚlimitsÚmax_prompt_tokens)Úagent.credential_persistencer¥  rŸ  r¡  r¡   r   Ú_COPILOT_CONTEXT_CACHE_TTLrI   rž  r=   rU  r[   r  )	rÉ   r0  r¥  Úkey_fpÚcatalogr˜   r¤  rÕ   Ú
max_prompts	   &&       r4   Úget_copilot_model_contextr®  R	  s  € õ FÙ% gÓ.€FßÓÔ#=ÀÔ#GÜ—’“Ô:Õ:Ô=WÔWÜ%×)Ñ)¨(Ó3Ð3ä(°Ô9€GßÙØ€EÛˆÜ�$—(‘(˜4“.×&Ð& BÓ'×-Ñ-Ó/ˆØ—x‘x Ó/×5Ð5°2×:Ñ:¸8ÓD×JÐJÈ×OÑOÐPcÓdˆ
ß‰3”:˜j¬#×.Ô.°:À¶>Ø#�#‹Jñ	 ð
 #ÐÜ"&§)¢)£+ÐØ!'ÐØ�9‰9�XÓÐr6   c               ó    € V ^8„  d   QhRRRR/# )r.   r}   rZ  r@   r�   r2   )r3   s   "r4   r5   r5   n	  s   € ÷ ñ ¨ð ¸4ñ r6   c                óœ   € T ;'       g    R P                  4       P                  R4      P                  4       P                  \        RR34      # )rC   rG  z"https://models.github.ai/inferencez%https://models.inference.ai.azure.com)rU  rK  rJ   r}  ÚCOPILOT_BASE_URL)r}   s   &r4   Ú_is_github_models_base_urlr²  n	  sD   € Ø�NˆN˜×!Ñ!Ó#×*Ñ*¨3Ó/×5Ñ5Ó7×BÑBÜ	Ð?ÐAhÐióð r6   c               ó$   € V ^8„  d   QhRRRRRR/# )r.   r0  rZ  r0   r1   r@   r´  r2   )r3   s   "r4   r5   r5   t	  s'   € ÷ [ñ [ -ð [Àð [ÐQdñ [r6   c                ó¬   € \        WR 7      pV'       d;   V Uu. uF-  q3P                  R4      '       g   K  VP                  RR4      NK/  	  up# R# u upi )©r0  r0   r¿  rC   N)rž  rI   )r0  r0   r¬  r¤  s   &&  r4   rD  rD  t	  sB   € Ü(°ÔJ€GßIP©7ÓE©7 4·h±h¸t·nÔˆD�H‰H�T˜2Ö©7ÑEÐZÐVZÐZùÒEs
   ™A¶Ac               ó$   € V ^8„  d   QhRRRRRR/# )r.   r¬  r“  r0  rZ  r@   rô  r2   )r3   s   "r4   r5   r5   y	  s)   € ÷ [ñ [Ø+ð[Ø=Jð[ØV^ñ[r6   c                óì   € V f   V'       d   \        VR7      p T ;'       g    .  Uu0 uFA  p\        VP                  R4      ;'       g    R4      P                  4       ;p'       g   K?  VkKC  	  up# u upi )Nr¦  r¿  rC   )rž  r=   rI   rU  )r¬  r0  r¤  rÕ   s   &&  r4   Ú_copilot_catalog_idsr¸  y	  s]   € à‚Ÿ7Ü,°WÔ=ˆØ$Ÿ]˜]¨˜]ÓZ™]�D´s¸4¿8¹8ÀD»>×;OÐ;OÈRÓ7P×7VÑ7VÓ7XÐ0X°Ó0X�CˆC™]ÑZÐZùÒZs   §!A1Á	A1Á(A1r¬  c               ó(   € V ^8„  d   QhRRRRRRRR/# ©r.   rÉ   rZ  r¬  r“  r0  r@   r=   r2   )r3   s   "r4   r5   r5   €	  s,   € ÷ #ñ #Øð#Ø)Gð#àð#à&)ñ#r6   c               ó¼  € \        T ;'       g    R 4      P                  4       pV'       g   R # \        WR7      p\        P                  ! V4      pV'       d   V# V.pRV9   d7   VP                  VP                  R^4      ^,          P                  4       4       VP                  R4      '       d   VP                  VRR 4       \        4       pV FH  pV'       d   W‡9   d   K  VP                  V4       V\        9   d   \        V,          u # W„9   g   KF  Vu # 	  RV9   d9   VP                  R^4      ^,          P                  4       p	V	'       d
   RV	9  d   V	# V# )rC   ©r¬  r0  rG  N)z-miniz-nanoz-chatéûÿÿÿ)
r=   rU  r¸  r   rI   rv   r|  rE  rå   ru   )
rÉ   r¬  r0  r~  Úcatalog_idsr  r‚  ry   r•  r.  s
   &$$       r4   Únormalize_copilot_model_idr¿  €	  s#  € ô ˆh�nˆn˜"Ó
×
#Ñ
#Ó
%€CßÙä&¨wÔH€KÜ"×&Ò& sÓ+€EßØˆà�€JØ
ˆc„zØ×Ñ˜#Ÿ)™) C¨Ó+¨AÕ.×4Ñ4Ó6Ô7Ø
‡|�|Ð/×0Ò0Ø×Ñ˜#˜c˜r˜(Ô#ä“U€DÛˆ	ß˜IÔ-ÙØ�‰�ÔØÔ.Ô.Ü)¨)Õ4Ò4ØÖ#ØÒñ  ð ˆc„zØ—9‘9˜S !Ó$ QÕ'×-Ñ-Ó/ˆ÷ ˜ 8Ô+ØˆOØ€Jr6   c               ó    € V ^8„  d   QhRRRR/# )r.   rÉ   r=   r@   rq   r2   )r3   s   "r4   r5   r5   ¦	  s   € ÷ 	ñ 	°Sð 	¸Yñ 	r6   c                ó`  € T ;'       g    R P                  4       P                  4       pVP                  R4      '       d   \        \        4      # \        V 4      P                  4       p\        V4      '       d   \        \        4      # VP                  R4      '       d   \        \        4      # . # )rC   zgpt-5)z	openai/o1z	openai/o3z	openai/o4Úo1Úo3Úo4)	rU  rJ   r}  rt   Ú"COPILOT_REASONING_EFFORTS_O_SERIESr¿  r°  r®  ÚCOPILOT_REASONING_EFFORTS_GPT5)rÉ   r~  rF  s   &  r4   Ú&_github_reasoning_efforts_for_model_idrÇ  ¦	  s‡   € Ø�>ˆ>�r×
 Ñ
 Ó
"×
(Ñ
(Ó
*€CØ
‡~�~ÐO×PÒPÜÔ6Ó7Ð7Ü+¨HÓ5×;Ñ;Ó=€JÜ�j×!Ò!ÜÔ'Ó(Ð(Ø×Ñ˜W×%Ò%ÜÔ2Ó3Ð3Ø€Ir6   c               ó    € V ^8„  d   QhRRRR/# )r.   rÉ   r=   r@   r�   r2   )r3   s   "r4   r5   r5   ²	  s   € ÷ ^ñ ^°ð ^¸ñ ^r6   c                óÌ   € \         P                  ! RV 4      p\        V4      ;'       d<    \        VP	                  ^4      4      ^8¬  ;'       d    V P                  R4      '       * # )zœopencode's ``shouldUseCopilotResponsesApi``: GPT-5+ uses the Responses API except
``gpt-5-mini``; non-GPT models (Claude, Gemini, ...) use Chat Completions.z
^gpt-(\d+)z
gpt-5-mini)ÚreÚmatchr�   r  Úgroupr}  )rÉ   rË  s   & r4   Ú!_should_use_copilot_responses_apirÍ  ²	  sO   € ô �HŠH�] HÓ-€EÜ�‹;×]Ð]œ3˜uŸ{™{¨1›~Ó.°!Ñ3×]Ð]¸H×<OÑ<OÐP\Ó<]Ô8]Ð]r6   c               ó(   € V ^8„  d   QhRRRRRRRR/# rº  r2   )r3   s   "r4   r5   r5   ¹	  s,   € ÷ ñ ØðØ)Gðàðà&)ñr6   c               ó†   € Vf   V'       d   \        VR7      p\        WVR7      pV'       d   \        V4      '       d   R# R# )a  API mode for a Copilot model from the id pattern (opencode's approach). Copilot's Claude models
go through its OpenAI-compatible chat endpoint, not the native Anthropic adapter: the catalog may
advertise /v1/messages but the Copilot token/header scheme lives in the OpenAI client path.r¦  r¼  Úcodex_responsesÚchat_completions)rž  r¿  rÍ  )rÉ   r¬  r0  rF  s   &$$ r4   Úcopilot_model_api_moderÒ  ¹	  s5   € ð ‚Ÿ7Ü,°WÔ=ˆÜ+¨HÈwÔW€JßÔ7¸
×CÒCÙ Ùr6   c               ó    € V ^8„  d   QhRRRR/# )r.   r]  rZ  r@   r2   )r3   s   "r4   r5   r5   Ç	  s   € ÷ kñ k¨]ð k¸}ñ kr6   c                óò   € \        T ;'       g    R4      P                  4       P                  4       P                  R^4      R,          pV'       d'   VP	                  \        \        4      4      '       d   R# R# )z¸``"codex_responses"`` for families that only accept the Responses API on Azure Foundry (GPT-5.x
incl. gpt-5-mini, codex, o1/o3/o4), else None. Any ``vendor/`` prefix is stripped first.rC   rG  rÐ  Néÿÿÿÿ)r=   rU  rJ   Úrsplitr}  r¤   r   )r]  r~  s   & r4   Úazure_foundry_model_api_moder×  Ç	  s]   € ô ˆj×Ð˜BÓ
×
%Ñ
%Ó
'×
-Ñ
-Ó
/×
6Ñ
6°s¸AÓ
>¸rÕ
B€Cß #¨¯©´uÔ=^Ó7_×(`Ò(`ÐÐjÐfjÐjr6   úopencode-goúopencode-zenc               ó    € V ^8„  d   QhRRRR/# )r.   Úprovider_idrZ  r@   r2   )r3   s   "r4   r5   r5   Ñ	  s   € ÷ Lñ L¨-ð L¸Mñ Lr6   c                óÞ   a€ \        T ;'       g    R4      P                  4       P                  4       oS'       g   R# \        V 4      pV\        9   d   V# \        V3R l\         4       R4      # )u)  Resolve a provider id (canonical or prefixed) to its OpenCode family, or None.

Returns ``"opencode-zen"`` or ``"opencode-go"`` for the built-in providers AND for custom providers
whose name extends a family slug (e.g. ``opencode-go-bridge`` pointing at
``https://opencode.ai/zen/go/v1``, issue #85589). Matching is case-insensitive. Custom family providers
need the same per-model api_mode routing and /v1 base-url normalization as the built-ins â€” this
predicate is the single owner of that family-membership question; do not re-implement it inline.
rC   Nc              3  óZ   <"  € T F   pSP                  V4      '       g   K  Vx € K"  	  R # 5irk   )r}  )r¼   Úfr~  s   & €r4   r½   Ú+opencode_provider_family.<locals>.<genexpr>à	  s    øé € ÐDÑ.�q°#·.±.À×2C—’Ó.ùs   ƒ+¡
+)r=   rU  rJ   r-  Ú_OPENCODE_FAMILIESrk  )rÛ  r   r~  s   & @r4   Úopencode_provider_familyrá  Ñ	  s\   ø€ ô ˆk×Ð˜RÓ
 ×
&Ñ
&Ó
(×
.Ñ
.Ó
0€CßÙÜ" ;Ó/€IØÔ&Ô&ØÐÜÔDÕ.ÓDÀdÓKÐKr6   c               ó$   € V ^8„  d   QhRRRRRR/# ©r.   rÛ  rZ  rÉ   r@   r=   r2   )r3   s   "r4   r5   r5   ã	  s"   € ÷ 	ñ 	¨]ð 	Àmð 	ÐX[ñ 	r6   c                ó:  € \        V 4      p\        T;'       g    R4      P                  4       pV'       d   Vf   V# T ;'       g    T R2V R23 FF  pVP                  4       P	                  VP                  4       4      '       g   K8  V\        V4      R u # 	  V# )zJNormalize OpenCode config IDs to the bare model slug used in API requests.rC   NrG  )rá  r=   rU  rJ   r}  r¥   )rÛ  rÉ   rw  Úcurrentrt  s   &&   r4   Únormalize_opencode_model_idræ  ã	  s‹   € ä% kÓ2€FÜ�(—.�.˜bÓ!×'Ñ'Ó)€Gß�f’nØˆØ!×+Ð+ VÐ,¨AÐ.°6°(¸!°Ó=ˆØ�=‰=‹?×%Ñ% f§l¡l£n×5Ô5Øœ3˜v›;˜<Ð(Ò(ñ >ð €Nr6   z2dict[str, tuple[tuple[tuple[str, ...], str], ...]]Ú_OPENCODE_API_MODE_PREFIXESc               ó$   € V ^8„  d   QhRRRRRR/# rã  r2   )r3   s   "r4   r5   r5   ü	  s"   € ÷ ñ ¨ð À-ð ÐTWñ r6   c                óæ   € \        V 4      p\        W4      P                  4       pV'       dE   \        P	                  T;'       g    RR4       F   w  rEVP                  V4      '       g   K  Vu # 	  R# )z\Determine the API mode for an OpenCode Zen / Go model (see ``_OPENCODE_API_MODE_PREFIXES``).rC   rÑ  r2   )rá  ræ  rJ   rç  rI   r}  )rÛ  rÉ   rw  rF  ÚprefixesÚmodes   &&    r4   Úopencode_model_api_moderì  ü	  s]   € ä% kÓ2€FÜ,¨[ÓC×IÑIÓK€JßÜ9×=Ñ=¸f¿l¸lÈÈBÖO‰NˆHØ×$Ñ$ X×.Ô.Ø’ñ Pñ r6   z/zenz/zen/goc               ó(   € V ^8„  d   QhRRRRRRRR/# )r.   rÛ  rZ  ro  r}   r@   r=   r2   )r3   s   "r4   r5   r5   
  s,   € ÷ ?ñ ?Øð?Ø*7ð?ØCPð?ØUXñ?r6   c                óJ  € \        T;'       g    R4      P                  4       P                  R4      p\        V 4      pV'       d   Vf   V# \        P
                  P                  V4      pVP                  ;'       g    RP                  4       pVR8H  ;'       g    VP                  R4      pVP                  P                  R4      pV'       d_   \        V 4      \        9   dK   \        P                  ! RV4      '       d.   \        V,          VP                  R4      '       d   RMR,           pVR8X  d   \        P                   ! RRV4      pM(V'       d!   VP                  R4      '       g
   VR,          p\        P
                  P#                  VP%                  VR	7      4      # )
uQ  Normalize an OpenCode Zen / Go base URL for the API mode. Must be SYMMETRIC: the anthropic-
stripped URL gets persisted to ``model.base_url`` after switching into an anthropic-routed model,
and chat/codex modes heal it by re-adding ``/v1`` â€” but only on opencode.ai hosts, so custom
``OPENCODE_*_BASE_URL`` proxies are left alone. On those hosts the relay path segment follows
the resolved family too (``/zen`` vs ``/zen/go``): the two relays serve different model sets,
so a ``model.base_url`` carried over from the other family 401s ("Model ... is not supported").
The family heal applies to the BUILT-IN providers only: a custom provider merely named after a
family (``opencode-go-bridge``) declared its relay path explicitly in ``providers:`` and keeps it.
Only the path is edited, so a port, userinfo, query or fragment round-trips untouched.rC   rG  zopencode.aiz.opencode.aiz/zen(/go)?(/v1)?rK  rn  z/v1$)rT   )r=   rU  rK  rá  rD   rC  rD  rÒ  rJ   rE  rT   r-  rà  rÊ  Ú	fullmatchÚ_OPENCODE_FAMILY_PATHSÚsubÚ
urlunparseÚ_replace)	rÛ  ro  r}   r<   rw  ÚparsedrÕ  ÚofficialrT   s	   &&&      r4   Únormalize_opencode_base_urlrö  
  s3  € ô ˆh�nˆn˜"Ó
×
#Ñ
#Ó
%×
,Ñ
,¨SÓ
1€CÜ% kÓ2€Fß�&’.Øˆ
Ü�\‰\×"Ñ" 3Ó'€FØ�O‰O×!Ð!˜r×(Ñ(Ó*€DØ�}Ñ$×EÐE¨¯©°nÓ(E€HØ�;‰;×Ñ˜cÓ"€DßÔ& {Ó3Ô7IÔIÌbÏlÊlÐ[nÐpt×NuÒNuÜ% fÕ-¸$¿-¹-È×:NÒ:N±ÐTVÕWˆØÐ'Ô'Ü�vŠv�g˜r 4Ó(‰ß	˜$Ÿ-™-¨×.Ò.Ø��ˆÜ�<‰<×"Ñ" 6§?¡?¸ ?Ó#=Ó>Ð>r6   c               ó(   € V ^8„  d   QhRRRRRRRR/# )r.   rÉ   rZ  r¬  r“  r0  r@   rq   r2   )r3   s   "r4   r5   r5   '
  s2   € ÷ Oñ OØðOØ)GðOàðOà&/ñOr6   c               óÐ  aa	€ \        WVR7      o	S	'       g   . # Vf   V'       d   \        VR7      pV'       d   \        V	3R lV 4       R4      MRpVeð   VP                  R4      p\	        V\
        4      '       d{   VP                  R4      p\	        V\
        4      '       d   VP                  R4      MRp\	        V\        4      '       g   . # \        \
        P                  V3R lV 4       4      4      # R	VP                  R. 4       Uu0 uF*  p\        V4      P                  4       P                  4       kK,  	  up9  d   . # \        \        T ;'       g    S	4      4      # u upi )
zEReturn supported reasoning-effort levels for a Copilot-visible model.r¼  Nr¦  c              3  óV   <"  € T F  qP                  R 4      S8X  g   K  Vx € K   	  R# 5ir^  r  )r¼   r¤  rF  s   & €r4   r½   Ú1github_model_reasoning_efforts.<locals>.<genexpr>1
  s    øé € ÐS©7 4·h±h¸t³nÈ
Ñ6RŸ$š$«7ùr¯  r‡  ÚsupportsÚreasoning_effortc              3  óŠ   <"  € T F8  p\        V4      P                  4       P                  4       ;o'       g   K4  Sx € K:  	  R # 5irk   )r=   rU  rJ   )r¼   r²  ru  s   & €r4   r½   rú  :
  s3   øé € Ð%d±g¨FÄsÈ6Ã{×GXÑGXÓGZ×G`ÑG`ÓGbÐBbÀ!ÓBb§a¢a³gùs
   ƒ1A¹
AÚ	reasoning)r¿  rž  rk  rI   r[   r\   rt   rm  r=   rU  rJ   rÇ  )
rÉ   r¬  r0  Úcatalog_entryr‡  rû  Úeffortsr±   ru  rF  s
   &$$     @@r4   Úgithub_model_reasoning_effortsr  '
  s  ù€ ô ,¨HÈwÔW€JßØˆ	à‚Ÿ7Ü,°WÔ=ˆß^e”DÔS©7ÓSÐUYÔZÐko€MØÒ Ø$×(Ñ(¨Ó8ˆÜ�l¤D×)Ò)à#×'Ñ'¨
Ó3ˆHÜ:DÀXÌt×:TÒ:T�h—l‘lÐ#5Ô6ÐZ^ˆGÜ˜g¤t×,Ò,Ø�	ÜœŸ™Ô%d±gÓ%dÓdÓeÐeà¸}×?PÑ?PÐQ_ÐacÔ?dÓeÑ?d¸!œs 1›vŸ|™|›~×3Ñ3Ö5Ñ?dÑeÔeØˆIÜ1´#°h×6LÐ6LÀ*Ó2MÓNÐNùò fs   Ä0E#zdict[str, float]Ú_probe_neg_cacheg      N@c               ó    € V ^8„  d   QhRRRR/# )r.   r}   r=   r@   rZ  r2   )r3   s   "r4   r5   r5   M
  s   € ÷ .ñ .˜Sð . ]ñ .r6   c                óF   € ^ RI Hp V! V 4      w  r#pV'       d   V RV 2# R# )z[``host:port`` for *base_url* (both URL candidates share one entry), or None without a host.)Úbase_url_originry  N)rf   r  )r}   r  r  rÕ  Úports   &    r4   Ú_probe_neg_keyr  M
  s+   € å%á# HÓ-�M€AˆTß#ˆdˆV�1�T�FÐÐ-¨Ð-r6   c               ó   € V ^8„  d   QhRR/# r†  r2   )r3   s   "r4   r5   r5   U
  s   € ÷ (ñ (àñ(r6   c           
     ó   € R V RVRVRVRV/# ©r›  Ú
probed_urlrn  Úsuggested_base_urlÚused_fallbackr2   r
  s   &&&&&r4   Ú_probe_resultr  U
  s)   € ð 	�&Ø�jØÐ.ØÐ0Ø˜ð(ð (r6   c               ó0   € V ^8„  d   QhRRRRRRRRRRR	R
/# )r.   r0  rZ  r}   r0   r1   ro  Úrequest_headersr>   r@   r>  r2   )r3   s   "r4   r5   r5   `
  sN   € ÷ MBñ MBØðMBØ&3ðMBØ>CðMBàðMBà5MðMBð ñMBr6   c                ó
  € T;'       g    RP                  4       P                  R4      pV'       g   \        RRR4      # \        V4      '       d"   \	        WR7      p\        V\
        \        4      # VP                  R4      '       d   VRR P                  R4      MVR,           pVR3.pV'       d   Wu8w  d   VP                  VR34       . p	\        V4      p
V
eo   \        P                  V
4      pVeV   \        P                  ! 4       V,
          \        8  d1   \        RVP                  R4      R,           TWu8w  d   V4      # R4      # R	\        /p\         P"                  P%                  V4      P&                  R
8X  d   R\)        4       P*                   2VR&   V '       d   VR8X  d   WR&   RVR&   MV '       d	   RV  2VR&   VP-                  \        4      '       d   VP/                  \1        4       4       \3        V\4        4      '       d   ^ RIHp VP/                  V! V4      4       / p\;        V4      pVe   WþR&   RpV Fé  w  ppVP                  R4      R,           pV	P                  V4        \=        V3RVRV/VB pT
e   \        PI                  T
R4       ^ RI%H&p . pTP                  R. 4       FJ  p\3        T\4        4      '       d   T! T4      '       d   K)  TP                  TP                  RR4      4       KL  	  \        TTTP                  R4      TT8w  d   TMTT4      u # 	  V
e%   V'       d   \        P                  ! 4       \        V
&   \        RV	'       d
   V	^ ,          MVP                  R4      R,           TWu8w  d   V4      # R4      #   \>         d_   p\3        T\         P@                  PB                  4      '       d   TPD                  MTpT;'       d    \3        T\F        4      p Rp?EKº  Rp?ii ; i)u  Probe a ``/models`` endpoint with light URL heuristics (``base`` then ``baseÂ±/v1``).
``anthropic_messages`` mode sends ``x-api-key`` + ``anthropic-version`` instead of a bearer; the
``data[].id`` response shape is identical. ``models`` is None when no candidate answered.rC   rG  Nrµ  rK  FTr+   r~  z!generativelanguage.googleapis.comzhermes-agent/zX-Goog-Api-Clientrn  r\  rU  rT  rV  rW  )Únormalize_extra_headersr,   r0   r9   )Únote_catalog_itemr^   r¿  éýÿÿÿ)'rU  rK  r  r²  rD  rœ  r±  rE  rv   r  r  rI   r¡   r  Ú_PROBE_NEG_TTLÚ_HERMES_USER_AGENTrD   rC  rD  rÒ  r   Úbase_versionr}  r  r‚  r[   r\   r  r  r‰   rQ   r®   rh  ÚURLErrorÚreasonÚTimeoutErrorÚpopr§  r  )r0  r}   r0   ro  r  rF  r›  Úalternate_baser‚  ÚtriedÚ_neg_keyÚ	_neg_seenr9   r  Ú_open_kwargsÚ_ssl_contextÚall_timed_outÚcandidate_baseÚis_fallbackr<   r^   r²   Úcauser  Úprobedr¤  s   &&&&&                     r4   Úprobe_api_modelsr'  `
  s¡  € ð —.�.˜b×'Ñ'Ó)×0Ñ0°Ó5€JßÜ˜T 4¨Ó,Ð,Ü! *×-Ò-Ü%¨gÔGˆÜ˜VÔ%7Ô9IÓJÐJà4>×4GÑ4GÈ×4NÒ4N�Z  �_×+Ñ+¨CÔ0ÐT^ÐafÕTf€NØ+5°uÐ*=Ð)>€Jß˜.Ô6Ø×Ñ˜>¨4Ð0Ô1à€EÜ˜jÓ)€HØÒÜ$×(Ñ(¨Ó2ˆ	ØÒ ¤d§n¢nÓ&6¸Õ&BÄnÔ%TÜ Ø�j×'Ñ'¨Ó,¨yÕ8¸*Ø"0Ô">�óJð JàDHóJð Jð  ,Ô-?Ð@€GÜ‡|�|×Ñ˜ZÓ(×1Ñ1Ð5XÔXØ)6Ô7GÓ7I×7VÑ7VÐ6WÐ'XˆÐ#Ñ$ß�8Ð3Ô3Ø&�ÑØ'3ˆÐ#Ò$ß	Ø%,¨W¨IÐ#6ˆ�Ñ Ø×ÑÔ-×.Ò.Ø�‰Ô.Ó0Ô1Ü�/¤4×(Ò(å=à�‰Ñ.¨Ó?Ô@ð $&€LÜ/°
Ó;€LØÒØ&2�]Ñ#Ø€MÛ'1Ñ#ˆ˜Ø×#Ñ# CÓ(¨9Õ4ˆØ�‰�SÔð	Ü˜SÑS¨'ÐS¸7ÐSÀlÑSˆDð ÒÜ× Ñ  ¨4Ô0Ý=àˆØ—H‘H˜V RÖ(ˆDÜ˜$¤×%Ò%Ñ*;¸D×*AÒ*AÙØ�M‰M˜$Ÿ(™( 4¨Ó,Ö-ñ )ô Ø�C˜×.Ñ.¨sÓ3Ø,°Ô>‰NÀJÐP[ó]ò 	]ñ' (2ð. Ò§Ü%)§^¢^Ó%5Ô˜Ñ"ÜØŸ%ˆe�AŽh Z×%6Ñ%6°sÓ%;¸iÕ%GÈØ(Ô6ˆóBð Bà<@óBð Bøô) ô 	ä",¨S´&·,±,×2GÑ2G×"HÒ"H�C—J’JÈcˆEØ)×MÐM¬j¸ÄÓ.MˆMÞûð		ús   É3NÎPÎ$A O=Ï%O=Ï=Pz^(?i)(embed|rerank|whisper|stable-diffusion|flux|sdxl|tts|bark|speech|image-gen|clip|vit-|dpt-)zfrozenset[str]Ú_DEEPINFRA_SURFACE_TAGSz#https://api.deepinfra.com/v1/openaizfilter=true&sort_by=hermeszdict[str, list[dict]]Ú_deepinfra_catalog_cacheÚ_deepinfra_catalog_neg_cachec               ó    € V ^8„  d   QhRRRR/# )r.   rw   r=   r@   r2   )r3   s   "r4   r5   r5   Ç
  s   € ÷ <ñ <˜ð < ñ <r6   c                óN   € ^ RI Hp V! V 4      ;'       g    RP                  4       # )zdProfile-scoped ``.env``/environ read: under a multiplexed turn the launch env is not this profile's.)Úget_env_value_prefer_dotenvrC   )r  r-  rU  )rw   r-  s   & r4   Ú_deepinfra_envr.  Ç
  s!   € å=Ù'¨Ó,×2Ð2°×9Ñ9Ó;Ð;r6   c               ó   € V ^8„  d   QhRR/# rK  r2   )r3   s   "r4   r5   r5   Í
  s   € ÷ Fñ F ñ Fr6   c                 ó¸   € \        R4      ;'       g    \        P                  R4      p ^ RIHp V! \        R4      4      ;'       g    RpV  RV 2V  R\
         23# )zÛReturn ``(cache_key, full_url)`` for the DeepInfra catalog endpoint. The key carries the
api-key fingerprint: the catalog is user-scoped (private fine-tunes), so two profiles with
different keys must not share an entry.ÚDEEPINFRA_BASE_URLrG  r¤  ÚDEEPINFRA_API_KEYÚanonÚ#z/models?)r.  Ú_DEEPINFRA_DEFAULT_BASE_URLrK  r©  r¥  Ú_DEEPINFRA_MODELS_QUERY)r1  r¥  rÄ  s      r4   Ú_deepinfra_catalog_urlr7  Í
  sa   € ô Ð/Ó0×OÐOÔ4O×WÑWÐX[Ó\€DÝEÙ	!¤.Ð1DÓ"EÓ	F×	PÐ	PÈ&€BØˆV�1�R�Dˆ>˜d˜V 8Ô,CÐ+DÐEÐEÐEr6   r0   c               ó$   € V ^8„  d   QhRRRRRR/# )r.   r0   r1   rÜ   r�   r@   úOptional[list[dict]]r2   )r3   s   "r4   r5   r5   ×
  s$   € ÷ ñ ØðØ,0ðØ=Qñr6   c                ód  € \        4       w  r#V'       gY   V\        9   d   \        V,          # \        P                  V4      pVe(   \        P
                  ! 4       V,
          \        8  d   R# R\        /p\        R4      pV'       d	   RV 2VR&    \        W0VR7      pTP                  R4      p\        T\        4      '       g   \        P
                  ! 4       \        T&   R# T\        T&   \        P                  TR4       T#   \         d!    \        P
                  ! 4       \        T&    R# i ; i)zÀRaw DeepInfra catalog list (chat, embed, image-gen, TTS, STT in one response), cached per base
URL. A Bearer token is attached when available so user-scoped catalogs (private fine-tunes) show.Nr~  r2  rV  rW  rJ  r^   )r7  r)  r*  rI   r¡   r  Ú_DEEPINFRA_CATALOG_NEG_TTLr  r.  rQ   r®   r[   rt   r  )	r0   rÜ   rM  r<   Ú	last_failr9   r0  ræ   r^   s	   $$       r4   Ú_fetch_deepinfra_catalogr=  ×
  s  € ô ,Ó-�N€IßØÔ0Ô0Ü+¨IÕ6Ð6Ü0×4Ñ4°YÓ?ˆ	ØÒ ¤d§n¢nÓ&6¸Õ&BÔF`Ô%`Ùà+Ô-?Ð@€GÜÐ0Ó1€GßØ%,¨W¨IÐ#6ˆ�Ñ ðÜ˜C¸'ÔBˆð �;‰;�vÓ€DÜ�dœD×!Ò!Ü26·.².Ó2BÔ$ YÑ/ÙØ*.Ô˜YÑ'Ü ×$Ñ$ Y°Ô5Ø€Køô ô Ü26·.².Ó2BÔ$ YÑ/Úðús   ÂD Ä'D/Ä.D/c               ó(   € V ^8„  d   QhRRRRRRRR/# )	r.   Útagr=   r0   r1   rÜ   r�   r@   r9  r2   )r3   s   "r4   r5   r5   õ
  s,   € ÷ ñ Ø	ðØðØ6:ðØG[ñr6   c               ó4  € \        WR7      pVf   R# . pV Fý  pVP                  R4      pVP                  R4      pV'       d   Vf   K3  \        V\        4      '       d   TM/ pVP                  R4      p	\        V	\        4      '       d   T	M. p
\
        ;QJ d    R V
 4       F  '       g   K   RM	  RM! R V
 4       4      '       d   W
9   pM'V R	8H  ;'       d    \        P                  V4      '       * pV'       g   Kè  VP                  RVRV/4       Kÿ  	  V# )
u  DeepInfra ``{"id", "metadata"}`` items whose ``metadata.tags`` includes *tag*. Items with no
surface tag fall through to the legacy id-regex exclusion (chat surface only â€” embed/image-gen/
tts/stt cannot be inferred from an id). ``None`` on network failure.©r0   rÜ   Nr¿  ÚmetadataÚtagsc              3  ó2   "  € T F  q\         9   x € K  	  R # 5irk   )r(  )r¼   rf  s   & r4   r½   Ú1_fetch_deepinfra_models_by_tag.<locals>.<genexpr>  s   é € Ð:±T°Ô+Ö+³Tùs   ‚TFrˆ  )	r=  rI   r[   r\   rt   r  Ú_DEEPINFRA_EXCLUDE_REÚsearchrv   )r?  r0   rÜ   r^   rƒ  r¤  rÕ   Úraw_metadatarB  Úraw_tagsrC  Úhits   &$$         r4   Ú_fetch_deepinfra_models_by_tagrK  õ
  sè   € ô
 $¨GÔQ€DØ‚|ÙØ€GÛˆØ�h‰h�t‹nˆØ—x‘x 
Ó+ˆß�lÒ*ÙÜ#-¨l¼D×#AÒ#A‘<ÀrˆØ—<‘< Ó'ˆÜ% h´×5Ò5‰x¸2ˆß‹3Ñ:±TÓ:�3�3Š3Ñ:±TÓ:×:Ò:Ø‘+‰Cà˜‘-×IÐIÔ(=×(DÑ(DÀSÓ(IÔ$IˆCß‰3Ø�N‰N˜D # z°8Ð<Ö=ñ ð €Nr6   c               ó$   € V ^8„  d   QhRRRRRR/# )r.   r0   r1   rÜ   r�   r@   r´  r2   )r3   s   "r4   r5   r5     s)   € ÷ Sñ SØðSØ,0ðSØ=PñSr6   c               óv   € \        RWR7      pVe#   V Uu. uF  q3R,          NK  	  up;'       g    R# R# u upi )z�DeepInfra chat-model ids (string-list contract for :func:`provider_model_ids`); ``None`` on
network failure or when no chat-tagged id exists.rˆ  rA  Nr¿  ©rK  )r0   rÜ   r§   r¤  s   &$  r4   rŠ  rŠ    s>   € ô +¨6¸7Ô`€EØ7<Ò7H¡EÓ*¡E˜D�$�ZˆZ¡EÑ*×2Ð2¨dÐRÈdÐRùÒ*s   –6c               ó$   € V ^8„  d   QhRRRRRR/# )r.   r?  r=   rÜ   r�   r@   rq   r2   )r3   s   "r4   r5   r5     s!   € ÷ ;ñ ;˜Sð ;°Dð ;ÀYñ ;r6   c               óh   € \        WR7      pV'       d   V Uu. uF  q3R,          NK  	  up# . # u upi )zFReturn DeepInfra model ids carrying surface *tag* (``[]`` on failure).rà   r¿  rN  )r?  rÜ   r§   r¤  s   &$  r4   Údeepinfra_model_idsrQ    s/   € ä*¨3ÔL€Eß-2¡5Ó)¡5˜4��JˆJ¡5Ñ)Ð:¸Ð:ùÒ)s   ™/c               ó    € V ^8„  d   QhRRRR/# )r.   ÚsectionrU   r@   r=   r2   )r3   s   "r4   r5   r5     s   € ÷ *ñ * ð *¸#ñ *r6   c                óê   € \        V \        4      '       d   V P                  R4      MRpT;'       g    \        R4      ;'       g    \        p\        V4      P                  4       P                  R4      # )ue   DeepInfra base URL: config-section ``base_url`` â†’ ``DEEPINFRA_BASE_URL`` env â†’ default; stripped.r}   Nr1  rG  )r[   r\   rI   r.  r5  r=   rU  rK  )rS  r•  Úvalues   &  r4   Údeepinfra_base_urlrV    sX   € ä+5°g¼t×+DÒ+D�—‘˜JÔ'È$€IØ×\Ð\œÐ(<Ó=×\Ð\ÔA\€EÜˆu‹:×ÑÓ×$Ñ$ SÓ)Ð)r6   c               ó    € V ^8„  d   QhRRRR/# )r.   r0   r1   r@   r´  r2   )r3   s   "r4   r5   r5   $  s   € ÷ ñ  eð Ð6Iñ r6   c                óV  € \         P                  ! RR4      P                  4       pV'       g   R# \         P                  ! RR4      P                  4       pV'       g	   ^ RIHp TpRRV 2R\
        /p VP                  R	4      R
,           p\        WPVR7      pVP                  R. 4       Uu. uF_  pVP                  R4      '       g   K  VP                  R4      R8X  g   K4  RVP                  R4      ;'       g    . 9   g   KV  VR,          NKa  	  up# u upi   \         d     R# i ; i)z>Fetch available language models with tool-use from AI Gateway.ÚAI_GATEWAY_API_KEYrC   Nrê  ré  rW  rV  r~  rG  r+   rJ  r^   r¿  r¤  Úlanguageztool-userC  )
rö  r#  rU  rg   rê  r  rK  rQ   rI   r®   )r0   r0  r}   rê  r9   r<   r^   rm   s   &       r4   r‡  r‡  $  s  € ä�iŠiÐ,¨bÓ1×7Ñ7Ó9€GßÙÜ�yŠyÐ.°Ó3×9Ñ9Ó;€HßÝ8Ø&ˆà '¨'¨Ð 3°\ÔCUÐV€GðØ�o‰o˜cÓ" YÕ.ˆÜ˜°wÔ?ˆà!ŸX™X f¨bÔ1ódÙ1˜Ø�u‰u�T�{ô Ø Ÿu™u V›}°
Ñ:ô Ø?IÈaÏeÉeÐTZËm×NaÐNaÐ_aÑ?bô ˆAˆd�GˆGÑ1ñdð 	dùò døô ô Úðús<   Á39D Â,DÃ
DÃ"DÃ;DÄDÄD ÄD ÄD(Ä'D(c               ó0   € V ^8„  d   QhRRRRRRRRRRR	R
/# )r.   r0  rZ  r}   r0   r1   ro  r9   r>   r@   r´  r2   )r3   s   "r4   r5   r5   9  s>   € ÷  ñ  Øð Ø&3ð Ø>Cð àð à-Eð ð ñ r6   c                ó@   € \        WW#VR7      pVP                  R4      # )zOFetch the list of available model IDs from the provider's ``/models`` endpoint.)r0   ro  r  r›  )r'  rI   )r0  r}   r0   ro  r9   r)  s   &&&&& r4   rT  rT  9  s"   € ô
 ˜g¸ÐelÔm€FØ�:‰:�hÓÐr6   c               ó(   € V ^8„  d   QhRRRRRRRR/# )	r.   r0  r   ro  rZ  r9   r>   r@   r=   r2   )r3   s   "r4   r5   r5   B  s2   € ÷ 
^ñ 
^Øð
^Ø)ð
^Ø4Lð
^ØQTñ
^r6   c           	     óH  € ^ RI p^ RIHp \        W4      '       d   V P                  MT pRP                  T;'       g    RT;'       g    R\        P                  ! T;'       g    / RR7      34      pVP                  VP                  RRR	7      ^R
7      P                  4       # )a  Custom endpoints have no ``PROVIDER_REGISTRY`` slug, so hash exactly what callers pass to
:func:`fetch_api_models`: a rotated ``api_key``, changed ``api_mode`` or edited ``extra_headers``
each bust the cache entry. blake2b for the same CodeQL rationale as ``_credential_fingerprint``.N)ÚCommandTokenSourcer  rC   T)rÿ  r  r  r3  r  )r  Úagent.command_token_sourcer_  r[   Úcache_identityrù  rL   r  r  r  r  )r0  ro  r9   r  r_  rx  r:  s   &&&    r4   Ú_custom_endpoint_fingerprintrb  B  s~   € ó
 å=Ü)3°G×)PÒ)Pˆw×%Ò%ÐV]€HØ�8‰8�X—^�^  X§^ ^°´T·Z²ZÀÇÀÈ2ÐY]Ô5^Ð_Ó`€DØ�?‰?˜4Ÿ;™; w°y˜;ÓAÈqˆ?ÓQ×[Ñ[Ó]Ð]r6   r:  c               ó(   € V ^8„  d   QhRRRRRRRR/# )	r.   rÂ   r   rÄ  r=   r:  r�   r@   zTypeGuard[dict[str, Any]]r2   )r3   s   "r4   r5   r5   O  s,   € ÷ 3ñ 3Øð3Øð3Ø)-ð3Ø:Sñ3r6   c               ó¢  € \        V \        4      ;'       d¹    V P                  R4      V8H  ;'       d�    \        V P                  R4      \        4      ;'       dv    T;'       g    \	        V R,          4      ;'       dR    \        V P                  R4      \
        \        34      ;'       d%    \        V P                  R4      \        4      '       * # )zãWell-formed cache row for fingerprint *fp*. Requires a numeric ``at`` so corrupt disk state
degrades to a cache miss instead of raising; empty model lists are valid only when the caller
opts into an authoritative empty catalog.rÄ  r›  rÅ  )r[   r\   rI   rt   r�   r  r1   )rÂ   rÄ  r:  s   &&$r4   rÌ  rÌ  O  s­   € ô 	�5œ$Ó÷ 	2ð 	2Ø�I‰I�d‹O˜rÑ!÷	2ð 	2ä�u—y‘y Ó*¬DÓ1÷	2ð 	2ð ×1Ð1œD  x¥Ó1÷	2ð 	2ô �u—y‘y “¬¬e¨Ó5÷		2ð 	2ô
 ˜5Ÿ9™9 T›?¬DÓ1Ô1ð3r6   c               ó0   € V ^8„  d   QhRRRRRRRRR	R
RR/# )r.   rÂ   r   rÄ  r=   r&  r1   r7  r�   r3  r  r@   rZ  r2   )r3   s   "r4   r5   r5   ]  s8   € ÷ ñ ˜Cð  Sð ¨uð ÀDð Ø"%ðØGTñr6   c               ó.  € V'       d   \        V\        4      p\        WVR7      '       g   R# W R,          ,
          pYPP                  R4      '       d   \        MT8  d   R# V R,          '       d%   V P                  R4      '       g   V\
        8  d   R# R# )aÓ  How :func:`cached_provider_model_ids` serves *entry* without the network.

``"fresh"`` inside the row's TTL (a curated fallback row only for
``_PROVIDER_MODELS_FALLBACK_TTL``), ``"stale"`` for a non-empty, non-fallback row inside
``_PROVIDER_MODELS_STALE_SERVE_MAX`` (served while an SWR thread revalidates), else ``None``:
the call would block on a live fetch. Empty native catalogs are authoritative only inside the
short native TTL, never through the stale window.r9  NrÅ  rÐ  r<  r›  r8  )Úminr"   rÌ  rI   Ú_PROVIDER_MODELS_FALLBACK_TTLÚ _PROVIDER_MODELS_STALE_SERVE_MAX)rÂ   rÄ  r&  r7  r3  r;  s   &&&$$ r4   r;  r;  ]  so   € ÷ Ü˜+Ô'EÓFˆÜ˜e°Y×?Ó?ÙØ
�d•Õ
€CØ
¯y©y¸×/DÒ/DÕ+È+ÔVÙØˆX‡„˜uŸy™y¨×4Ò4¸Ô?_Ô9_ÙÙr6   ro  r<  c               ó<   € V ^8„  d   QhRRRRRRRRRR	R
RRRRRRR/	# )r.   r0  r   r}   rZ  r0   r1   ro  r9   r>   rÜ   r�   rÃ  r3  r  r@   r´  r2   )r3   s   "r4   r5   r5   r  sh   € ÷ H$ñ H$ØðH$Ø)ðH$Ø7<ðH$àðH$à-EðH$ð ðH$ð .2ðH$ð
 ðH$ð
 7JñH$r6   c               óÆ  a aaaaaaaaa€ ^ RI Ho V3R lp	RVV3R lloV VVVVV3R lo\        S;'       g    R4      P                  4       P	                  R4      P                  4       p
V
'       g   V'       d   R# \        S! 4       4      # \        S SS4      oRV
 R	S 2p\        4       pVP                  V4      p\        P                  ! 4       p\        V\        4      ;'       d    VP                  R
4      RJ pV'       * ;'       d    \        VSVR7      pV'       dU   WíR,          ,
          pVV8  d	   V	! V4      # VR,          '       d(   V\        8  d   VVV3R lp\        VV4       V	! V4      # V'       d   R# S! 4       pV'       g   \        VS4      '       d   S! VV4      p\!        VV4       V	! V4      # \        VS4      '       d	   V	! V4      # \        V4      # )aK  Disk-cached :func:`fetch_api_models` for custom endpoints. ``cache_only`` callers (GUI picker
opens that must not block on a stopped local endpoint) still get a warm catalog instead of
collapsing to the config-declared subset. ``fetch_models`` supplies native-aware discovery
without minting a command token before cache admission.)Ú_NativePickerModelListc                ór   <€ V P                  R 4      '       d   SM\        ! V R,          4      p\        V4      # )Únative_catalogr›  )rI   rt   r¨  )rÂ   rž  rl  s   & €r4   Ú_catalogÚ)cached_fetch_api_models.<locals>._catalog~  s4   ø€ Ø*/¯)©)Ð4D×*EÒ*EÑ&Ì4ÐOÐQVÐW_ÕQ`ÓaˆÜ! $Ó'Ð'r6   Nc                ó<   <€ / \        SW4      CR \        V S4      /C# )rn  )rÈ  r[   )rÑ  rÅ  rl  rÄ  s   &&€€r4   Ú_entryÚ'cached_fetch_api_models.<locals>._entry‚  s%   ø€ Øi”,˜r 4Ó,ÐiÐ.>Ä
È4ÐQgÓ@hÑiÐir6   c                 óR   <€ Se   S! 4       # ^ RI Hp  \        V ! S4      SSSSR7      # )N)Úmaterialize_probe_api_key)r0   ro  r9   )r`  ru  rT  )ru  r0  ro  r}   r<  r9   r0   s    €€€€€€r4   Ú_liveÚ&cached_fetch_api_models.<locals>._live…  s:   ø€ ØÒ#Ù“>Ð!ÝHÜÑ 9¸'Ó BÀHÐV]Ðhpð  {Bô  Cð  	Cr6   rC   rG  r+  r4  rn  Tr9  rÅ  r›  c                 óZ   <€ S! 4       p V '       g   \        V S4      '       d	   S! V 4      # R # rk   )r[   )rÑ  rl  rr  rv  s    €€€r4   Ú_refresh_customÚ0cached_fetch_api_models.<locals>._refresh_custom§  s)   ø€ Ù“w�ß'+¬z¸$Ð@V×/WÒ/W‘v˜d“|ÐaÐ]aÐar6   rk   )Ú!hermes_cli.model_switch_providersrl  r=   rU  rK  rJ   r¨  rb  r×  rI   r¡   r[   r\   rÌ  ri  rð  rÞ  )r0  r}   r0   ro  r9   rÜ   rÃ  r<  r3  ro  Únormalized_urlrM  r˜   rÂ   r&  Ú
native_rowÚvalidr;  ry  rÑ  Ústoredrl  rr  rv  rÄ  s   ffddd$$d$            @@@@r4   Úcached_fetch_api_modelsr€  r  s¡  ÿù€ õ Iõ(÷jð j÷Cò Cô ˜Ÿ˜ RÓ(×.Ñ.Ó0×7Ñ7¸Ó<×BÑBÓD€Nßß!ˆtÐBÔ'9¹%»'Ó'BÐBô 
& g¨x¸Ó	A€BØ˜.Ð)¨¨2¨$Ð/€IÜ'Ó)€EØ�I‰I�iÓ €EÜ
�)Š)‹+€CÜ˜E¤4Ó(×PÐP¨U¯Y©YÐ7GÓ-HÈDÐ-P€JØÔ×WÐWÔ"4°U¸BÈJÔ"W€EçØ˜$•KÕˆØ�ÔÙ˜E“?Ð"ð ��?Œ?˜sÔ%EÔE÷
bô ˜y¨/Ô:Ù˜E“?Ð"çÙá‹7€DßŒz˜$Ð 6×7Ò7Ù˜˜cÓ"ˆÜ˜9 fÔ-Ù˜ÓÐô ˜% ×$Ò$Ù˜‹ÐÜ˜dÓ#Ð#r6   )ÚminimalÚlowr»  Úhigh)r‚  r»  rƒ  r`  )rC   rC  )rn  )g       @rk   >   úox-alpha-freeúx-preview-f-freeúdeepseek-v4-flash-free>   r…  ró  rÎ  r„  rÌ  rÏ  i€:	 )rC  >   ú
/responsesú/v1/messagesú/chat/completions)NrC  )NN)rØ  rÙ  )©)zgpt-zgrok-z
muse-sparkrÐ  ))rz  zminimax-Úqwenúunion-alpharn  )))rz  rŒ  rn  rŠ  ))r‹  rn  )NF)rC  NN>   ÚsttÚttsrˆ  Úembedú	image-genú	video-gen(&  Ú__conditional_annotations__Ú__doc__Ú
__future__r   rë  rš  rB   rL   Úloggingrö  rÊ  rË  rí  rÑ  rD   Úurllib.requestÚurllib.errorr¡   Úpathlibr   Útypingr   r   r   r   Úhermes_cli.route_identityr   Úhermes_cli.urllib_securityr
   Úhermes_cli.version_infor   r  r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   Ú hermes_cli.models_reasoning_capsr   r    Úhermes_cli.models_localr!   r"   r#   r$   r%   r&   r'   r(   r)   r*   Ú	getLoggerrÍ  r¯   r  r  r±  rœ  r�  rÆ  rÅ  r8   rQ   r®   r_   ri   r{   r‰   r‹   Ú__annotations__r‘   rš   rª   r³   r´   rÀ   rÇ   rÐ   r×   rì   rô   rø   r  r  r  r  r  r*  rL  r+  r,  r/  r<  rB  râ   rX  rã   rm  ru  r  r„  r˜  rœ  r¢  r©  rª  r«  Ú_openrouter_caps_disk_checkedÚ_openrouter_caps_warm_startedr¬  r­  Ú_nous_caps_disk_checkedÚ_nous_caps_warm_startedÚagent.reasoning_effortr®  r¯  r¶  r°  r·  r¼  rÂ  r×  rÒ   rŽ  ræ  rï  rò  rå   rõ  rf  r6  ÚRuntimeErrorr¢   r£   ÚAttributeErrorr  r	  r  r"  r6  r  r=  r9  rG  rR  rl  rY  r]  ra  rd  rj  r„  rŒ  rˆ  r’  r–  r¢  rž  r¥  r-  r¸  r¼  r{  rÆ  rÅ  rÖ  rÚ  rã  rë  rþ  r  r  r  r(  r3  r=  r>  r4  r@  rE  rM  r  rU  rY  r_  rj  rp  ru  r€  rŽ  Ú	frozensetr¢  r—  r•  r“  r�  r¨  r±  rµ  r¿  r»  r\  Ú_PROVIDER_MODELS_CACHE_TTLri  rh  rÂ  ÚLockrß  rÈ  rÍ  rÑ  rð  ró  rÖ  r×  r"  rÞ  r/  r2  r>  rI  rO  r\  ry  r‚  rŠ  r�  r’  r”  r•  r–  r™  rž  rŸ  r   r¡  rª  r®  r²  rD  r¸  r¿  rÇ  rÍ  rÒ  r×  rà  rá  ræ  rç  rì  rð  rö  r  r  r  r  r  r'  ÚcompilerF  r(  r5  r6  r)  r*  r;  r.  r7  r=  rK  rŠ  rQ  rV  r‡  rT  rb  rÌ  r;  r€  )r’  s   @r4   Ú<module>r¬     s6
  øðôõ #ã Û Û Û Û Û 	Û 	Û 
Û Û Û Û Û Ý ß /Ñ /çÝ å >Ý <Ý 4÷÷ ÷ ÷ ÷ ñ ÷(÷
÷ 
÷ 
ð 
×	Ò	˜8Ó	$€ð #Ñ#3Ó#5×#BÑ#BÐ"CÐDÐ à2Ð Ø(Ð)¨Ð1Ð Ø)Ð Û!EÐ Û%>Ð "ðPÐ_c÷ Pð

)ØEIð
)ØRV÷
)ð4¨9÷ 4õ1ñ AY÷ õð$ ;?Ð Ð7Ó >õ&õKð¸÷ õ&Nð ;?Ð Ð7Ó >õõSõ
rõMõcò6Cà÷Cð CòDà÷Dð DõCð8  Ð �cÓ Ø24Ð Ð/Ó 4õõð°ð È5÷ ð8  >Ð Ø#&Ð ˜SÓ &àOQÐ ÐLÓ QõGõ
õQò"ØNS÷"ð "õJ	1õ^ðsØðsØ9=ðsØVXðsà÷s÷&
*ð 
*õ3÷0 ð  õF*õB
'õ@õCð PTÐ  Ð"LÓ SØ59Ð $ lÓ 9Ø %Ð Ø %Ð ØIMÐ ÐFÓ MØ/3Ð  Ó 3ØÐ ØÐ ÷ fÑ eõ4õ	õ"ò CØ38ðCØMR÷Cð CðLT u÷ Tõ
<õ;ò Ø38÷ ð  ðFT°%÷ Tñ #&Ð&6Ó"7¹#Ð>OÓ:PÕ"PÐT`ÐbjÐSkÕ"kÐ �xÓ kð ˜w¨°iÀÈ^Ð\€õõ*õPð(ØMQ÷(õ>Eõ
õ"	õhò	OÐW[÷ 	Oð 	Oð !Ð õ	ð%ð  ÷%õ6/õcõ
8õõ<Gõ@õ2õõ,+*õ\õ<	õ9õFõeõ7õ3õ2õ0õ.,ðeØ:>ðeØZ^ðeà÷eõ&õ$Eõõ4õ
;õ'õ(Mð, !&Ð Ø $Ð ØPTÐ ÐMÓ Tõõ.	Fõ0õ õõSõ"Bõ" )õFJõõð6.-ØÑZð.-à�Nð.-ð Ðð.-ð Ð#ð	.-ð
 ˆMð.-ð Ðð.-ñ 
Ð!ð.-ñ Ð#ð.-ñ ÒVð.-ñ Òmð.-ñ Òtð.-ñ ˆoð.-ñ �/ð.-ð  ˆoð!.-ñ" Ðð#.-ñ$ Ð+ð%.-Ð ™Nô -ñ2 "+ÛCó"Ð ÷
e÷B	<÷<÷ ó-÷$O÷Nñ4 !*ÛEó!Ð ÷
oð00È÷ 0ñ 0ñT "Ð ñ $1Ð  ð !#Ð ñ !›UÐ ‘sÔ "Ø—N“NÓ$Ð ÷Wò W÷
<ò <÷@÷%qò %q÷P<÷
a<÷H÷÷
E÷f÷rð
?Ø6;ñ?à1ñ?àHM÷?ñ ?÷D ò  ÷Fò$=Ø7;ñ=ØVZ÷=ò =÷@_ñ

A±T÷ 
Añ 
Aó NÐ ñØ8=÷ñ ñ&ÐTY÷ ñ ð$ ?CÐ Ñ;Ô BØ15Ð ¡Ô 5Ù*-Ð  ¡%Ô -Ù"%Ð ÷#ò #ðR *,Ð ™Ô +Ù%(Ð ™UÔ (Ø,0Ð ™MÔ 0Ù!Ð ÷ò ÷8÷[ò [÷
[ò [ñ#ØJNñ#à!÷#ñ #÷L	ð 	÷^ð ^ñØJNñà!÷ò ÷kð kñ 5Ñ ÷Lð L÷$	ð 	ñ" ñ Pñ ñ +ð	S,Ñ ÑOô ,÷ð ñ )©&±-ÁÐKÑ ÷?ð ?ñ8OØJNñOà!÷Oò OðD &(Ñ Ñ"Ô 'Ù�÷.ð .÷(ó (÷MBó MBðd Ÿ
›
ñ1ó2Ñ ñ +4ó 5=ó +>Ñ ™ô >ñ DÑ Ù6Ñ ð 35Ñ Ñ/Ô 4ð 24Ñ Ñ.Ô 3Ù!Ñ ÷<ð <÷Fð FñØðØ38÷ò ñ<Ø"%ðØ=B÷ò ò4SØ38÷Só Sð;¸5÷ ;ò ;÷*ó *÷ó ÷* ó  ÷
^ð 
^ñ3Ø05÷3ò 3ñØ(B÷ò ñ*H$Ø?BñH$à"ðH$àHLðH$ð  ðH$ð 5:ñH$ð ñ	H$ð
 2÷H$ô H$r6   