+
    jHàjY†  ã                  ó  a€ 0 t $ R t^ RIHt ^ RIt^ RIHt ^ RIHtH	t	H
t
HtHt ^ RIHtHt ]P                   ! ]4      t]! RR7       ! R R	4      4       t/ R
]! RRR7      bR]! RRR7      bR]! RRR7      bR]! RRRR7      bR]! RRRR7      bR]! RRRRR 7      bR!]! RR"R#R$7      bR%]! RÙR&R'R(7      bR)]! RR*R+R,R 7      bR-]! RÚR.7      bR/]! R0RÛR17      bR2]! RÜR3R47      bR5]! R6R77      bR8]! RÝR9R:R(7      bR;]! R0R<R=7      bR>]! R0RR?R7      bR@]! R0RAR=7      b/ RB]! RCR77      bRD]! RER77      bRF]! RGR77      bRH]! RRI7      bRJ]! RRKR7      bRL]! RRMR7      bRN]! RROR7      bRP]! RRQR7      bRR]! RRSR7      bRT]! RRRR7      bRU]! RVRWRX7      bRY]! RZR77      bR[]! R\R77      bR]]! R0R^R_R7      bR`]! RaRbRX7      bRc]! RÞRdReR(7      bRf]! RßRgRhR(7      bCRi]! RàRjRk7      Rl]! RmRáRnRoRp7      Rq]! RâRrRsR(7      Rt]! RãRuRvR(7      Rw]! RxRyRX7      Rz]! R{R77      R|]! R}R~R7      R€]! R€R�7      /CtR‚]Rƒ&   ] ! R„ R…4      4       t/ RRäbR2RåbRTRæbRRçbRURèbR5RébR8RêbR@RëbR/RìbR-RíbR)RîbRRïbRHRðbRJRñbRLRòbRNRóbRBRôb/ RDRõbRFRöbRPR÷bRRRøbRYRùbR[RúbR]RûbR|RübR`RýbRfRþbRiRÿbRqER bRlERbRtERbR%ERbR†ERbCtRŠ]R‹&   ]P1                  4        U UUu/ uF  w  rV F  q"V bK  	  K  	  uppp tRŒ]R�&   / R
RŽbRR�bRR�bR)R‘bR8R’bRYR“bRfR”bRqR•bRlR–bR[R—bRtR˜bR]R™bR%RšbR†R›bR|RœbR€R�bRwRžbRRŸ/CtRŒ]R &   R¡RmR0R0RRR}R}/tRŒ]R¢&   R£ R¤ ltERR¥ R¦ lltERR§ R¨ l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#]$! RLRJ04      t%R´]Rµ&   R¶ R· lt&R¸ R¹ lt']$! RºR»04      t(R´]R¼&   ERR½ R¾ llt)ERR¿ RÀ llt*RÁ RÂ lt+ERRÃ RÄ llt,ERRÅ RÆ llt-RÇ RÈ lt.ERRÉ RÊ llt/ERRË RÌ llt0RÍ RÎ lt1RÏ RÐ lt2R‡t3]3RˆR‰3t4RÑ]RÒ&   RÓ RÔ lt5RÕ RÖ lt6ER	R× RØ llt7R# u uppp i (
  z=Single source of truth for provider identity in Hermes Agent.)ÚannotationsN)Ú	dataclass)ÚAnyÚDictÚListÚOptionalÚTuple)Úbase_url_host_matchesÚbase_url_hostnameT)Úfrozenc                  óp   € ] tR t^t$ RtRtR]R&   RtR]R&   RtR]R	&   Rt	R
]R&   Rt
R]R&   RtR]R&   RtR# )ÚHermesOverlayz?Hermes-specific provider metadata layered on top of models.dev.Úopenai_chatÚstrÚ	transportFÚboolÚis_aggregatorÚapi_keyÚ	auth_typeútuple[str, ...]Úextra_env_varsÚ Úbase_url_overrideÚbase_url_env_var© N)Ú__name__Ú
__module__Ú__qualname__Ú__firstlineno__Ú__doc__r   Ú__annotations__r   r   r   r   r   Ú__static_attributes__r   ó    Ú9/home/ubuntu/.hermes/hermes-agent/hermes_cli/providers.pyr   r      sC   ‡ áIà"€IˆsÓ"Ø€M�4ÓØ€IˆsÓØ&(€N�OÓ(ØÐ�sÓØÐ�c×r"   r   ÚmoaÚvirtualzmoa://local)r   r   Ú
openrouterÚOPENROUTER_BASE_URL)r   r   ÚnousÚoauth_device_codez)https://inference-api.nousresearch.com/v1zopenai-codexÚcodex_responsesÚoauth_externalz%https://chatgpt.com/backend-api/codex)r   r   r   z
openai-apizhttps://api.openai.com/v1ÚOPENAI_BASE_URL)r   r   r   ú	xai-oauthzhttps://api.x.ai/v1ÚXAI_BASE_URL)r   r   r   r   z
qwen-oauthzhttps://portal.qwen.ai/v1ÚHERMES_QWEN_BASE_URL)r   r   r   Úlmstudiozhttp://127.0.0.1:1234/v1ÚLM_BASE_URL)r   r   r   zcopilot-acpÚexternal_processzacp://copilotÚCOPILOT_ACP_BASE_URLzgithub-copilot)r   Ú	anthropicÚanthropic_messages)r   r   ÚzaiÚGLM_BASE_URL)r   r   zkimi-for-codingÚKIMI_BASE_URL)r   Ústepfunz#https://api.stepfun.ai/step_plan/v1ÚSTEPFUN_BASE_URLÚminimaxÚMINIMAX_BASE_URL)r   r   zminimax-oauthz https://api.minimax.io/anthropicz
minimax-cnÚMINIMAX_CN_BASE_URLÚdeepseekÚDEEPSEEK_BASE_URLÚalibabaÚDASHSCOPE_BASE_URLzalibaba-coding-planÚALIBABA_CODING_PLAN_BASE_URLÚvercel)r   ÚopencodeÚOPENCODE_ZEN_BASE_URLzopencode-goÚOPENCODE_GO_BASE_URLÚkiloÚKILOCODE_BASE_URLÚhuggingfaceÚHF_BASE_URLÚnovitaÚNOVITA_BASE_URLÚxaiÚnvidiaz#https://integrate.api.nvidia.com/v1ÚNVIDIA_BASE_URL)r   r   ÚxiaomiÚXIAOMI_BASE_URLztencent-tokenhubÚTOKENHUB_BASE_URLztencent-tokenplanz2https://api.lkeap.cloud.tencent.com/plan/anthropicÚTOKENPLAN_BASE_URLÚarceezhttps://api.arcee.ai/api/v1ÚARCEE_BASE_URLÚcommandcodez&https://api.commandcode.ai/provider/v1ÚCOMMANDCODE_BASE_URLÚgmizhttps://api.gmi-serving.com/v1ÚGMI_BASE_URLÚ	fireworksz%https://api.fireworks.ai/inference/v1)r   r   ÚactualÚchat_completionszhttps://api.actual.inc/v1ÚACTUAL_BASE_URL)r   r   r   r   Úupstagezhttps://api.upstage.ai/v1ÚUPSTAGE_BASE_URLznebius-token-factoryz&https://api.tokenfactory.nebius.com/v1ÚNEBIUS_BASE_URLzollama-cloudzhttps://ollama.com/v1ÚOLLAMA_BASE_URLzazure-foundryÚAZURE_FOUNDRY_BASE_URLÚbedrockÚbedrock_converseÚaws_sdk)r   r   Úvertex)r   zdict[str, HermesOverlay]ÚHERMES_OVERLAYSc                  ó˜   € ] tR t^et$ RtR]R&   R]R&   R]R&   R]R&   RtR]R	&   RtR]R
&   RtR]R&   Rt	R]R&   Rt
R]R&   RtR]R&   RtR# )ÚProviderDefuP   Complete provider definition â€” merged from models.dev + overlay + user config.r   ÚidÚnamer   r   Úapi_key_env_varsr   Úbase_urlr   Fr   r   r   r   ÚdocÚsourcer   N)r   r   r   r   r   r    rm   r   r   r   rn   ro   r!   r   r"   r#   ri   ri   e   sV   ‡ áZàƒGØ
ƒIØƒNØ%Ó%Ø€HˆcÓØÐ�cÓØ€M�4ÓØ€IˆsÓØ€CˆƒMØ€FˆC×r"   ri   ÚcustomÚllamacppú	llama.cppú	llama-cppzdict[str, tuple[str, ...]]Ú_ALIAS_GROUPSzdict[str, str]ÚALIASESzMixture of AgentszNous PortalzChatGPT or Codex SubscriptionzGitHub Copilot ACPzStepFun Step PlanzXiaomi MiMoz	GMI CloudzUpstage SolarzActual ComputerzTencent TokenHubzNebius Token FactoryzTencent TokenPlanz	LM StudiozCustom endpointzAWS BedrockzGoogle Vertex AIzOllama Cloudz%xAI Grok OAuth (SuperGrok / Premium+)Ú_LABEL_OVERRIDESr   ÚTRANSPORT_TO_API_MODEc               ó    € V ^8„  d   QhRRRR/# )é   rk   r   Úreturnr   )Úformats   "r#   Ú__annotate__r|   ¨   s   € ÷ !ñ !˜Sð ! Sñ !r"   c                óh   € V P                  4       P                  4       p\        P                  W4      # )z@Resolve aliases and normalise casing to a canonical provider id.)ÚstripÚlowerru   Úget)rk   Úkeys   & r#   Únormalize_providerr‚   ¨   s%   € à
�*‰*‹,×
Ñ
Ó
€CÜ�;‰;�sÓ Ð r"   c               ó$   € V ^8„  d   QhRRRRRR/# )ry   Úproviderr   rm   rz   r   r   )r{   s   "r#   r|   r|   ®   s!   € ÷ ñ ˜cð °#ð ¸tñ r"   c                ó^   € \        T ;'       g    R4      R8H  ;'       g    \        V4      R8H  # )zRIdentify Actual by provider/alias or its hosted endpoint, including custom routes.r   r[   úapi.actual.inc)r‚   r
   )r„   rm   s   &&r#   Úis_actual_router‡   ®   s4   € ô 	˜8Ÿ>˜> rÓ*¨hÑ6÷ 	;ð 	;Ü˜XÓ&Ð*:Ñ:ðr"   c               ó    € V ^8„  d   QhRRRR/# )ry   Ú	canonicalr   Úallow_networkr   r   )r{   s   "r#   r|   r|   ¶   s   € ÷ ñ  ð °Dñ r"   c                óh   €  ^ RI Hp V'       d	   V! V 4      # V! V RR7      #   \         d     R# i ; i)z„models.dev entry or None. Single-arg call on the default path: test sites monkeypatch
``get_provider_info`` with single-arg lambdas.)Úget_provider_infoF)rŠ   N)Úagent.models_devrŒ   Ú	Exception)r‰   rŠ   Ú_mdev_providers   && r#   Ú_models_dev_infor�   ¶   s6   € ðÝHß,9‰~˜iÓ(Ðm¹~ÈiÐglÔ?mÐmøÜô Úðús   ‚" �" ˜	" ¢1°1c               ó    € V ^8„  d   QhRRRR/# )ry   Úovr   rz   ri   r   )r{   s   "r#   r|   r|   À   s   € ÷ &ñ & ð &ÐZeñ &r"   c                óx   € \        WVP                  W4VP                  VP                  VP                  VVR 7
      # ))
rj   rk   r   rl   rm   r   r   r   rn   ro   )ri   r   r   r   r   )r‰   r’   rk   Úenv_varsrm   rn   ro   s   &&&&&&&r#   Ú_overlay_pdefr•   À   s:   € Ü˜)¸"¿,¹,ÐYaØ(*×(;Ñ(;È2×K[ÑK[Ðgi×gsÑgsÐy|Ø$ô&ð &r"   rŠ   c               ó$   € V ^8„  d   QhRRRRRR/# )ry   rk   r   rŠ   r   rz   úOptional[ProviderDef]r   )r{   s   "r#   r|   r|   Æ   s"   € ÷ ñ �sð ¨dð Ð>Sñ r"   c          	     óÊ  € \        V 4      p\        W!4      p\        P                  V4      pVe¡   T;'       g    \	        4       p\        VP                  4      pVP                   F  pWv9  g   K  VP                  V4       K  	  \        Y%VP                  \        V4      VP                  ;'       g    VP                  VP                  R4      # Ve8   \        W$\        P                  W"4      VP                  VP                  RR4      # \!        V4      pVeH   VP"                  '       g8   VP$                  R8X  d%   VP&                  '       d   VP(                  '       g   R# V# )uÀ   Look up a built-in provider by id or alias: models.dev catalog merged with the Hermes overlay;
Hermes-only overlay (nous, openai-codex, â€¦); plugin provider profiles with a concrete endpoint.Nú
models.devr   Úhermesr   )r‚   r�   rg   r€   r   ÚlistÚenvr   Úappendr•   rk   Útupler   Úapirn   rv   Ú_plugin_profile_pdefrm   r   rl   r   )	rk   rŠ   r‰   Ú	mdev_infoÚoverlayr’   r”   ÚevÚpdefs	   &$       r#   Úget_providerr¥   Æ   s(  € ô # 4Ó(€IÜ  Ó:€IÜ×!Ñ! )Ó,€GØÒØ×'Ð'œ›ˆÜ˜	Ÿ™Ó&ˆØ×#Ô#ˆBØÖ!Ø—‘ Ö#ñ $ô ˜Y¨I¯N©N¼EÀ(»OÈR×MaÑMa×MrÐMrÐen×erÑerØ&Ÿ]™]¨Ló:ð 	:àÒÜ˜YÔ1A×1EÑ1EÀiÓ1[Ð]d×]sÑ]sØ$×6Ñ6¸¸HóFð 	Fô   	Ó*€DØ‚|˜DŸMŸM˜M¨d¯n©nÀ	Ô.IÈd×Nc×NcÐNcÐhl×h}×h}Ðh}ÙØ€Kr"   c               ó    € V ^8„  d   QhRRRR/# )ry   rk   r   rz   r—   r   )r{   s   "r#   r|   r|   å   s   € ÷ Wñ W˜sð WÐ'<ñ Wr"   c                ó:  a	€  ^ RI Hp V! V 4      pTf   R# \        TP                  ;'       g    R
4      p\        ;QJ d    . R T 4       F  NK  	  5M! R T 4       4      o	\        ;QJ d    . T	3R lT 4       F  NK  	  5M! T	3R lT 4       4      p\
        P                  4        UUu/ uF  w  rVYebK	  	  pppTP                  ;'       g    RP                  4       p\        TP                  TP                  ;'       g    TP                  ;'       g    T TP                  Yˆ;'       g    R4      YBP                  ;'       g    RP                  4       \        \        S	4      R4      TP                   ;'       g    RRR	7      #   \         d     R# i ; iu uppi )a  The registered ``ProviderProfile`` for *name* (or one of its aliases) as a ProviderDef; the
id is the profile's canonical name so an alias switch persists and resolves credentials under
the same identity as the profile itself. URL-shaped env vars are the endpoint, not the key.)Úget_provider_profileNc              3  óV   "  € T F  qP                  R4      '       g   K  Vx € K!  	  R# 5i)Ú	_BASE_URLN)rª   Ú_URL)Úendswith)Ú.0Úvs   & r#   Ú	<genexpr>Ú'_plugin_profile_pdef.<locals>.<genexpr>ñ   s   é € ÐN¡˜1¯J©JÐ7L×,M—Q’Q£ùs   ‚)Ÿ
)c              3  ó8   <"  € T F  qS9  g   K  Vx € K  	  R # 5i)Nr   )r­   r®   Úurl_varss   & €r#   r¯   r°   ò   s   øé € Ð>¡˜1°XÑ,=—Q’Q£ùs   ƒ�
r   r   r   úplugin-profile)rj   rk   r   rl   rm   r   r   ro   r   )Ú	providersr¨   rŽ   rž   r”   rw   ÚitemsÚapi_moder~   ri   rk   Údisplay_namer€   rm   ÚnextÚiterr   )
rk   Ú_profileÚprofr”   Úkey_varsÚkr®   Úapi_mode_to_transportÚmoder²   s
   &        @r#   r    r    å   sH  ø€ ðÝ>Ù˜‹~ˆð ‚|ÙÜ�T—]‘]×(Ð( bÓ)€HßŒuÑN¡ÓN�u‰uÑN¡ÓNÓN€HßŒuÔ>¡Ó>�u‰uÔ>¡Ó>Ó>€HÜ.C×.IÑ.IÔ.KÔLÑ.K¡d a˜QšTÑ.KÐÑLð �M‰M×Ð˜R×&Ñ&Ó(€DÜ˜$Ÿ)™)¨$×*;Ñ*;×*PÐ*P¸t¿y¹y×*PÐ*PÈDØ!6×!:Ñ!:¸4×AVÐAVÈÓ!WØ(0¿M¹M×<OÐ<OÈR×;VÑ;VÓ;XÜ(,¬T°(«^¸RÓ(@Ø!%§¡×!<Ð!<°9ÐEUô	Wð Wøô ô Úðüó Ms   ƒF Â+FÆFÆFc               ó    € V ^8„  d   QhRRRR/# )ry   Úprovider_idr   rz   r   )r{   s   "r#   r|   r|   þ   s   € ÷ ,ñ ,˜3ð , 3ñ ,r"   c                óŠ   € \        V 4      pV\        9   d   \        V,          # \        V4      pV'       d   VP                  # T# )zOHuman-readable display name: label override, else models.dev name, else the id.)r‚   rv   r¥   rk   )rÁ   r‰   r¤   s   &  r#   Ú	get_labelrÃ   þ   s;   € ä" ;Ó/€IØÔ$Ô$Ü 	Õ*Ð*Ü˜	Ó"€Dßˆ4�9‰9Ð+ )Ð+r"   c               ó    € V ^8„  d   QhRRRR/# ©ry   r„   r   rz   r   r   )r{   s   "r#   r|   r|     s   € ÷ 1ñ 1˜Cð 1 Dñ 1r"   c                ó    € \        T ;'       g    R4      pVP                  R4      '       d   R# \        V4      pV'       d   VP                  # R# )z:Return True when the provider is a multi-model aggregator.r   úcustom:TF)r‚   Ú
startswithr¥   r   )r„   Úprovider_normr¤   s   &  r#   r   r     sC   € ä& x§~ ~°2Ó6€MØ×Ñ 	×*Ò*ÙÜ˜Ó&€Dß!%ˆ4×ÑÐ0¨5Ð0r"   úfrozenset[str]Ú_FLAT_NAMESPACE_RESELLERSc               ó    € V ^8„  d   QhRRRR/# rÅ   r   )r{   s   "r#   r|   r|     s   € ÷ (ñ ( Cð (¨Dñ (r"   c                ó\   € \        T ;'       g    R4      pV\        9   d   R# \        V4      # )uû   True only for TRUE routing aggregators (OpenRouter, named ``custom:*`` proxies) â€” excludes
flat-namespace resellers whose catalog is first-party. Use for "would selecting this model
silently re-route away from the intended provider?" (picker dedup).r   F)r‚   rË   r   )r„   rÉ   s   & r#   Úis_routing_aggregatorrÎ     s+   € ô ' x§~ ~°2Ó6€MØÔ1Ô1ÙÜ˜Ó'Ð'r"   c               ó    € V ^8„  d   QhRRRR/# )ry   rm   r   rz   r   r   )r{   s   "r#   r|   r|   #  s   € ÷ =ñ = cð =¨dñ =r"   c                ó   € \        V R4      # )u“  True when *base_url* points at OpenAI's official API host family. Hostname-parsed matching
only â€” never substring â€” so lookalike hosts (``api.openai.com.attacker.test``) and path-segment
spoofs (``proxy.test/api.openai.com/v1``) are rejected; a genuine ``*.api.openai.com``
subdomain requires control of openai.com DNS.

A genuine ``*.api.openai.com`` subdomain requires control of openai.com DNS, so the dot-suffix match
does not reopen the #32243 spoofing hole. Delegates to ``utils.base_url_host_matches``, which owns the
exact-or-dot-suffix hostname contract (userinfo/port stripped, lowercased, trailing dot removed) â€” one
implementation, not two.
zapi.openai.com)r	   )rm   s   &r#   Úis_official_openai_hostrÑ   #  s   € ô ! Ð+;Ó<Ð<r"   zapi.meta.aizapi.router.comÚ_RESPONSES_NATIVE_HOSTSc               ó    € V ^8„  d   QhRRRR/# )ry   rm   r   rz   zOptional[str]r   )r{   s   "r#   r|   r|   8  s   € ÷ ñ  Sð °-ñ r"   c                ór  € V '       g   R# V P                  R4      P                  4       p\        V 4      pVR8X  d   R# VR8X  d
   RV9   d   R# VR8X  g   VP                  R	4      '       d   R# \	        V 4      '       g   V\
        9   d   R
# VP                  R4      '       d   \        V R4      '       d   R# R# )uï  Return the wire protocol a specific endpoint *requires*, or None. Some hosts accept exactly
one API mode (api.openai.com 400s chat/completions for reasoning models with tools); these are
*mandatory*: a session carrying a stale api_mode (a /model switch that kept the previous
provider's ``chat_completions``) must be overridden, not merely filled in when empty.
Exact-hostname matching only â€” never substring â€” so lookalike hosts and path-segment spoofs are
not treated as the real endpoint.NÚ/r†   r\   zapi.kimi.comz/codingr5   zapi.anthropic.comz
/anthropicr*   zbedrock-runtime.zamazonaws.comrd   )Úrstripr   r
   r¬   rÑ   rÒ   rÈ   r	   )rm   Ú	url_lowerÚhostnames   &  r#   Úhost_mandated_api_moderÙ   8  s§   € ÷ ÙØ—‘ Ó$×*Ñ*Ó,€IÜ  Ó*€HØÐ#Ô#Ù!ð �>Ô! i°9Ô&<Ù#ØÐ&Ô&¨)×*<Ñ*<¸\×*JÒ*JÙ#ô ˜x×(Ò(¨HÔ8OÔ,Oñ !Ø×ÑÐ-×.Ò.Ô3HÈÐSb×3cÒ3cÙ!Ùr"   c               ó    € V ^8„  d   QhRRRR/# )ry   Úmodelr   rz   r   )r{   s   "r#   r|   r|   X  s   € ÷ ñ ˜ð  cñ r"   c                ó¸   € \        T ;'       g    R4      P                  4       P                  4       P                  R4      '       d   \	        4       R8X  d   R# R# R# )añ  Wire protocol for a Nous Portal model. Portal serves its ``anthropic/*`` catalog on a native
Messages route alongside OpenAI-compatible chat/completions for everything else.

``anthropic/*`` rides chat/completions by default for now (``nous.anthropic_wire``). Measured
2026-09-06, 20 concurrent sessions x 6 tool calls on Fable 5.1, same account and hour: the
native route re-wrote the previous turn on 14-20% of consecutive calls (4 runs; the cache read
stopped at the prior breakpoint with byte-identical prefixes), chat/completions 0 of 320 pairs.
That is 15-20% of a fan-out's cache-write bill. The cause is inside the portal's native route
(NousResearch/api#227 carries the diagnostics); flip the default back to ``native`` when it is
fixed. Cost of ``chat``: prior-turn thinking travels as OpenAI-style reasoning fields instead of
signed native blocks, and cache_control scopes are translated by the portal's adapter.
Empty/unknown model defaults to ``chat_completions`` (the historical Nous transport).r   z
anthropic/Únativer5   r\   )r   r~   r   rÈ   Ú_nous_anthropic_wire)rÛ   s   &r#   Únous_api_moderß   X  sN   € ô ˆ5�;ˆ;�BÓ×ÑÓ×%Ñ%Ó'×2Ñ2°<×@Ò@ô (<Ó'=ÀÔ'IÐ#ÐaÐOaÐaÙr"   c               ó   € V ^8„  d   QhRR/# )ry   rz   r   r   )r{   s   "r#   r|   r|   l  s   € ÷ <ñ <˜cñ <r"   c                 ó  €  ^ RI Hp  \        V ! 4       P                  R4      ;'       g    / P                  R4      ;'       g    R4      P	                  4       P                  4       pTR9   d   T# R#   \         d     R# i ; i)zË``nous.anthropic_wire``: ``"chat"`` (default), ``"native"``, or ``"auto"`` (chat, then per-session
promotion decided from the first response; see ``agent/nous_wire.py``). Anything else reads as ``chat``.©Úload_config_readonlyr(   Úanthropic_wireÚchat)rÝ   Úauto)Úhermes_cli.configrã   r   r€   r~   r   rŽ   )rã   Úvalues     r#   rÞ   rÞ   l  s{   € ðÝ:ÜÑ*Ó,×0Ñ0°Ó8×>Ð>¸B×CÑCÐDTÓU×`Ð`ÐZ`Óa×gÑgÓi×oÑoÓqˆð Ð/Ô/ˆ5Ð;°VÐ;øô ô Úðús   ‚'A1 ªA1 Á#A1 Á1B Á?B c               ó(   € V ^8„  d   QhRRRRRRRR/# )ry   r„   r   rm   rÛ   rz   r   )r{   s   "r#   r|   r|   w  s(   € ÷ ñ  ð °ð Àð Ècñ r"   c                óš  € \        W4      '       d   R# \        V4      pVe   V# T ;'       g    RP                  4       P                  4       R9   d   \	        V4      # \        V 4      pVeW   VP                  \        9   d   \        VP                  ,          # ^ RIH	p VP                  V! 4       9   d   VP                  # R# V R8X  d   R# R# )u  API mode (wire protocol) for a provider/endpoint: host-mandated mode, then Nous dual-wire
(model-derived â€” the overlay alone says openai_chat and would pin Claude on the wrong wire),
then the known provider's transport, then bedrock, else ``chat_completions``.r\   r   )Úregistered_api_modesrc   rd   >   r(   Únousresearchúnous-portal)
r‡   rÙ   r~   r   rß   r¥   r   rw   Úagent.transportsrë   )r„   rm   rÛ   Úmandatedr¤   rë   s   &&&   r#   Údetermine_api_moderð   w  s¯   € ô �x×*Ò*Ù!Ü% hÓ/€HØÒØˆØ�ˆ�B×ÑÓ×%Ñ%Ó'Ð+RÔRÜ˜UÓ#Ð#Ü˜Ó!€DØÒØ�>‰>Ô2Ô2Ü(¨¯©Õ8Ð8å9Ø!%§¡Ñ3GÓ3IÔ!Iˆt�~‰~ÐaÐOaÐaØ�9ÔÙ!Ùr"   c               ó0   € V ^8„  d   QhRRRRRRRRRRRR/# )	ry   Úpidr   rk   rm   Úkey_envr   rz   ri   r   )r{   s   "r#   r|   r|   �  s?   € ÷ jñ j�Cð j˜sð j¨cð j¸Cð jÈCð jÐdoñ jr"   c                ó:   € \        YYC'       d   V3MRVRRRR7      # )z```source="user-config"`` ProviderDef shared by ``providers:`` and ``custom_providers:`` entries.Fr   zuser-config)rj   rk   r   rl   rm   r   r   ro   r   )ri   )rò   rk   rm   ró   r   s   &&&&&r#   Ú
_user_pdefrõ   �  s+   € ä˜#°IÖ^eÐQXÑPZÐkmØ (¸ÈÐ[hôjð jr"   c               ó$   € V ^8„  d   QhRRRRRR/# )ry   rk   r   Úuser_configzdict[str, Any]rz   r—   r   )r{   s   "r#   r|   r|   –  s'   € ÷ Nñ N ð N°.ð NÐEZñ Nr"   c           
     ó0  € \        V\        4      '       d   V'       d   VP                  V 4      MRp\        V\        4      '       g   R# VP                  RR4      ;'       g7    VP                  RR4      ;'       g    VP                  RR4      ;'       g    RpV'       g   R# \        YP                  RR4      ;'       g    T TVP                  R4      ;'       g    VP                  R4      ;'       g    RVP                  R	R
4      ;'       g    R
4      # )ug  Resolve a provider from the user's config.yaml ``providers:`` section.

A ``providers.<name>`` block that carries no endpoint (``api``/``url``/``base_url``) is not a
custom-endpoint definition â€” it is tuning for a BUILT-IN provider of the same name (e.g.
``providers.bedrock: {stale_timeout_seconds: 600}``, the documented path in
``agent/turn_recovery.py`` / ``thinking_timeout_guidance.py``). Resolving it here would shadow
the built-in's real transport/base_url/auth_type with an empty ``openai_chat``/``api_key``
stub, routing e.g. AWS Bedrock through the generic custom-endpoint ``/models`` probe (#110402).
NrŸ   r   Úurlrm   rk   ró   Úapi_key_envr   r   )Ú
isinstanceÚdictr€   rõ   )rk   r÷   Úentryrm   s   &&  r#   Úresolve_user_providerrþ   –  sÚ   € ô &0°¼T×%BÒ%BÇ{ˆK�O‰O˜DÔ!ÐX\€EÜ�eœT×"Ò"ÙØ�y‰y˜ Ó#×^Ð^ u§y¡y°¸Ó';×^Ð^¸u¿y¹yÈÐUWÓ?X×^Ð^Ð\^€HßÙÜ�dŸI™I f¨bÓ1×9Ð9°T¸8Ø—i‘i 	Ó*×LÐL¨e¯i©i¸Ó.F×LÐLÈ"Ø—i‘i ¨]Ó;×LÐL¸}óNð Nr"   c               ó$   € V ^8„  d   QhRRRRRR/# )ry   r·   r   Úprovider_keyrz   r   )r{   s   "r#   r|   r|   «  s&   € ÷ Vñ V sð V¸#ð VÀsñ Vr"   c                ó  € \        T;'       g    R4      P                  4       ;'       g$    \        T ;'       g    R4      P                  4       pVP                  4       P                  RR4      pVP	                  R4      '       d   V# RV 2# )zíStable ``custom:`` identity for a configured provider: keyed ``providers:`` entries use their
config key (survives display-name changes); legacy ``custom_providers:`` entries have no key,
so their normalized display name is the identity.r   Ú Ú-rÇ   )r   r~   r   ÚreplacerÈ   )r·   r   ÚidentityÚ
normalizeds   &&  r#   Úcustom_provider_slugr  «  sx   € ô �<×%Ð% 2Ó&×,Ñ,Ó.×QÐQ´#°l×6HÐ6HÀbÓ2I×2OÑ2OÓ2Q€HØ—‘Ó!×)Ñ)¨#¨sÓ3€JØ#×.Ñ.¨y×9Ò9ˆ:ÐUÀÈÈÐ?UÐUr"   c               ó$   € V ^8„  d   QhRRRRRR/# )ry   r·   r   r   rz   rÊ   r   )r{   s   "r#   r|   r|   ´  s!   € ÷ ñ ¨#ð ¸Sð È.ñ r"   c                ó¶  € \        4       pW3 F¾  p\        T;'       g    R4      P                  4       P                  4       pV'       g   K>  VP	                  RR4      pVP                  WE\        V4      04       VP                  R4      '       g   K…  VP                  R^4      ^,          pV'       g   K¨  VP                  VRV 204       KÀ  	  \        V4      # )zCReturn every current and legacy identity accepted for one endpoint.r   r  r  rÇ   Ú:)
Úsetr   r~   r   r  Úupdater  rÈ   ÚsplitÚ	frozenset)r·   r   Úaliasesrè   Úrawr  Úsuffixs   &&     r#   Úcustom_provider_aliasesr  ´  s·   € ä›€GØÓ-ˆÜ�%—+�+˜2Ó×$Ñ$Ó&×,Ñ,Ó.ˆßÙØ—[‘[  cÓ*ˆ
Ø�‰˜Ô)=¸jÓ)IÐJÔKØ× Ñ  ×+Ô+Ø×%Ñ% c¨1Ó-¨aÕ0ˆFß‰vØ—‘ ¨'°*°Ð(>Ð?Ö@ñ .ô �WÓÐr"   c               ó$   € V ^8„  d   QhRRRRRR/# )ry   rk   r   Úcustom_providersúOptional[list[dict[str, Any]]]rz   r—   r   )r{   s   "r#   r|   r|   Ä  s#   € ÷ ñ  #ð Ð9Wð Ð\qñ r"   c           	     óD  € T ;'       g    RP                  4       P                  4       pV'       d   V'       d   \        V\        4      '       g   R# RpV EF5  p\        V\        4      '       g   K  VP                  R4      ;'       g    RP                  4       pVP                  RR4      ;'       g7    VP                  RR4      ;'       g    VP                  RR4      ;'       g    RP                  4       pV'       d	   V'       g   Kµ  VP                  R4      ;'       g    RP                  4       p\        \        WW4      YVVP                  R4      ;'       g    RP                  4       4      pVf   TpV\        WW4      9   g   EK4  Vu # 	  VR	8X  d   V'       d   V# R# )
zÕResolve a provider from the user's config.yaml ``custom_providers`` list. A stored bare
``"custom"`` (corrupt state from a prior model-switch bug) falls back to the first valid entry
so existing configs self-heal.r   Nrk   rm   rù   rŸ   r   ró   rp   )	r~   r   rû   r›   rü   r€   rõ   r  r  )	rk   r  Ú	requestedÚfirst_validrý   r·   Úapi_urlr   r¤   s	   &&       r#   Úresolve_custom_providerr  Ä  sN  € ð —�˜×"Ñ"Ó$×*Ñ*Ó,€Iß×,´JÐ?OÔQU×4VÒ4VÙØ)-€Kô "ˆÜ˜%¤×&Ò&ÙØŸ	™	 &Ó)×/Ð/¨R×6Ñ6Ó8ˆØ—9‘9˜Z¨Ó,×bÐb°·	±	¸%ÀÓ0D×bÐbÈÏ	É	ÐRWÐY[ÓH\×bÐbÐ`b×iÑiÓkˆß§7ÙØŸ	™	 .Ó1×7Ð7°R×>Ñ>Ó@ˆÜÔ.¨|ÓJÈLØ Ÿ9™9 YÓ/×5Ð5°2×<Ñ<Ó>ó@ˆàÒØˆKØÔ/°ÓK×KØŠKñ "ð �HÔ§ØÐÙr"   c               ó$   € V ^8„  d   QhRRRRRR/# )ry   r  r   r‰   rz   r—   r   )r{   s   "r#   r|   r|   á  s"   € ÷ ñ  Cð °Cð Ð<Qñ r"   c           	     óJ  a€  ^ RI Hp VP                  V 4      pVf   R# \        V3R lV 4       4      ^8”  dW   \	        VP
                  VP                  R\        VP                  ;'       g    R4      VP                  ;'       g    RRR7      #  R#   \         d     R# i ; i)	a°  Exact Hermes registry ids win over LOSSY alias collapsing (kimi-coding-cn must stay distinct
from kimi-coding instead of collapsing through the shared models.dev alias "kimi-for-coding").
A collapse is lossy only when MULTIPLE registry providers normalize to the same canonical name;
single-entry rewrites ("copilot" -> "github-copilot") are correct routing and keep resolving
through the built-in chain so overlay transports apply.)ÚPROVIDER_REGISTRYNc              3  óL   <"  € T F  p\        V4      S8X  g   K  ^x € K  	  R# 5i)é   N)r‚   )r­   Ú_ridr‰   s   & €r#   r¯   Ú-_lossy_alias_registry_pdef.<locals>.<genexpr>ì  s#   øé € Ð^Ñ4�TÔ8JÈ4Ó8PÐT]Ñ8]�qŠqÓ4ùs   ƒ$š
$r   r   zhermes-auth-registry©rj   rk   r   rl   rm   ro   r   )Úhermes_cli.authr  r€   Úsumri   rj   rk   rž   rl   Úinference_base_urlrŽ   )r  r‰   Ú_AUTH_PROVIDER_REGISTRYÚ_pcfgs   &f  r#   Ú_lossy_alias_registry_pdefr(  á  s¡   ø€ ð
ÝPØ'×+Ñ+¨CÓ0ˆØŠ=ÙÜÔ^Ñ4Ó^Ó^ÐabÔbÜ %§(¡(°·±À}Ü05°e×6LÑ6L×6RÐ6RÐPRÓ0SÐ^c×^vÑ^v×^|Ð^|Ðz|Ø&<ô>ð >ð cñ øô ô ØÙðús#   ƒB  AB Á.B ÂB ÂB"Â!B"r   ÚLLAMACPP_ALIASESc               ó   € V ^8„  d   QhRR/# )ry   rz   r   r   )r{   s   "r#   r|   r|   ü  s   € ÷ ñ  $ñ r"   c                 óT   €  ^ RI Hp  \        V ! 4       4      #   \         d     R# i ; i)uµ   True when GGUFs are staged under the Hermes home's ``models/`` â€” the model the picker's Local
row offers, which the runtime seam serves by booting/attaching a server on selection.©Ústaged_model_idsF)Ú"hermes_cli.local_runtime.bootstrapr-  r   rŽ   r,  s    r#   Ú_has_staged_local_modelsr/  ü  s+   € ðÝGÜÑ$Ó&Ó'Ð'øÜô Úðús   ‚ ˜'¦'c               ó   € V ^8„  d   QhRR/# )ry   rz   r—   r   )r{   s   "r#   r|   r|     s   € ÷ ^ñ ^Ð-ñ ^r"   c            
     óò   €  ^ RI Hp  ^ RIHp V! V ! 4       ^ R7      pV'       g   \        4       '       g   R# \        \        RRRT;'       g    / P                  RR4      R	R
7      #   \         d    Rp LXi ; i)u?  The llamacpp aliases are a real provider whenever the managed server (or a detected external
one) resolves â€” reachability is the credential â€” OR a model is staged for the runtime to serve.
The picker's Local row is built from staged GGUFs and is deliberately offline-first (selection
starts the server through the runtime seam), so requiring a live endpoint before admitting the id
made that row offer a provider the resolver rejected ("Unknown provider 'llamacpp'"). Without
this rung model-switch rejected the very provider the Local Models 'Use' flow writes to config.râ   )Úresolve_llamacpp_endpoint)ÚconfigÚwait_for_boot_sNÚLocalr   rm   r   zlocal-runtimer"  r   )	rç   rã   Ú!hermes_cli.local_runtime.endpointr2  rŽ   r/  ri   ÚLLAMACPP_PROVIDER_IDr€   )rã   r2  Úendpoints      r#   Ú_llamacpp_pdefr9    sv   € ðÝ:ÝOÙ,Ñ4HÓ4JÐ\]Ô^ˆ÷ Ô4×6Ò6ÙÜÔ.°WÈÐhjØ!)§ ¨R× 4Ñ 4°ZÀÓ DÈ_ô^ð ^øô	 ô ØŠðús   ‚A& Á&A6Á5A6c               ó(   € V ^8„  d   QhRRRRRRRR/# )	ry   rk   r   Úuser_providerszOptional[dict[str, Any]]r  r  rz   r—   r   )r{   s   "r#   r|   r|     s1   € ÷ 1Fñ 1F ð 1FÐ5Mð 1FØ,Jð1FØVkñ1Fr"   c           	     óÊ  € \        V 4      pV P                  4       P                  4       pV'       d   \        WA4      pVe   V# W48w  d   \	        WC4      pVe   V# \        V4      pVe8   VP                  R8X  d%   V'       d   \        VP                  V4      pVe   V# V# V'       d   W43 F  p\        Wq4      pVf   K  Vu # 	  \        W4      pVe   V# V\        9   d   \        4       pVe   V#  \        V4      p	V	e/   \        W9P                  RV	P                  V	P                  RR7      #  \#        V4      pVe   VP                  R8w  d   V# R#   \          d     L1i ; i)a­  Full resolution chain: user ``providers.<raw name>`` -> lossy-alias registry id -> built-in
(models.dev + overlays) -> user providers (canonical, then raw) -> ``custom_providers`` ->
managed llamacpp -> models.dev directly. User-defined ``providers.<name>`` is tried FIRST on
the raw (pre-alias) name: a configured ``providers.openai`` pointing at api.openai.com must not
be hijacked by the legacy "openai" -> "openrouter" alias.Nr³   r   r™   r"  rp   )r‚   r~   r   rþ   r(  r¥   ro   rj   r  r)  r9  r�   ri   rk   rœ   rŸ   rŽ   r    )
rk   r;  r  r‰   r  Ú	user_pdefr¤   Ú	candidateÚcustom_pdefr¡   s
   &&&       r#   Úresolve_provider_fullr@    sn  € ô # 4Ó(€IØ
�*‰*‹,×
Ñ
Ó
€CßÜ)¨#Ó>ˆ	ØÒ ØÐØÔÜ)¨#Ó9ˆØÒØˆKÜ˜	Ó"€DØÒØ�;‰;Ð*Ô*¯~Ü-¨d¯g©g°~ÓFˆIØÒ$Ø Ð ØˆßØ#Ó)ˆIÜ-¨iÓHˆIØÔ$Ø Ò ñ *ô *¨$ÓA€KØÒØÐØ
ÔÔÜÓˆØÒØˆKðÜ$ YÓ/ˆ	ØÒ Ü )·.±.ÈMÐlu×lyÑlyØ(1¯©¸lôLð Lð !ô   	Ó*€DØÒ#¨¯©°8Ô(;ˆ4ÐEÀÐEøô ô Ùðús   Ã2<E ÅE"Å!E")Ú
LM_API_KEY)ÚCOPILOT_GITHUB_TOKENÚGH_TOKEN)ÚANTHROPIC_TOKENÚCLAUDE_CODE_OAUTH_TOKEN)ÚGLM_API_KEYÚZAI_API_KEYÚZ_AI_API_KEY)ÚSTEPFUN_API_KEY)ÚCOMMANDCODE_API_KEY)ÚGMI_API_KEY)ÚFIREWORKS_API_KEY)ÚACTUAL_API_KEY)ÚUPSTAGE_API_KEY)ÚNEBIUS_API_KEYÚNEBIUS_TOKEN_FACTORY_API_KEY)Úopenai)Úglmzz-aizz.aiÚzhipu)zx-aizx.aiÚgrok)z
grok-oauthr-   z
x-ai-oauthzxai-grok-oauth)Únimz
nvidia-nimzbuild-nvidiaÚnemotron)Úkimizkimi-codingzkimi-coding-cnÚmoonshot)Ústepzstepfun-coding-plan)zminimax-chinaÚ
minimax_cn)Úclaudezclaude-code)ÚcopilotÚgithub)zgithub-copilot-acp)Úchatgptzchatgpt-codex)z
ai-gatewayÚ	aigatewayzvercel-ai-gateway)zopencode-zenÚzen)Úgozopencode-go-sub)Úkilocodez	kilo-codezkilo-gateway)z	deep-seek)Ú	dashscopeÚaliyunÚqwenzalibaba-cloud)Úalibaba_codingzalibaba-codingÚalibaba_coding_plan)Úhfzhugging-facezhuggingface-hub)z	novita-aiÚnovitaai)Úmimozxiaomi-mimo)ÚtencentÚtokenhubztencent-cloudÚtencentmaas)Ú	tokenplanztencent-lkeap)Úawszaws-bedrockzamazon-bedrockÚamazon)zarcee-aiÚarceeai)z	gmi-cloudÚgmicloud)zfireworks-aiÚfw)Úsolar)zactual-computerÚactualcomputerÚaci)Únebiusznebius-tokenfactoryz	nebius-tfztoken-factoryÚtokenfactory)r0   z	lm-studioÚ	lm_studio)ÚollamaÚlocalÚvllmrq   rr   rs   )r   r   )T)r   )r   )NN)8Ú__conditional_annotations__r   Ú
__future__r   ÚloggingÚdataclassesr   Útypingr   r   r   r   r   Úutilsr	   r
   Ú	getLoggerr   Úloggerr   rg   r    ri   rt   rµ   ru   rv   rw   r‚   r‡   r�   r•   r¥   r    rÃ   r   r  rË   rÎ   rÑ   rÒ   rÙ   rß   rÞ   rð   rõ   rþ   r  r  r  r(  r7  r)  r/  r9  r@  )Úcanonr  Úaliasr}  s   000@r#   Ú<module>r‡     s3  øðÜ Cå "ã Ý !ß 3Õ 3ç :à	×	Ò	˜8Ó	$€ñ
 �$Ô÷ð ó ððD-Ø	‰= 9ÀÔNðD-à‘-¨dÐEZÔ[ðD-ð ‰MÐ$7ÐKvÔwðD-ð ‘MÐ,=ÐIYØ4[ô]ð	D-ð ‘-Ð*;ÐOjØ1BôDðD-ð ‘Ð):ÐFVØ1FÐYgôiðD-ð ‘-Ð*:ÐNiØ1GôIðD-ð ‘¨_ÐPjØ/<ô>ðD-ð ‘=Ð+<ÐHZØ3BÐUkômðD-ð  ‘mÐ3WÔXð!D-ð" ‘Ð)=ÐN|Ô}ð#D-ð$ 
‰=Ð(VÐiwÔxð%D-ð& ‘}°oÔFð'D-ð( ‰}Ð,@Ø/TØ.@ôBð)D-ð. ‰}Ð';ÐN`Ôað/D-ð0 ‘]Ð-AÐM]Ø5WôYð1D-ð4 ‘-Ð*>ÐQfÔgñ5D-ð6 ‘Ð/BÔCð7D-ð8 ‰}Ð.BÔCð9D-ð: ™=Ð:XÔYð;D-ð< ‰m¨$Ô/ð=D-ð> ‘¨DÐCZÔ[ð?D-ð@ ‘=¨tÐF\Ô]ðAD-ðB ‰M¨Ð?RÔSðCD-ðD ‘=¨tÀmÔTðED-ðF ‰m¨$ÐARÔSðGD-ðH 
‰=Ð#4ÐH]Ðp~ÔðID-ðJ ‰mÐ.SÐfwÔxðKD-ðL ‰mÐ->Ô?ðMD-ðN ™Ð7JÔKðOD-ðP ™Ð1EØ9mØ8LôNðQD-ðV ‰]Ð-JÐ]mÔnðWD-ðZ ‘=Ð0HØ3[Ø2HôJð[D-ð` 
‰=Ð(8ÐLlØ*8ô:ñaD-ðd ‘Ð.DØ1XôZà‰mÐ&8ÐI\Ø.IÐ\môoà‰}Ð,@ÐToØ.@ôBà™MÐ9kØ<dØ;LôNð ‘MÐ4KÐ^oÔpà‘]Ð4LÔMØ‰}Ð'9ÀYÔOð
 ‰m hÔ/ñGD-€Ð)ó DðR ÷ð ó ðð"-Ø�+ð-Ø$Ð&Fð-ØHMÐOgð-àÐLð-ð Ð?ð-ð ÐLð	-ð
 Ð.ð-ð
 1=Ð>]ð-ð Ð*ð-ð -=Ð>Sð-ð Ð*ð-ð -;Ð<Xð-ð Ð>ð-ð Ð'ð-ð *7Ð8Qð-ð TZð  \Eð-ð �ñ-ð !*Ð+[ð-ð ÐVð-ð Ð<ð-ð ?GÐHað-ð Ð%ð-ð (:Ð;rð-ð Ð7ð-ð ÐAð-ð DKÐLcð-ð  
Ð$ð!-ð  '2Ð3Ið!-ð  LUÑV`ð!-ð" Ñ:ð#-ð$ Ñkð%-ð& Ñ6ð'-ð, ÑOñ--€Ð)ó ð0 ?L×>QÑ>QÔ>SÕiÑ>S©N¨EÓahÐX] %š<Ñah™5Ñ>SÓi€ˆÓ ið
$Ø	Ðð$Ø &¨ð$Ø7EÐGfð$àÐ'ð$à)2Ð4Gð$àIQÐS`ð$àbgÐitð$ð ˆð$ð !)Ð*;ð$ð >PÐQcð$ð Ð2ð	$ð 5HÐI\ð	$ð _iÐjuð	$ð
 Ðð$ð
 "+¨Mð$ð
 <DÐEWð$ð
 ZhÐiwð$ð Ð8ñ$Ð �.ó ð Ð%Ð';Ð=QØÐ(Ð*<Ð>Pð)Ð �~ó õ!÷ð ÷ð õ&ð°T÷ õ>Wõ2,õ1ñ -6°}ÀjÐ6QÓ,RÐ ˜>Ó Rõ(õ=ñ$ +4°]ÐDTÐ4UÓ*VÐ ˜Ó V÷ð ÷@ð õ(<÷ð ÷2jð jõN÷*Vð V÷ð õ õ:ð. "Ð Ø%9¸;ÈÐ$TÐ �/Ó Tõõ^÷&1Fò 1FùôU js   ËP