+
    jHàjr# ã                  ó  a € 0 t $ R t^ RIHt ^ RIt^ RIt^ RIt^ RIHt ^ RI	H
t
 ^ RIHt ^ RIHtHtHtHt ]P$                  ! ]4      t^ RIHt ^ RIHtHtHtHt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/H0t0H1t1H2t2H3t3H4t4 ^ RIH5t6 ^ RIH7t8 ^ RI9H:t: ^ RI;H<t<H=t=H>t>H?t?H@t@ ^ RIAHBtBHCtCHDtDHEtE ]
! RRR7      tFR]GR&   ]R R l4       tH]
! RRR7      tIR]GR&   ]R 4       tJR tKRÓR ltLR tMR R ltNR R ltOR  R! ltPR"R#R$R#R%R&R'R#R(R)/tQ0 RÔmtRR* R+ ltSR, R- ltTRÕR/ R0 lltUR1 R2 ltVR3 R4 ltWR5 R6 ltXRÓR7 R8 lltYR9 R: ltZR; R< lt[R=R/R> R? llt\R@ RA lt]RB RC lt^RD RE lt_RFR./RG RH llt`RItaRJtbRK RL ltcRM RN ltdRO RP lteRQ RR ltfRS RT ltgRU RV lthRWR/RX RY lltiRZ R[ ltjR\ R] ltkR^ R_ ltlR` Ra ltmRb Rc ltnRd Re ltoRf Rg ltpRh Ri ltqRj Rk ltrRl Rm ltsRÓRn Ro lltt^ RpIuHvtvHwtwHxtxHytyHztzH{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‰ ^ RqIŠH‹t‹HŒtŒH�t�HŽtŽH�t� RrR#]#3RsR#]%3RtR&]$3RuR&]:3RvR)Rw 3RxRÖ/t�Ry]GRz&   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‰ t—RŠ t˜R‹ t™RŒ tšR� RŽ lt›R� R� ltœR‘ t�R’]—Rr]™R“]šR”R• /tžR–]GR—&   R˜RR™RR=R/Rš R› lltŸ]! RœR�7       ! Rž RŸ4      4       t R“] ! ]p]@R R¡R¢4      Rr] ! R£ R#R¤R¥R¦4      Rs] ! R§ R#R¤R¥R¨]%4      Rt] ! R© R&RªR«R¬4      /t¡R­]GR®&   R¯ R° lt¢R± R² lt£R³ R´ lt¤RÓRµ R¶ llt¥R· R¸ lt¦R×t§RØt¨R¹ Rº lt©R» R¼ ltªR½ R¾ lt«R¿ RÀ lt¬RÁ RÂ lt­RÃ RÄ lt®RÅ RÆ lt¯RÇ RÈ lt°RÉRR˜RR™RR=R/RÊ RË llt±RÌ RÍ lt²RÎ t³RÏ RÐ lt´RÉRR=RR™RR˜R/RÑ RÒ lltµR# )Ùuõ  Shared runtime provider resolution for CLI, gateway, cron, and helpers: the resolution ORDER
(:func:`resolve_runtime_provider`), api_mode / base_url helpers and the pool / OAuth / explicit paths.
Custom-provider lookup lives in :mod:`hermes_cli.runtime_provider_custom`; Azure Foundry,
OpenRouter/bare-custom, Bedrock and external-process builders in
:mod:`hermes_cli.runtime_provider_backends` â€” both re-exported here so
``hermes_cli.runtime_provider.<name>`` imports and test patches keep working.)ÚannotationsN)Úcontextmanager)Ú
ContextVar)Ú	dataclass)ÚAnyÚCallableÚDictÚOptional)Úauth)ÚCredentialPoolÚPooledCredentialÚ credential_pool_matches_providerÚ#custom_provider_pool_key_candidatesÚ	load_pool)Úget_secret_str)ÚACTUAL_LOCAL_NOAUTH_PLACEHOLDERÚ	AuthErrorÚDEFAULT_CODEX_BASE_URLÚDEFAULT_QWEN_BASE_URLÚDEFAULT_XAI_OAUTH_BASE_URLÚPROVIDER_REGISTRYÚ_agent_key_is_usableÚ_nous_inference_env_overrideÚformat_auth_errorÚresolve_providerÚ resolve_nous_runtime_credentialsÚ!resolve_codex_runtime_credentialsÚ%resolve_xai_oauth_runtime_credentialsÚ resolve_qwen_runtime_credentialsÚ$resolve_api_key_provider_credentialsÚ-resolve_external_process_provider_credentialsÚhas_usable_secretÚis_actual_local_base_urlÚlooks_like_openrouter_keyÚnormalize_actual_base_url©Úconfig)Úmodels)ÚOPENROUTER_BASE_URL)Údetermine_api_modeÚget_providerÚis_actual_routeÚis_official_openai_hostÚnous_api_mode)Úbase_url_host_matchesÚbase_url_hostnameÚbase_url_pathÚenv_intÚ_FROZEN_RUNTIME_CONFIG)Údefaultz$ContextVar[Optional[dict[str, Any]]]c               ó   € V ^8„  d   QhRR/# )é   r&   údict[str, Any]© )Úformats   "Ú@/home/ubuntu/.hermes/hermes-agent/hermes_cli/runtime_provider.pyÚ__annotate__r:   .   s   € ÷ ,ñ , .ñ ,ó    c              #  ó  "  € \         P                  ! \        P                  ! \         P                  4      V 4      p\
        P                  V4      p Rx € \
        P                  V4       R#   \
        P                  T4       i ; i5i)ad  Resolve against a session's frozen config instead of the live config.yaml.

Every rung reads its endpoint through ``load_config``/``_get_model_config``, so a frozen route's
credential stays paired with the endpoint it was frozen with after a live ``model.base_url``
edit (R2-M2). The auth store (credential pool) is not config and still refreshes/rotates.
N)Ú_config_modÚ_deep_mergeÚcopyÚdeepcopyÚDEFAULT_CONFIGr2   ÚsetÚreset)r&   ÚmergedÚtokens   &  r9   Úfrozen_runtime_configrF   -   s^   é € ô ×$Ò$¤T§]¢]´;×3MÑ3MÓ%NÐPVÓW€FÜ"×&Ñ& vÓ.€Eð,Ûä×$Ñ$ UÖ+øÔ×$Ñ$ UÕ+üs   ‚ABÁA- ÁBÁ-BÂBÚ_DEFER_TOKEN_MINTFzContextVar[bool]c               #  ó    "  € \         P                  R4      p  Rx € \         P                  V 4       R#   \         P                  T 4       i ; i5i)züResolve the route without exchanging short-lived OAuth tokens up front (Vertex today): the
resolved ``api_key`` is a callable that mints on first use. For the gateway-backed classic
CLI, whose gateway session mints its own token for every turn it runs.TN)rG   rB   rC   )rE   s    r9   Údeferred_token_mintrI   @   s<   é € ô
 ×!Ñ! $Ó'€Eð'Ûä×Ñ Ö&øÔ×Ñ Õ&üs   ‚A™4 �A´AÁAc                 óˆ   € \         P                  4       p V e   \        P                  ! V 4      # \        P
                  ! 4       # ©N)r2   Úgetr?   r@   r=   Úload_config©Úfrozens    r9   rM   rM   O   s2   € Ü#×'Ñ'Ó)€FØ$*Ò$6Œ4�=Š=˜Ó ÐU¼K×<SÒ<SÓ<UÐUr;   c                ó.   € \         P                  ! V 4      # rK   )r=   Úget_compatible_custom_providersr%   s   &r9   rQ   rQ   T   s   € Ü×6Ò6°vÓ>Ð>r;   c                ó.   € \         P                  ! V 4      # rK   )r=   Únormalize_extra_headers)Úvalues   &r9   rS   rS   X   s   € Ü×.Ò.¨uÓ5Ð5r;   c               ó    € V ^8„  d   QhRRRR/# )r5   ÚhostÚstrÚreturnÚboolr7   )r8   s   "r9   r:   r:   \   s   € ÷ \ñ \˜Sð \ Tñ \r;   c                óZ   € T ;'       g    R P                  4       P                  R4      R9   # )Ú Ú.>   Ú	localhostú::1ú0.0.0.0ú	127.0.0.1)ÚlowerÚrstrip)rV   s   &r9   Ú_loopback_hostnamerc   \   s(   € Ø�JˆJ�B×ÑÓ×&Ñ& sÓ+Ð/[Ñ[Ð[r;   c               ó    € V ^8„  d   QhRRRR/# )r5   ÚnamerW   rX   rY   r7   )r8   s   "r9   r:   r:   `   s   € ÷ ñ ˜cð  dñ r;   c                óZ   €  \         P                  ! V 4      R8H  #   \         d     R# i ; i)uP   True when a provider alias (ollama, vllm, llamacpp, â€¦) resolves to ``custom``.ÚcustomF)Úauth_modr   Ú	Exception)re   s   &r9   Ú_resolves_to_customrj   `   s/   € ðÜ×(Ò(¨Ó.°(Ñ:Ð:øÜô Úðús   ‚ ›*©*c               ó$   € V ^8„  d   QhRRRRRR/# )r5   Úcfg_base_urlrW   Úcfg_providerrX   rY   r7   )r8   s   "r9   r:   r:   h   s(   € ÷ |ñ |¸sð |ÐRUð |ÐZ^ñ |r;   c                ó`  € T;'       g    RP                  4       P                  4       pT ;'       g    RP                  4       p\        V4      ;'       d[    VR8H  ;'       gN    VR9  ;'       d    \        V4      ;'       g.    \	        VR4      '       * ;'       d    \        \        V4      4      # )u­  Whether ``model.base_url`` may back bare ``custom`` runtime resolution. The picker can select
Custom while ``model.provider`` still names a previous provider, so non-loopback URLs are rejected
unless the YAML provider is already ``custom`` or a local-server alias (ollama/vllm/llamacpp â€”
else a legit LAN ollama endpoint falls through to OpenRouter): a stale OpenRouter/Z.ai base_url
cannot hijack local sessions.

See #14676.
r[   rg   úopenrouter.ai>   r[   Úauto)Ústripra   rY   rj   r.   rc   r/   )rl   rm   Úcfg_provider_normÚbus   &&  r9   Ú,_config_base_url_trustworthy_for_bare_customrt   h   s°   € ð &×+Ð+¨×2Ñ2Ó4×:Ñ:Ó<ÐØ
×
Ð
˜"×	#Ñ	#Ó	%€Bô �‹8÷ |ð |Ð*¨hÑ6÷ {ð {Ø Ñ-×XÐXÔ2EÐFWÓ2X÷{ð {ô "7°r¸?Ó!KÔK×yÐyÔPbÔctÐuwÓcxÓPyð|r;   zapi.x.aiÚcodex_responseszapi.meta.aizapi.actual.incÚchat_completionszapi.router.comúapi.anthropic.comÚanthropic_messagesc               ó    € V ^8„  d   QhRRRR/# )r5   Úbase_urlrW   rX   úOptional[str]r7   )r8   s   "r9   r:   r:   Š   s   € ÷ ñ  sð ¨}ñ r;   c                óf  € T ;'       g    RP                  4       P                  4       P                  R4      p\        V 4      p\        P                  V4      ;'       g    \        V 4      '       d   RMRpV'       d   V# \        V4      pVP                  R4      '       g   VR8X  d
   RV9   d   R# R# )	uˆ  Auto-detect api_mode from the resolved base URL, or None. Exact-hostname matches reject
lookalike subdomains (api.anthropic.com.attacker.test) and path-segment spoofing
(proxy.test/api.anthropic.com/v1). Official OpenAI hosts (incl. us./eu. data-residency hosts)
need Responses for GPT-5.x tool calls with reasoning.

- Direct api.anthropic.com endpoints must use the native Messages API (``/v1/messages``). Anthropic also
exposes an OpenAI-compat ``/chat/completions`` shim on the same host, but Pro/Max OAuth subscriptions
are only billed against the native Messages route; hitting the shim accounts against a separate "extra
usage" pool that is empty by default and surfaces as HTTP 400 "You're out of extra usage."  See issue
#32243. - Third-party Anthropic-compatible gateways (MiniMax, Zhipu GLM, LiteLLM proxies, etc.)
conventionally expose the native Anthropic protocol under a ``/anthropic`` suffix â€” treat those as
``anthropic_messages`` transport instead of the default ``chat_completions``. - Kimi Code's
``api.kimi.com/coding`` endpoint also speaks the Anthropic Messages protocol (the /coding route accepts
Claude Code's native request shape).
r[   Ú/ru   Nzapi.kimi.comz/codingrx   )z
/anthropicz/anthropic/v1)	rq   ra   rb   r/   Ú_HOST_MANDATED_API_MODESrL   r,   r0   Úendswith)rz   Ú
normalizedÚhostnameÚmandatedÚpaths   &    r9   Ú_detect_api_mode_for_urlr„   Š   s˜   € ð  —.�.˜b×'Ñ'Ó)×/Ñ/Ó1×8Ñ8¸Ó=€JÜ  Ó*€HÜ'×+Ñ+¨HÓ5×{Ð{ÔOfÐgo×OpÒOpÑ:KÐvz€HßØˆÜ˜Ó$€DØ‡}�}Ð4×5Ò5¸(ÀnÔ:TÐYbÐfpÔYpñ
 $Ùr;   c               ó    € V ^8„  d   QhRRRR/# )r5   Úrawr   rX   r{   r7   )r8   s   "r9   r:   r:   ©   s   € ÷ 	jñ 	j˜ð 	j ñ 	jr;   c                óÎ   € \        V \        4      '       d%   \        P                  ! V 4      P	                  4       MRpV'       g   R# ^ RIHp V\        9   g   W! 4       9   d   V# R# )uJ  Validate an api_mode from config (None if invalid). Legacy/alias spellings (``openai``,
``anthropic``, ``responses``, â€¦) are canonicalized first so old configs keep their transport
instead of silently falling through to hostname-based detection. A mode with a registered
transport (a provider plugin's own dialect) is valid too.r[   N)Úregistered_api_modes)Ú
isinstancerW   r=   Ú_canonical_api_modera   Úagent.transportsrˆ   Ú_VALID_API_MODES)r†   r€   rˆ   s   &  r9   Ú_parse_api_moder�   ©   sW   € ô
 BLÈCÔQT×AUÒAU”×0Ò0°Ó5×;Ñ;Ô=Ð[]€JßÙÝ5Ø#Ô'7Ô7¸:ÐI]ÓI_Ô;_ˆ:ÐiÐeiÐir;   r[   c               ó(   € V ^8„  d   QhRRRRRRRR/# )r5   ÚproviderrW   rz   ÚmodelrX   r7   )r8   s   "r9   r:   r:   µ   s(   € ÷ ñ  ð °ð ¸Cð Èñ r;   c                ó¢   € \        W4      '       d   R# \        V4      pV'       d   V# \        WV4      pVR8X  d   \        W4      '       g   R# V# )a~  api_mode when no explicit/persisted mode applies: URL detection (host-mandated wire shapes)
first, then the transport the provider overlay declares via ``providers.determine_api_mode``
(``openai-api`` pointed at us.api.openai.com 400'd on every tool call without it), then
``chat_completions``. A declared ``anthropic_messages`` is kept only on the provider's own
endpoint (#76836).rv   rx   )r+   r„   r)   Ú_on_declared_anthropic_endpoint)r�   rz   r�   ÚdetectedÚdeclareds   &&&  r9   Ú_fallback_api_moder•   µ   sO   € ô �x×*Ò*Ù!Ü'¨Ó1€HßØˆÜ! (°eÓ<€HØÐ'Ô'Ô0OÐPX×0cÒ0cñ
 "Ø€Or;   c               ó$   € V ^8„  d   QhRRRRRR/# )r5   r�   rW   rz   rX   rY   r7   )r8   s   "r9   r:   r:   Ê   s&   € ÷ Uñ U¨cð U¸Sð UÀTñ Ur;   c                óž  € \        V RR7      pV'       d   VP                  MRP                  4       p\        V4      P	                  R4      pV'       d!   T;'       g    RP                  4       '       g   R# \        V\        V4      4      '       g   R# \        V4      pVR8H  ;'       g%    WT8H  ;'       g    VP                  VR,           4      # )u¶  True when ``base_url`` is the provider's own Anthropic-protocol endpoint: the catalog
default's host (or a subdomain of it) and either the bare host â€” the provider's own host
with no path still means the native endpoint (#53054) â€” or the default's path
(``/anthropic`` for MiniMax, ``/plan/anthropic`` for Tencent) with or without a ``/v1``
tail. With nothing to compare â€” no URL, an overlay-only provider whose models.dev default
is not cached (offline), or a default with no path at all (``api.anthropic.com``: no sibling
OpenAI-compatible path exists to tell an override's protocol from) â€” keep the declared
transport: demoting the provider's own endpoint would be the worse failure.F)Úallow_networkr[   ú/v1Tr}   )r*   rz   rq   r0   Úremovesuffixr.   r/   Ú
startswith)r�   rz   Úpdefr3   Údefault_pathrƒ   s   &&    r9   r’   r’   Ê   s¡   € ô ˜°Ô6€Dß $ˆt�}Š}¨"×3Ñ3Ó5€GÜ  Ó)×6Ñ6°uÓ=€Lß § ¨B×5Ñ5×7Ò7ÙÜ  Ô+<¸WÓ+E×FÒFÙÜ˜Ó"€DØ�2‰:×TÐT˜Ñ-×TÐT°·±ÀÐPSÕASÓ1TÐTr;   c               ó$   € V ^8„  d   QhRRRRRR/# )r5   Ú	model_cfgr6   rz   rW   rX   r7   )r8   s   "r9   r:   r:   Þ   s'   € ÷ 
Bñ 
B¨nð 
BÈð 
BÐPSñ 
Br;   c                ó   € \        VR7      '       d   R# \        V P                  R4      4      p\        V4      pVR8X  d*   VR8w  d#   \        P                  RT;'       g    R4       RpT;'       g    T;'       g    R# )u·   api_mode for legacy/plain ``provider: custom`` endpoints â€” conservative by default: only
direct OpenAI/xAI/Meta URLs imply Responses; named custom providers opt in via ``api_mode``.©rz   rv   Úapi_moderu   zMIgnoring persisted custom api_mode=codex_responses for non-OpenAI endpoint %sz	(unknown)N)r+   r�   rL   r„   ÚloggerÚinfo)rŸ   rz   Úconfigured_modeÚdetected_modes   &&  r9   Ú_resolve_plain_custom_api_moder§   Þ   su   € ô  ×)Ó)Ù!Ü% i§m¡m°JÓ&?Ó@€OÜ,¨XÓ6€MØÐ+Ô+°ÐARÔ0RÜ�‰ÐcÐem×e|Ðe|Ðq|Ô}ØˆØ×AÐA˜m×AÐAÐ/AÐAr;   c               ó$   € V ^8„  d   QhRRRRRR/# )r5   r�   rW   Úconfigured_providerrX   rY   r7   )r8   s   "r9   r:   r:   ë   s&   € ÷ Hñ H¨ð HÀ#ð HÈ$ñ Hr;   c                óÖ   € W8X  d   R# \         P                  ! V 4      p\         P                  ! V4      p\        T;'       d$    T;'       d    VP                  VP                  8H  4      # )zOProfile aliases share an auth registry ID; unrelated routes must stay distinct.T)r   rL   rY   Úid)r�   r©   ÚpconfigÚ
configureds   &&  r9   Ú_same_registered_providerr®   ë   sT   € àÔ&ÙÜ×#Ò# HÓ-€GÜ"×&Ò&Ð':Ó;€JÜ�×FÐF˜J×FÐF¨7¯:©:¸¿¹Ñ+FÓGÐGr;   c               ó$   € V ^8„  d   QhRRRRRR/# )r5   r�   r{   r©   rX   rY   r7   )r8   s   "r9   r:   r:   ô   s(   € ÷ uñ u°=ð uÐWdð uÐptñ ur;   c                ó  € T ;'       g    RP                  4       P                  4       T;'       g    RP                  4       P                  4       r2V'       * ;'       g1    VR8X  d   VR8H  ;'       g    VP                  R4      # \        W#4      # )u¬   Whether a persisted api_mode may be honored for ``provider`` â€” only when the config's
provider matches (or none is recorded), so a stale mode never leaks across a switch.r[   rg   zcustom:)rq   ra   r›   r®   )r�   r©   ÚpÚcs   &&  r9   Ú$_provider_supports_explicit_api_moder³   ô   su   € ð �NˆN˜×!Ñ!Ó#×)Ñ)Ó+Ð.A×.GÐ.GÀR×-NÑ-NÓ-P×-VÑ-VÓ-X€qØŒ5×tÐtÀÀhÄ�Q˜(‘]×=Ð= a§l¡l°9Ó&=ÐtÔTmÐnoÓTsÐtr;   c               ó$   € V ^8„  d   QhRRRRRR/# )r5   r�   rW   rŸ   r6   rX   r{   r7   )r8   s   "r9   r:   r:   û   s&   € ÷ Eñ E 3ð E°>ð EÀmñ Er;   c                ó„   € \        VP                  R4      4      pV'       d   \        V \        V4      4      '       d   V# R# )zRPersisted ``model.api_mode`` when valid and recorded for this provider, else None.r¢   N)r�   rL   r³   Ú_cfg_provider)r�   rŸ   r¥   s   && r9   Ú_configured_api_moder·   û   sB   € ä% i§m¡m°JÓ&?Ó@€Oß-Ô2VÐW_ÔanÐoxÓay×2zÒ2zˆ?ð  Eð  AEð  Er;   c               ó$   € V ^8„  d   QhRRRRRR/# )r5   rŸ   r6   Útarget_modelr{   rX   rW   r7   )r8   s   "r9   r:   r:     s"   € ÷ :ñ : ð :¸mð :ÐPSñ :r;   c                óL   € T;'       g    V P                  R4      ;'       g    R# )z{The caller's target model (e.g. /model switch) beats the persisted default, else api_mode
is computed from a stale default.r3   r[   )rL   )rŸ   r¹   s   &&r9   Ú_effective_modelr»     s#   € ð ×9Ð9˜9Ÿ=™=¨Ó3×9Ð9°rÐ9r;   r¹   c               ó(   € V ^8„  d   QhRRRRRRRR/# )r5   rŸ   r6   Úapi_keyrW   r¹   r{   rX   r7   )r8   s   "r9   r:   r:     s*   € ÷ "ñ "¨ð "À#ð "ÐXeð "Ðqtñ "r;   c               óx  € \        R V 4      pV'       dR   \        \        W4      4      P                  4       pVR8X  d'   V'       d   \        P
                  ! V4      '       g   R# V# \        \        W4      4      P                  4       p V'       d   \        P                  ! WAR7      # R#   \         d     R# i ; i)Úcopilotru   rv   )r½   )r·   rW   r»   rq   Ú_modelsÚ!_should_use_copilot_responses_apiÚcopilot_model_api_moderi   )rŸ   r½   r¹   r¥   Ú
model_names   &&$  r9   Ú_copilot_runtime_api_moderÄ     sœ   € Ü*¨9°iÓ@€Oßô Ô)¨)ÓBÓC×IÑIÓKˆ
ØÐ0Ô0·ZÜ×AÒAÀ*×MÒMÙ%ØÐô Ô% iÓ>Ó?×EÑEÓG€Jð"ßNXŒw×-Ò-¨jÔJÐpÐ^pÐpøÜô "Ú!ð"ús   Â	B* Â(B* Â*B9Â8B9c               ó$   € V ^8„  d   QhRRRRRR/# )r5   Úeffective_modelrW   r¢   rX   r7   )r8   s   "r9   r:   r:      s!   € ÷ ñ ¨cð ¸Sð ÀSñ r;   c                óŒ   € V '       d   VR8X  d   V#  \         P                  ! V 4      ;'       g    T#   \         d    Tu # i ; i)z®Upgrade api_mode for GPT-5.x / codex / o1-o4 deployments on Azure Foundry (Azure 400s
/chat/completions on these). Skipped when the user explicitly picked anthropic_messages.rx   )rÀ   Úazure_foundry_model_api_moderi   )rÆ   r¢   s   &&r9   Ú_azure_inferred_api_moderÉ      sF   € ÷ ˜hÐ*>Ô>ØˆðÜ×3Ò3°OÓD×PÐPÈÐPøÜô ØŠðús   “3 °3 ³AÁAc               ó0   € V ^8„  d   QhRRRRRRRRRR	R
R/# )r5   r�   rW   rŸ   r6   rz   rÆ   r   Úopencode_by_modelrY   rX   r7   )r8   s   "r9   r:   r:   +  sB   € ÷ pñ p¨sð p¸~ð pÐY\ð pÐorð pØ8<ðpØADñpr;   c               ó  € V R8X  d3   \        W4      pV'       d   VR8w  d   \        P                  RV4       R# V'       d/   \        P                  ! V 4      e   \        P
                  ! W4      # \        W4      ;'       g    \        WV4      # )a   Persisted ``model.api_mode`` when it belongs to this provider, else URL/transport fallback.
OpenCode Zen/Go serve both anthropic_messages and chat_completions models, so (when
``opencode_by_model``) their mode is always re-derived from the effective model.Úactualrv   zQRouting built-in Actual through chat_completions instead of persisted api_mode=%s)r·   r£   r¤   rÀ   Úopencode_provider_familyÚopencode_model_api_moder•   )r�   rŸ   rz   rÆ   rË   r¥   s   &&&&$ r9   Ú _configured_or_fallback_api_moderÐ   +  st   € ð
 �8ÔÜ.¨xÓCˆß˜Ð2DÔDÜ�K‰KÐkÐm|Ô}Ù!ßœW×=Ò=¸hÓGÒSÜ×.Ò.¨xÓIÐIÜ Ó4×oÐoÔ8JÈ8Ð_nÓ8oÐor;   c               ó4   € V ^8„  d   QhRRRRRRRRRRR	R
RR/# )r5   r�   rW   rŸ   r6   r½   rz   rÆ   r   rË   rY   rX   r7   )r8   s   "r9   r:   r:   :  sK   € ÷ Añ A¨ð A¸ð AÐRUð AÐadð AÐwzð AØ26ðAØ;>ñAr;   c               óX   € V R8X  d   \        WVR7      # V R8X  d   R# \        WW4VR7      # )zMapi_mode for a registry ``api_key`` provider (explicit and env/config paths).r¿   ©r¹   Úxairu   ©rË   )rÄ   rÐ   )r�   rŸ   r½   rz   rÆ   rË   s   &&&&&$r9   Ú_api_key_provider_api_moderÖ   :  s<   € ð �9ÔÜ(¨È/ÔZÐZØ�5Ôñ
 !Ü+¨HÀÐnô  Að  Ar;   Úrequested_providerc          
     ó,   € V ^8„  d   QhRRRRRRRRRR/# )r5   r�   rW   r¢   rŸ   úOptional[dict[str, Any]]r×   rX   r7   )r8   s   "r9   r:   r:   H  s2   € ÷ ñ °sð Àcð ÐVnð Ø>AðØKNñr;   c                óô   € V'       dF   \        VP                  R4      ;'       g    R4      P                  4       P                  4       R8w  d   V# V R9   g    VR9   g   V R8X  d   \	        V4      '       d   R# V# )uÆ  Opt-in rewrite to "codex_app_server" via ``model.openai_runtime``. Eligible: ``openai`` /
``openai-codex``, and a configured named custom provider (``providers.<name>``) whose id codex
looks up in its own ``[model_providers.<name>]`` table (#75186). Anonymous ``custom`` has no
stable id and stays ineligible. No-op when unset, "auto", or empty. Applied once, on the
runtime ``resolve_runtime_provider`` picked â€” never inside an individual ladder rung.Úopenai_runtimer[   Úcodex_app_serverrg   >   Úopenaiúopenai-codex)rW   rL   rq   ra   Úcodex_model_provider_id©r�   r¢   rŸ   r×   s   $$$$r9   Ú%_maybe_apply_codex_app_server_runtimerá   H  sk   € ÷ œ˜IŸM™MÐ*:Ó;×AÐA¸rÓB×HÑHÓJ×PÑPÓRÐVhÔhØˆØÐ-Ô-Ð1CÐGaÔ1aØ˜HÔ$Ô)@ÐAS×)TÒ)TÙ!Ø€Or;   zhttps://api.anthropic.comzwNo Anthropic credentials found. Run 'hermes auth add anthropic' to sign in, or set ANTHROPIC_TOKEN / ANTHROPIC_API_KEY.c               ó0   € V ^8„  d   QhRRRRRRRRRRRR	/# )
r5   r�   rW   r¢   rz   r   r½   ÚextrarX   r6   r7   )r8   s   "r9   r:   r:   ^  s@   € ÷ kñ k�sð k cð k°Sð kÀ3ð kÐQTð kÐYgñ kr;   c                óV   € \        W4      '       d   Rp\        V4      pRV RVRVRV/VC# )zbBuild a resolved-runtime dict; ``extra`` carries source/requested_provider/provider-specific keys.rv   r�   r¢   rz   r½   )r+   r$   )r�   r¢   rz   r½   rã   s   &&&&,r9   Ú_runtimerå   ^  s:   € ä�x×*Ò*Ø%ˆÜ,¨XÓ6ˆØ˜ *¨h¸
ÀHÈiÐY`ÐjÐdiÐjÐjr;   c               ó    € V ^8„  d   QhRRRR/# ©r5   rŸ   r6   rX   rW   r7   )r8   s   "r9   r:   r:   f  s   € ÷ @ñ @˜^ð @°ñ @r;   c                ó‚   € \        V P                  R 4      ;'       g    R4      P                  4       P                  4       # )r�   r[   )rW   rL   rq   ra   )rŸ   s   &r9   r¶   r¶   f  s0   € Üˆy�}‰}˜ZÓ(×.Ð.¨BÓ/×5Ñ5Ó7×=Ñ=Ó?Ð?r;   c               ó$   € V ^8„  d   QhRRRRRR/# )r5   rŸ   r6   r�   rW   rX   r7   )r8   s   "r9   r:   r:   j  s&   € ÷ Hñ H¨^ð HÀsð HÈsñ Hr;   c                óú   € \        V 4      pVR8X  d   \        P                  ! V4      p\        W4      '       dB   \	        V P                  R4      ;'       g    R4      P                  4       P                  R4      # R# )u—   ``model.base_url`` (stripped, no trailing slash) only when ``model.provider`` is
``provider`` â€” a stale base_url must not leak into another provider.rÍ   rz   r[   r}   )r¶   rÀ   Únormalize_providerr®   rW   rL   rq   rb   )rŸ   r�   r©   s   && r9   Ú_config_base_url_for_providerrì   j  st   € ô (¨	Ó2ÐØ�8ÔÜ%×8Ò8Ð9LÓMÐÜG`Ðai×GÒGŒ3ˆy�}‰}˜ZÓ(×.Ð.¨BÓ/×5Ñ5Ó7×>Ñ>¸sÓCð  Hð  FHð  Hr;   c               ó$   € V ^8„  d   QhRRRRRR/# )r5   r�   r{   rz   rX   rY   r7   )r8   s   "r9   r:   r:   s  s'   € ÷ lñ l¨=ð lÀMð lÐVZñ lr;   c                ó"  a€ \         P                  ! \        T ;'       g    R4      P                  4       P	                  4       4      p\        T;'       g    R4      P                  4       P                  R4      oVe3   S'       d+   SVP                  ;'       g    RP                  R4      8X  d   R# \        ;QJ d2    V3R l\         P                  ! 4        4       F  '       g   K   R# 	  R# ! V3R l\         P                  ! 4        4       4      # )a‰  True when ``base_url`` is another built-in provider's canonical endpoint, not ``provider``'s.

A persisted session route that pairs one provider with another's endpoint is left over from a
switch that kept the old URL (openai-codex + the Nous Portal URL sent the Codex slug to the Portal).
Only registered providers are judged: a custom or proxy URL is never another provider's canonical one.
r[   r}   Fc              3  ót   <"  € T F-  pSVP                   ;'       g    R P                  R4      8H  x € K/  	  R# 5i)r[   r}   N)Úinference_base_urlrb   )Ú.0ÚotherÚurls   & €r9   Ú	<genexpr>Ú/is_foreign_provider_endpoint.<locals>.<genexpr>~  s1   øé € ÐkÑPjÀuˆs�u×/Ñ/×5Ð5°2×=Ñ=¸cÓBÖBÓPjùs   ƒ8œ8T)	r   rL   rW   rq   ra   rb   rð   ÚanyÚvalues)r�   rz   r¬   ró   s   && @r9   Úis_foreign_provider_endpointrø   s  s¾   ø€ ô  ×#Ò#¤C¨¯¨°BÓ$7×$=Ñ$=Ó$?×$EÑ$EÓ$GÓH€GÜ
ˆh�nˆn˜"Ó
×
#Ñ
#Ó
%×
,Ñ
,¨SÓ
1€CØ‚Ÿc S¨W×-GÑ-G×-MÐ-MÈ2×,UÑ,UÐVYÓ,ZÔ%ZÙß‹3ÔkÔPa×PhÒPhÔPjÓk�3Œ3ÐkŠ3Ðkˆ3ÔkÔPa×PhÒPhÔPjÓkÓkÐkr;   c               ó    € V ^8„  d   QhRRRR/# )r5   rz   rW   rX   rY   r7   )r8   s   "r9   r:   r:   �  s   € ÷ _ñ _¨cð _°dñ _r;   c                ó  € T ;'       g    RP                  4       pV'       d$   \        V4      ;'       g    RP                  4       MRp\        V4      ;'       d5    VR8H  ;'       g(    VP	                  R4      ;'       g    \        V4      R8H  # )am  Whether a configured ``model.base_url`` plausibly speaks the Anthropic Messages protocol:
official Anthropic/Claude hosts, Azure Foundry, or ``/anthropic`` / Kimi ``/coding`` proxies
(the same signal :func:`_detect_api_mode_for_url` uses). Otherwise the caller falls back to
``https://api.anthropic.com`` so a stale non-Anthropic URL cannot hijack native Anthropic.r[   rw   rx   )z.anthropic.comz.claude.comz
.azure.com)rq   r/   ra   rY   r   r„   )rz   Ú	candidater�   s   &  r9   Ú_anthropic_base_url_override_okrü   �  s•   € ð
 —�˜R×&Ñ&Ó(€Iß?HÔ! )Ó,×2Ð2°×9Ñ9Ô;Èb€HÜ�‹>÷ _ð _˜xÐ+>Ñ>÷  ^ð  ^À(×BSÑBSð  UDó  CE÷  ^ð  ^Ü":¸9Ó"EÐI]Ñ"]ð_r;   c               ó    € V ^8„  d   QhRRRR/# rç   r7   )r8   s   "r9   r:   r:   Œ  s   € ÷ Qñ Q ~ð Q¸#ñ Qr;   c                óD   € \        V R4      p\        V4      '       d   V# R# )zFConfig base_url for native Anthropic, or "" when absent/untrustworthy.Ú	anthropicr[   )rì   rü   )rŸ   rl   s   & r9   Ú_anthropic_cfg_base_urlr   Œ  s#   € ä0°¸KÓH€LÜ:¸<×HÒHˆ<ÐPÈbÐPr;   r�   c               ó    € V ^8„  d   QhRRRR/# )r5   r�   ú
str | NonerX   rW   r7   )r8   s   "r9   r:   r:   ’  s   € ÷ 
ñ 
¨
ð 
¸cñ 
r;   c                óš   € ^ RI Hp V! V R7      pV'       g4   V '       d   V! 4       '       d   \        RV  R24      h\        \        4      hV# )é    )Úresolve_anthropic_token©r�   z+Anthropic credentials are rate-limited for z@; other Claude models remain available (see `hermes auth list`).)Úagent.anthropic_credentialsr  r   Ú_NO_ANTHROPIC_CREDENTIALS_MSG)r�   r  rE   s   $  r9   Ú_anthropic_token_or_raiser	  ’  sT   € ÝCÙ#¨%Ô0€Eß÷ Ñ,×.Ò.ÜÐIÈ%Èð Q]ð ]ó ^ð ^äÔ5Ó6Ð6Ø€Lr;   c               ó    € V ^8„  d   QhRRRR/# ©r5   rz   rW   rX   r7   )r8   s   "r9   r:   r:   Ÿ  s   € ÷ Fñ F Cð F¨Cñ Fr;   c                óê  € \        V 4      pV'       du   \        ;QJ d2    R VP                  R4      R
,           4       F  '       g   K   RM'	  RM#! R VP                  R4      R
,           4       4      '       g   VR8X  g   RV9   d   R# VP                  R4       Uu. uF  q"'       g   K  VNK  	  ppV'       d"   V^ ,          R9   d   VP                  ^ 4       K)  \	        V4      ^8¼  d.   RP                  R VR,           4       4      P                  4       MRpV'       d%   V^ ,          P                  4       '       d   VR9   d   R# \        V R	2R4      ;'       g    RP                  4       # u upi )uX  ``<VENDOR>_API_KEY`` from the env, vendor = registrable hostname label (``api.deepseek.com``
â†’ ``deepseek``). Lookalike hosts pick the ATTACKER's label (api.deepseek.com.attacker.test â†’
"attacker") so DEEPSEEK_API_KEY stays put. "" for IPs/loopback/single-label hosts and for
OPENAI/OPENROUTER/OLLAMA, which have their own host-gated paths.c              3  ó@   "  € T F  qP                  4       x € K  	  R # 5irK   )Úisdigit©rñ   Úchs   & r9   rô   Ú(_host_derived_api_key.<locals>.<genexpr>¥  s   é € ÐJÑ2I¨BŸ:™:Ÿ<˜<Ó2Iùs   ‚r\   TFr]   Ú:r[   c              3  óT   "  € T F  qP                  4       '       d   TMR x € K   	  R# 5i)Ú_N)Úisalnumr  s   & r9   rô   r  ª  s   é € ÐI¹j¸Ÿj™jŸlšl™°Ô3»jùs   ‚&(Ú_API_KEYéÿÿÿÿ)ÚapiÚwwwéþÿÿÿ)ÚOPENAIÚ
OPENROUTERÚOLLAMA)
r/   rö   ÚsplitÚpopÚlenÚjoinÚupperÚisalphar   rq   )rz   r�   ÚlblÚlabelsÚ	sanitizeds   &    r9   Ú_host_derived_api_keyr'  Ÿ  s  € ô
 ! Ó*€Hß—s“sÑJ°(·.±.ÀÓ2EÀbÖ2IÓJ—s—s’sÑJ°(·.±.ÀÓ2EÀbÖ2IÓJ×JÒJÈhÐZeÔNeÐilÐpxÔixÙØ%Ÿ^™^¨CÔ0Ó8Ñ0�c³C�cˆcÑ0€FÐ8ß
�V˜A•Y .Ô0Ø�
‰
�1ŽÜUXÐY_ÓU`ÐdeÔUe�—‘ÑI¸fÀR¾jÓIÓI×OÑOÔQÐkm€Iß˜I a�L×0Ñ0×2Ò2°iÐCeÔ6eÙÜ˜i˜[¨Ð1°2Ó6×<Ð<¸"×CÑCÓEÐEùò 9s   Â	E0Â+E0c               ó$   € V ^8„  d   QhRRRRRR/# )r5   rz   rW   ÚollamarY   rX   Úlistr7   )r8   s   "r9   r:   r:   °  s!   € ÷ :ñ :¨Sð :¸Tð :Àdñ :r;   c               ó\  € \        V R4      ;'       g    \        V R4      p\        RR4      P                  4       P                  R4      pT;'       g@    \	        V4      ;'       d-    T ;'       g    RP                  4       P                  R4      V8H  pV'       d0   \        V R4      '       d   \        RR4      P                  4       MR.M. pYB'       d   \        RR4      P                  4       MR\        V R	4      '       d   \        R
R4      P                  4       MR\        V 4      .,           # )a9  Env API keys gated on their authoritative hosts, then the host-derived ``<VENDOR>_API_KEY``.
Sending OPENAI/OPENROUTER/OLLAMA keys to an unrelated endpoint leaks credentials
(GHSA-76xc-57q6-vm5m); match on HOST, not substring. ``_host_derived_api_key`` skips OLLAMA, so
callers that want it opt in via ``ollama``.ú
openai.comzopenai.azure.comÚOPENAI_BASE_URLr[   r}   z
ollama.comÚOLLAMA_API_KEYÚOPENAI_API_KEYro   ÚOPENROUTER_API_KEY)r.   r   rq   rb   rY   r'  )rz   r)  Ú	is_openaiÚenv_openai_baseÚ
candidatess   &$   r9   Ú_host_gated_env_key_candidatesr4  °  s  € ô
 & h°Ó=×tÐtÔAVÐW_ÐasÓAt€Iô %Ð%6¸Ó;×AÑAÓC×JÑJÈ3ÓO€OØ×pÐpœd ?Ó3×oÐo¸¿¸ÀR×8NÑ8NÓ8P×8WÑ8WÐX[Ó8\Ð`oÑ8o€I÷ }CÔBWÐX`Ðbn×BoÒBo”.Ð!1°2Ó6×<Ñ<Ô>ÐuwÑxð  IK€JØÎœÐ(8¸"Ó=×CÑCÔEÐXZÜMbÐckÐm|×M}ÒM}œÐ(<¸bÓA×GÑGÔIð  DFÜ.¨xÓ8ð:õ :ð :r;   c               ó    € V ^8„  d   QhRRRR/# ©r5   Úentryr   rX   rW   r7   )r8   s   "r9   r:   r:   À  s   € ÷ Yñ Y˜sð Y sñ Yr;   c                óF   € \        V R R4      ;'       g    \        V RR4      # )Úruntime_api_keyNÚaccess_tokenr[   ©Úgetattr©r7  s   &r9   Ú_pool_entry_api_keyr>  À  s$   € Ü�5Ð+¨TÓ2×XÐX´g¸eÀ^ÐUWÓ6XÐXr;   c               ó    € V ^8„  d   QhRRRR/# r6  r7   )r8   s   "r9   r:   r:   Ä  s   € ÷ ^ñ ^ ð ^¨ñ ^r;   c                óZ   € \        V R R4      ;'       g    \        V RR4      ;'       g    R# )Úruntime_base_urlNrz   r[   r;  r=  s   &r9   Ú_pool_entry_base_urlrB  Ä  s-   € Ü�5Ð,¨dÓ3×]Ð]´w¸uÀjÐRVÓ7W×]Ð]Ð[]Ð]r;   c               ó$   € V ^8„  d   QhRRRRRR/# )r5   r7  r   Úmin_ttlÚintrX   rY   r7   )r8   s   "r9   r:   r:   È  s&   € ÷ ñ  #ð °ð ¸ñ r;   c                óX   € \        R Uu/ uF  q"\        WR4      bK  	  upV4      # u upi )Ú	agent_keyN)rG  Úagent_key_expires_atÚscope)r   r<  )r7  rD  Úks   && r9   Ú_nous_entry_key_usablerK  È  s/   € ÜÑEsÓ tÑEsÀ¤G¨E°dÓ$;Ò!;ÑEsÑ tÐv}Ó~Ð~ùÒ ts   Š'c               ó   € V ^8„  d   QhRR/# )r5   rX   rE  r7   )r8   s   "r9   r:   r:   Ì  s   € ÷ Eñ E˜3ñ Er;   c                 ó.   € \        ^<\        RR4      4      # )é<   ÚHERMES_NOUS_MIN_KEY_TTL_SECONDSi  )Úmaxr1   r7   r;   r9   Ú_nous_min_key_ttlrQ  Ì  s   € Üˆr”7Ð<¸dÓCÓDÐDr;   c               ó   € V ^8„  d   QhRR/# ©r5   rX   r6   r7   )r8   s   "r9   r:   r:   Ð  s   € ÷ xñ x˜^ñ xr;   c                 ó@   € \        \        \        R R4      4      R7      # )ÚHERMES_NOUS_TIMEOUT_SECONDSÚ15)Útimeout_seconds)r   Úfloatr   r7   r;   r9   Ú_resolve_nous_credsrY  Ð  s   € Ü+¼EÄ.ÐQnÐptÓBuÓ<vÔwÐwr;   c               ó(   € V ^8„  d   QhRRRRRRRR/# )r5   r�   rW   r¢   rz   rX   r7   )r8   s   "r9   r:   r:   Ô  s(   € ÷ 
ñ 
 ð 
°ð 
¸sð 
Àsñ 
r;   c                óÂ   € \         P                  ! V 4      e   \         P                  ! WV4      pV R8X  d   \        P                  ! V4      pV R8X  d   \        V4      pV# )u  Shared tail for pool-entry and api-key paths: OpenCode /v1 rule (OpenCode URLs end with /v1
for OpenAI-compatible models but the Anthropic SDK prepends its own /v1/messages â€” strip for
anthropic_messages, re-append otherwise), then LM Studio normalization.ÚlmstudiorÍ   )rÀ   rÎ   Únormalize_opencode_base_urlrh   Ú$_normalize_lmstudio_runtime_base_urlr$   )r�   r¢   rz   s   &&&r9   Ú_finalize_base_urlr_  Ô  sV   € ô ×'Ò'¨Ó1Ò=Ü×6Ò6°xÈ8ÓTˆØ�:ÔÜ×@Ò@ÀÓJˆØ�8ÔÜ,¨XÓ6ˆØ€Or;   c               ó    € V ^8„  d   QhRRRR/# r  r7   )r8   s   "r9   r:   r:   ä  s   € ÷ ñ  sð ¨sñ r;   c                óú  € V '       g   R#  ^ RI pV P                  R4      pTP                  VP                  R4      '       d   TMVR,           R,           R
R7      pVP                  '       d`   VP                  4       P                  R. 4      p\        V4      ^8X  d0   V^ ,          P                  RR4      '       d   V^ ,          R,          # R#   \         d"   p\        P                  R	Y4        Rp?R# Rp?ii ; i)zFQuery a local server for its model name when only one model is loaded.r[   Nr}   r™   z/models)ÚtimeoutÚdatar«   z$Auto-detect model from %s failed: %s)r5   é   )
Úrequestsrb   rL   r   ÚokÚjsonr   ri   r£   Údebug)rz   re  ró   Úrespr'   Úexcs   &     r9   Ú_auto_detect_local_modelrk  ä  sÆ   € çÙð	LÛØ�o‰o˜cÓ"ˆØ�|‰| C§L¡L°×$7Ò$7™S¸SÀ5½[ÈIÕUÐ_eˆ|ÓfˆØ�7�7ˆ7Ø—Y‘Y“[—_‘_ V¨RÓ0ˆFÜ�6‹{˜aÔ F¨1¥I§M¡M°$¸×$;Ò$;Ø˜a•y •Ð&ñ øô ô LÜ�‰Ð;¸X×KÐKÙûðLús$   Œ6C ÁA8C Â<C ÃC:ÃC5Ã5C:c               ó   € V ^8„  d   QhRR/# rS  r7   )r8   s   "r9   r:   r:   õ  s   € ÷ ñ ˜>ñ r;   c                 ó   € \        4       p V P                  R4      p\        V\        4      '       d)   VP	                  4       '       d   RVP	                  4       /# \        V\
        4      '       g   / # \        V4      pVP                  R4      '       g$   VP                  R4      '       d   VR,          VR&   VP                  R4      p\        V\
        4      '       dp   \        P                  ! V4      w  rET;'       g%    \        VP                  R4      ;'       g    R4      pWBR&   V'       d   VP                  R4      '       g   WRR&   TpVP                  R4      ;'       g    RP	                  4       p\        T;'       g    R4      P	                  4       '       g0   V'       d(   \        V4      R9   d   \        V4      pV'       d   WrR&   V# )zª``model`` config section with ``model`` accepted as an alias for ``default``, a dict
``default`` split into model/provider, and a local single-model server auto-detected.r�   r3   r�   r[   rz   )r]   r`   )
rM   rL   r‰   rW   rq   Údictr=   Úsplit_model_config_defaultr/   rk  )r&   rŸ   ÚcfgÚ_defaultÚ	cfg_modelrm   rz   r“   s           r9   Ú_get_model_configrs  õ  s`  € ô ‹]€FØ—
‘
˜7Ó#€IÜ�)œS×!Ò! i§o¡o×&7Ò&7Ø˜9Ÿ?™?Ó,Ð-Ð-Ü�i¤×&Ò&Øˆ	Ü
ˆy‹/€CØ�7‰7�9×Ò #§'¡'¨'×"2Ò"2Ø˜W�ˆˆI‰Ø�w‰w�yÓ!€HÜ�(œD×!Ò!Ü"-×"HÒ"HÈÓ"RÑˆ	Ø#×KÐK¤s¨9¯=©=¸Ó+D×+JÐ+JÈÓ'KˆØ"ˆI‰ß §¡¨
× 3Ò 3Ø*�
‰OØˆØ—‘˜
Ó#×)Ð) r×0Ñ0Ó2€HÜˆx�~ˆ~˜2Ó×$Ñ$×&Ò&¯8Ô8IÈ(Ó8SÐWqÔ8qÜ+¨HÓ5ˆßØ%�	‰NØ€Jr;   c               ó    € V ^8„  d   QhRRRR/# )r5   Ú	requestedr{   rX   rW   r7   )r8   s   "r9   r:   r:     s   € ÷ /ñ /¨-ð /À3ñ /r;   c                óî  € V '       d5   V P                  4       '       d   V P                  4       P                  4       # \        4       P                  R4      p\	        V\
        4      '       d5   VP                  4       '       d   VP                  4       P                  4       # ^ RIHp V! 4       pVe   VP                  RR4      M\        RR4      p V P                  4       P                  4       ;'       g    R# )zÆProvider request from explicit arg, then config, then ``HERMES_INFERENCE_PROVIDER``, else
"auto". Config beats the env so chat uses the endpoint the user last saved, not a stale
shell/.env override.r�   )Úbound_client_envÚHERMES_INFERENCE_PROVIDERr[   rp   )	rq   ra   rs  rL   r‰   rW   Úagent.session_client_envrw  r   )ru  rm   rw  Úclients   &   r9   Úresolve_requested_providerr{    sÆ   € ÷ �Y—_‘_×&Ò&Ø�‰Ó ×&Ñ&Ó(Ð(Ü$Ó&×*Ñ*¨:Ó6€LÜ�,¤×$Ò$¨×);Ñ);×)=Ò)=Ø×!Ñ!Ó#×)Ñ)Ó+Ð+Ý9ÙÓ€FØ?EÒ?Q�—
‘
Ð6¸Ô;ÔWeð  gBð  DFó  XG€IØ�?‰?Ó×"Ñ"Ó$×.Ð.¨Ð.r;   )Ú_LLAMACPP_ALIASESÚ_apply_custom_provider_extrasÚ"_custom_provider_request_overridesÚ_filter_capabilitiesÚ_find_custom_identityÚ_get_named_custom_providerÚ_lift_common_custom_fieldsÚ_lift_extra_headersÚ_lift_model_capabilitiesÚ_normalize_base_url_for_matchÚ_normalize_custom_provider_nameÚ_resolve_named_custom_runtimeÚ_try_resolve_from_custom_poolÚcanonical_custom_identityrß   Úexpand_direct_api_aliasÚfind_custom_provider_identityÚ&find_custom_provider_identity_by_modelÚhas_named_custom_providerÚis_routable_provider)Ú_is_external_process_providerÚ_resolve_azure_foundry_runtimeÚ_resolve_bedrock_runtimeÚ!_resolve_external_process_runtimeÚ_resolve_openrouter_runtimerÞ   z	xai-oauthz
qwen-oauthÚ
openrouterúminimax-oauthc                 óD   € \        \        P                  ! R 4      RR4      # )r•  rð   r[   )r<  r   rL   r7   r;   r9   Ú<lambda>r—  9  s   € ´GÔ<M×<QÒ<QÐRaÓ<bÐdxÐz|Ô4}r;   rÔ   zdict[str, tuple]Ú_POOL_ENTRY_SIMPLE_MODESc               ó   € V ^8„  d   QhRR/# )r5   rX   Útupler7   )r8   s   "r9   r:   r:   >  s   € ÷ ,~ñ ,~ÐW\ñ ,~r;   c                óä  € V R8X  dA   \        \        VRR4      4      P                  R4      '       d   \        W 4      ;'       g    TpV \        9   dó   \        V ,          w  rVV R8X  dS   \        RR4      P                  4       P                  R4      pV'       d   WW3# VRV39   d   \        W 4      ;'       g    TpV R8X  d^   \        R,          P                  ;'       g    RP                  R4      pVP                  R4      RV39   d   \        W 4      ;'       g    TpYT;'       g    \        V4      '       d	   V! 4       3# T3# V R	8X  d&   R
\        V4      ;'       g    T;'       g    \        3# V R8X  d*   \        V4      \        4       ;'       g    R;'       g    T3# V R8X  d<   \        V\        VRR4      VR7      pYT;'       g    \        R,          P                  3# V R8X  d{   Rp\!        V4      R8X  d;   \        VR4      ;'       g    Tp\#        VP%                  R4      4      ;'       g    Tp\'        W54      pYUR
8X  d   \(        P*                  ! RRV4      3# T3# \        P$                  ! V 4      p	V	'       da   V'       d0   VP                  R4      V	P                  P                  R4      8X  d*   \        W 4      ;'       g    T;'       g    V	P                  p\-        WWCRR7      V3# )z6(api_mode, base_url) for a pool entry of ``provider``.rÍ   Úsourcer[   zenv:rÞ   ÚHERMES_CODEX_BASE_URLr}   rÔ   rÿ   rx   Únousr¿   r9  rÓ   úazure-foundryrv   r¢   z/v1/?$TrÕ   )rW   r<  r›   rì   r˜  r   rq   rb   r   rð   Úcallabler   Ú_ANTHROPIC_DEFAULT_BASE_URLr-   r   rÄ   r¶   r�   rL   rÉ   ÚreÚsubrÐ   )
r�   r7  rŸ   rÆ   rz   r¢   Údefault_urlÚoverride_urlÚ	canonicalr¬   s
   &&&&&     r9   Ú_pool_entry_mode_and_urlr§  >  s¨  € à�8Ô¤¤G¨E°8¸RÓ$@Ó A× LÑ LÈV× TÒ TÜ0°ÓE×QÐQÈˆØÔ+Ô+Ü 8¸Õ BÑˆØ�~Ô%ô *Ð*AÀ2ÓF×LÑLÓN×UÑUÐVYÓZˆLßØÐ-Ð-ð ˜B Ð,Ô,Ü8¸ÓM×YÐYÐQY�Ø�uÔô +¨5Õ1×DÑD×JÐJÈ×RÑRÐSVÓWˆIØ�‰˜sÓ#¨¨I Ô6Ü8¸ÓM×YÐYÐQY�Ø×^Ð^´xÀ×7LÒ7L¡k£mÐ^Ð^ÐR]Ð^Ð^Ø�;ÔØ#Ô%<¸YÓ%G×%rÐ%rÈ8×%rÐ%rÔWrÐrÐrØ�6ÔÜ˜_Ó-Ô0LÓ0N×/aÐ0TÐRT×/aÐ/aÐYaÐaÐaØ�9ÔÜ,¨Y¼ÀÐGXÐZ\Ó8]Ðl{Ô|ˆØ×TÐTÔ%6°yÕ%A×%TÑ%TÐTÐTØ�?Ô"Ø%ˆÜ˜Ó# Ô6Ü4°YÀÓP×\Ð\ÐT\ˆHÜ& y§}¡}°ZÓ'@ÓA×MÐMÀXˆHÜ+¨OÓFˆØÐI]Ô=]œ"Ÿ&š& ¨B°Ó9ÐlÐlÐckÐlÐlô  ×#Ò# HÓ-€GßŸ H§O¡O°CÓ$8¸G×<VÑ<V×<]Ñ<]Ð^aÓ<bÔ$bÜ0°ÓE×oÐoÈ×oÐoÐU\×UoÑUoˆÜ+¨HÀÐnrÔsÐu}Ð}Ð}r;   rŸ   Úpoolc               ó4   € V ^8„  d   QhRRRRRRRRRR	R
RRR/# )r5   r�   rW   r7  r   r×   rŸ   rÙ   r¨  zOptional[CredentialPool]r¹   r{   rX   r6   r7   )r8   s   "r9   r:   r:   m  sL   € ÷ Qñ Q°#ð QÐ>Nð QÐdgð QØ0HðQØWoðQà3@ðQàLZñQr;   c                óì   € T;'       g    \        4       p\        WV\        W54      \        V4      P	                  R 4      4      w  rg\        WV4      p\        WV\        V4      \        VRR4      WBR7      # )r}   rœ  r¨  )rœ  Úcredential_poolr×   )	rs  r§  r»   rB  rb   r_  rå   r>  r<  )r�   r7  r×   rŸ   r¨  r¹   r¢   rz   s   $$$$$$  r9   Ú _resolve_runtime_from_pool_entryr¬  m  s}   € ð ×0Ð0Ô.Ó0€IÜ1°(À9ÔN^Ð_hÓNwÜ2FÀuÓ2M×2TÑ2TÐUXÓ2Yó[Ñ€Hä! (°hÓ?€HÜ�H¨Ô2EÀeÓ2LÔU\Ð]bÐdlÐntÓUuØ$(ôQð Qr;   c               ó   € V ^8„  d   QhRR/# )r5   rX   rY   r7   )r8   s   "r9   r:   r:   x  s   € ÷ Hñ HÐgkñ Hr;   c                ó(  € \        VP                  R4      ;'       g    R4      P                  4       p\        RR4      P                  4       ;'       g    \        RR4      P                  4       p\	        V4      ;'       d>    \        V4      R9   ;'       g(    \        V4      R8H  ;'       d    \        VR4      '       * p\	        T;'       g    T;'       g    T4      pV R9   ;'       d*    V'       * ;'       d    \	        T;'       g    T4      '       * # )	z]OpenRouter pool only for a plain openrouter/auto request with no custom endpoint or override.rz   r[   r-  r(   r”  ro   >   rp   rg   >   rp   r”  )rW   rL   rq   r   rY   r¶   r.   )r×   rŸ   Úexplicit_api_keyÚexplicit_base_urlrl   Úenv_base_urlsÚcfg_is_mirrorÚhas_custom_endpoints   &&&&    r9   Ú_openrouter_should_use_poolr´  x  s  € ä�y—}‘} ZÓ0×6Ð6°BÓ7×=Ñ=Ó?€LÜ"Ð#4°bÓ9×?Ñ?ÓA×vÐvÄ^ÐTiÐkmÓEn×EtÑEtÓEv€Mô ˜Ó&÷ ð Ü�iÓ Ð$6Ñ6÷ 	sð 	sÜ˜)Ó$¨Ñ4×qÐqÔ=RÐS_ÐapÓ=qÔ9qð ô Ð0×RÐR°M×RÐRÀ]ÓSÐØÐ!7Ñ7÷  Hð  HÐ@SÔ<S÷  Hð  HÔ\`Ðaq÷  bGð  bGð  vGó  ]Hô  YHð  Hr;   c               ó$   € V ^8„  d   QhRRRRRR/# )r5   r¨  r   r7  r   Úpool_api_keyrW   r7   )r8   s   "r9   r:   r:   ‡  s!   € ÷ ñ  >ð ¸#ð ÈSñ r;   c                óp  € \        4       p\        W4      '       d   W3# \        P                  R4        V P	                  4       pVe   T\        V4      r!V'       d   \        W4      '       g   \        P                  R4       RpW3#   \
         d#   p\        P                  RT4       Rp Rp?LkRp?ii ; i)u  Nous pool entries carry the agent_key (an invoke JWT) which the pool does not refresh on
selection (avoids network calls in `hermes auth list`); refresh here before falling back to
singleton auth resolution. Returns (entry, pool_api_key) â€” key "" when still unusable.zINous pool entry agent_key expired/missing, refreshing selected pool entryz"Nous pool entry refresh failed: %sNzRNous pool entry agent_key still unavailable, falling through to runtime resolutionr[   )rQ  rK  r£   rh  Útry_refresh_currentri   r>  )r¨  r7  r¶  rD  Ú	refreshedrj  s   &&&   r9   Ú_refresh_nous_pool_entryrº  ‡  s¤   € ô  Ó!€GÜ˜e×-Ò-ØÐ"Ð"Ü
‡L�LÐ\Ô]ðØ×,Ñ,Ó.ˆ	ð ÒØ'Ô)<¸YÓ)Gˆ|ßÔ5°e×EÒEÜ�‰ÐiÔjØˆØÐÐøô ô Ü�‰Ð9¸3Ô?Ø�	ûðús   µB ÂB5ÂB0Â0B5c               ó$   € V ^8„  d   QhRRRRRR/# )r5   r7  r   r¶  rW   rX   r7   )r8   s   "r9   r:   r:   œ  s!   € ÷ ñ ¨ð ¸3ð À3ñ r;   c                óÌ   € ^ RI HpHp V'       d   V! V4      ^ ,          '       g   V# V! V4      w  rEWA8X  d   V'       g   ^ RIHp V! V4       V# W@n        V'       d   WPn        V# )u±  Exchange a copilot pool entry that still carries the RAW GitHub token.

The seeder skips the exchange while copilot is merely discovered (ambient gh login, not in
config); here copilot IS the runtime target (`/model copilot/â€¦ --session`, `--provider copilot`,
delegation/cron overrides), and a raw token routes to the language-server integrator whose
allowlist omits enterprise-only models (400 model_not_available_for_integrator).)Úget_copilot_api_tokenÚvalidate_copilot_token)Ú"_warn_copilot_raw_degradation_once)Úhermes_cli.copilot_authr½  r¾  Úagent.credential_poolr¿  r:  rz   )r7  r¶  r½  r¾  Ú	api_tokenÚenterprise_base_urlr¿  s   &&     r9   Ú_exchange_copilot_pool_entryrÄ  œ  s\   € ÷ VßÑ5°lÓCÀA×FÔFØÐÙ%:¸<Ó%HÑ"€IØÔ ×)<ÝLÙ*¨<Ô8ØÐØ"ÔßØ,ŒØÐr;   c               ó(   € V ^8„  d   QhRRRRRRRR/# )r5   r�   rW   r×   rŸ   r6   rX   rÙ   r7   )r8   s   "r9   r:   r:   ±  s)   € ÷ ñ  ð ¸#ð È.ð Ø(@ñr;   c           	     ó  € V R8g  ;'       g    \        WVV4      p V'       d   \        V 4      MRpV'       d   VP                  4       '       g   R# TP	                  T;'       g    RR7      pVf   R# \        V4      p	V R8X  d   \        WxV	4      w  r‰MV R8X  d   \        W‰4      p	\        V	4      '       g   R# V	'       d,   \        Wp\        V4      R7      '       d   \        WVW'VR7      # R#   \         d    Rp LÌi ; i)zQRuntime from the provider's credential pool, or None to continue down the ladder.r”  Nr  rž  r¿   r¡   )r�   r7  r×   rŸ   r¨  r¹   )r´  r   ri   Úhas_credentialsÚselectr>  rº  rÄ  r!   r   rB  r¬  )
r�   r×   rŸ   r¯  r°  r¹   Úshould_use_poolr¨  r7  r¶  s
   &&&&&&    r9   Ú_resolve_from_poolrÊ  ±  s  € ð  ,Ñ.÷ `ð `Ô2MÐN`Ðm}ØM^ó3`€Oðß&5Œy˜Ô"¸4ˆ÷ �T×)Ñ)×+Ò+ÙØ�K‰K˜l×2Ð2¨dˆKÓ3€EØ‚}ÙÜ& uÓ-€LØ�6ÔÜ6°tÀLÓQÑˆˆ|Ø	�YÔ	Ü3°EÓHˆÜ˜\×*Ò*ÙßÔ8¸ÔRfÐglÓRm×nÓnÜ/¸ÐcuØ:CÐ]iôkð 	káøô# ô ØŠðús   œC. ¤C. Ã.C>Ã=C>c           	     ó”   € T;'       g    \        V4      ;'       g    \        pT;'       g    \        VR 7      p\        RRW2RV R7      # )r  rÿ   rx   Úexplicit©rœ  r×   )r   r¡  r	  rå   )r×   rŸ   r½   rz   r¹   s   &&&&&r9   Ú_explicit_anthropicrÎ  Ï  sQ   € Ø×\Ð\Ô2°9Ó=×\Ð\ÔA\€HØ×FÐFÔ2¸ÔF€GÜ�KÐ!5°xÐQ[ð  qCô  Dð  Dr;   c                óÖ   € V '       d   WV3# V! 4       pVP                  RR4      T;'       g,    VP                  RR4      P                  R4      ;'       g    TVP                  V4      3# )z‘When no explicit key was given, take api_key / expiry / base_url from stored credentials
(an explicit --base-url still wins over the stored one).r½   r[   rz   r}   )rL   rb   )r½   r°  rz   ÚexpiryÚ
expiry_keyÚresolveÚcredss   &&&&&& r9   Ú_creds_fallbackrÔ  Õ  sv   € ÷ Ø &Ð(Ð(Ù‹I€EØ�9‰9�Y Ó#Ð%6×%kÐ%k¸%¿)¹)ÀJÐPRÓ:S×:ZÑ:ZÐ[^Ó:_×%kÐ%kÐckÐmr×mvÑmvð  xBó  nCð  Cð  Cr;   c           
     ól   € \        Y#T;'       g    \        R R\        4      w  r%p\        RRWRRVV R7      # )NÚlast_refreshrÞ   ru   rÌ  )rœ  rÖ  r×   )rÔ  r   r   rå   )r×   rŸ   r½   r°  r¹   rz   rÖ  s   &&&&&  r9   Ú_explicit_codexr×  Þ  sE   € Ü&5°gÐRc×R}ÐR}Ôg}Ø6:¸NÔLmó'oÑ#€G�|ä�NÐ$5°xÐQ[ÐjvØ'9ô;ð ;r;   c           
     óˆ  € \         P                  ! R 4      ;'       g    / pT;'       gb    \        4       ;'       gP    \        VP	                  R4      ;'       g    \         P
                  4      P                  4       P                  R4      pT;'       gO    \        V\        4       4      '       d3   \        VP	                  R4      ;'       g    R4      P                  4       MRp\        Y#TVP	                  R4      ;'       g    VP	                  R4      R\        4      w  r&p\        R \        \        W4      4      WbRWpR7      # )	rž  rð   r}   rG  r[   rH  Ú
expires_atrÌ  )rœ  rÙ  r×   )rh   Úget_provider_auth_stater   rW   rL   ÚDEFAULT_NOUS_INFERENCE_URLrq   rb   r   rQ  rÔ  rY  rå   r-   r»   )r×   rŸ   r½   r°  r¹   Ústaterz   rÙ  s   &&&&&   r9   Ú_explicit_nousrÝ  å  s$  € Ü×,Ò,¨VÓ4×:Ð:¸€EØ!÷ sð sÔ%AÓ%C÷ sð sÜ�u—y‘yÐ!5Ó6×]Ð]¼(×:]Ñ:]Ó^×dÑdÓf×mÑmÐnqÓrð ð ÷  Að  AÔG[Ð\aÔctÓcv×GwÒGwœ#˜eŸi™i¨Ó4×:Ð:¸Ó;×AÑAÔCÐ}€GÜ$3°GÐPXØ49·I±IÐ>TÓ4U×4pÐ4pÐY^×YbÑYbÐcoÓYpÐr~Ü4Gó%IÑ!€G�zô �FœMÔ*:¸9Ó*SÓTÐV^ÐpzØ)ôRð Rr;   c               ó(   € V ^8„  d   QhRRRRRRRR/# )r5   r�   rW   r½   rz   rX   r7   )r8   s   "r9   r:   r:   ó  s.   € ÷ Gñ G ð G¨cð G¸Sð GÀSñ Gr;   c                óR   € V R8X  d    V'       g   \        V4      '       d   \        # T# )u`   Actual Computer's loopback daemon speaks a no-auth local API â€” substitute the placeholder key.rÍ   )r"   r   )r�   r½   rz   s   &&&r9   Ú_actual_local_keyrà  ó  s.   € à.6¸(Ô.BÏ7ÔWoÐpx×WyÒWyÔ*ð  Gð  @Gð  Gr;   c               ó$   € V ^8„  d   QhRRRRRR/# )r5   r�   rW   rz   rX   r7   )r8   s   "r9   r:   r:   ø  s&   € ÷ Uñ U˜#ð U¨ð U°ñ Ur;   c                ó*   € V R 8X  d   \        V4      # T# )rÍ   )r$   )r�   rz   s   &&r9   Ú_actual_urlrã  ø  s   € Ø2:¸hÔ2FÔ$ XÓ.ÐTÈHÐTr;   c           
     ó   € V'       gÆ   V R 8X  d0   \        W04      ;'       g    \        V 4      P                  RR4      pM�V R
9   d,   \        V 4      P                  RR4      P                  R4      pM]VP                  '       d4   \        VP                  R4      P                  4       P                  R4      MRpT;'       g    VP                  p\        W4      pV'       gP   \        V 4      pVP                  RR4      pV'       g+   \        WP                  RR4      P                  R4      4      p\        YYET;'       g    VP                  RR4      RR7      p	\        W	V4      p\        WV4      p\        W	VP                  R4      VRVR	7      # )rÍ   rz   r[   r}   r½   r3   TrÕ   rÌ  rÍ  >   úkimi-codingúkimi-coding-cn)rì   r   rL   rb   Úbase_url_env_varr   rq   rð   rã  rÖ   r_  rà  rå   )
r�   r¬   r×   rŸ   r½   rz   r¹   Úenv_urlrÓ  r¢   s
   &&&&&&&   r9   Ú_explicit_api_key_providerré  ü  sc  € ßØ�xÔÜ5°iÓJ÷ ^ð ^Ü?ÀÓI×MÑMÈjÐZ\Ó]ñ àÐ:Ô:Ü;¸HÓE×IÑIÈ*ÐVXÓY×`Ñ`ÐadÓe‰HàZa×Zr×ZrÐZr”n W×%=Ñ%=¸rÓB×HÑHÓJ×QÑQÐRUÔVÐxzˆGØ×<Ð< '×"<Ñ"<ˆHÜ˜8Ó.€HßÜ4°XÓ>ˆØ—)‘)˜I rÓ*ˆßÜ" 8¯Y©Y°zÀ2Ó-F×-MÑ-MÈcÓ-RÓSˆHÜ)¨(¸wÐR^×R~ÐR~Ðbk×boÑboÐpyÐ{}Ób~Ø<@ôB€Hä! (°hÓ?€HÜ °8Ó<€GÜ�H¨¯©¸Ó(<¸gÈjÐmô  Að  Ar;   rÿ   rž  rŸ  c                ó   € \        WW#R 7      # ))r×   rŸ   r¯  r°  )r�  )ÚrqÚmcÚkeyró   Útms   &&&&&r9   r—  r—    s   € Ô2PÐdfØbeõ3~r;   z(dict[str, Callable[..., dict[str, Any]]]Ú_EXPLICIT_RESOLVERSr¯  r°  c               ó4   € V ^8„  d   QhRRRRRRRRRRR	RR
R/# )r5   r�   rW   r×   rŸ   r6   r¯  r{   r°  r¹   rX   rÙ   r7   )r8   s   "r9   r:   r:     sK   € ÷ Kñ K¨3ð KÀCð KÐTbð KØ0=ðKØYfðKà,9ðKàE]ñKr;   c           	     ó”  € \        T;'       g    R 4      P                  4       p\        T;'       g    R 4      P                  4       P                  R4      pV'       g   V'       g   R# \        P	                  V 4      pVe   V! WW4V4      # \
        P                  ! V 4      pV'       d   VP                  R8X  g   R# \        WWW4V4      # )r[   r}   Nr½   )rW   rq   rb   rï  rL   r   Ú	auth_typeré  )r�   r×   rŸ   r¯  r°  r¹   Úresolverr¬   s   $$$$$$  r9   Ú_resolve_explicit_runtimerô    s»   € ô Ð+×1Ð1¨rÓ2×8Ñ8Ó:ÐÜÐ-×3Ð3°Ó4×:Ñ:Ó<×CÑCÀCÓHÐß×$5ÙÜ"×&Ñ& xÓ0€HØÒÙÐ*Ð7GÐ\hÓiÐiÜ×#Ò# HÓ-€Gß˜×)Ñ)¨YÔ6ÙÜ% hÐ9KÐXhð  ~Jó  Kð  Kr;   TrN   c                  ó\   € ] tR tRt$ RtR]R&   R]R&   R]R&   R]R	&   R]R
&   RtR]R&   RtR# )Ú_OAuthRuntimeSpeci/  zDEnv/auth-store OAuth providers resolved by a single credential call.zCallable[[], dict[str, Any]]rÒ  r   r¢   rW   Údefault_sourcerÑ  Úfailure_msgr[   Údefault_base_urlr7   N)Ú__name__Ú
__module__Ú__qualname__Ú__firstlineno__Ú__doc__Ú__annotations__rù  Ú__static_attributes__r7   r;   r9   rö  rö  /  s,   ‡ áNà)Ó)ØƒMØÓØƒOØÓØÐ�c×r;   rö  ÚportalrÙ  z2Auto-detected Nous provider but credentials failedc                 ó   € \        4       # rK   )r   r7   r;   r9   r—  r—  @  s   € Ô.OÔ.Qr;   zhermes-auth-storerÖ  z3Auto-detected Codex provider but credentials failedc                 ó   € \        4       # rK   )r   r7   r;   r9   r—  r—  B  s   € Ô+PÔ+Rr;   z7Auto-detected xAI OAuth provider but credentials failedc                 ó   € \        4       # rK   )r   r7   r;   r9   r—  r—  D  s   € Ô,LÔ,Nr;   zqwen-cliÚexpires_at_mszQwen OAuth credentials failedzdict[str, _OAuthRuntimeSpec]Ú_OAUTH_RUNTIME_PROVIDERSc               ó   € V ^8„  d   QhRR/# ©r5   rX   rÙ   r7   )r8   s   "r9   r:   r:   I  s   € ÷ lñ lÐUmñ lr;   c           	     óü  € \         V ,          pVP                  4       p\        VP                  4      '       d   VP                  \	        W#4      4      MVP                  p\        YVP                  R4      ;'       g    RP                  R4      ;'       g    VP                  VP                  RR4      3RVP                  RVP                  4      /VP                  VP                  VP                  4      /BRV/B # )zµRuntime from an ``_OAUTH_RUNTIME_PROVIDERS`` spec; raises AuthError when the credential is
stale/revoked/benched (``_ladder_rungs`` decides whether an "auto" request falls through).rz   r[   r}   r½   rœ  r×   )r  rÒ  r   r¢   r»   rå   rL   rb   rù  r÷  rÑ  )r�   r×   rŸ   r¹   ÚspecrÓ  r¢   s   &&&&   r9   Ú_resolve_oauth_runtimer  I  sÕ   € ô $ HÕ-€DØ�L‰L‹N€EÜKSÐTX×TaÑTa×KbÒKbˆt�}‰}Ô-¨iÓFÔGÐhl×huÑhu€HÜ�H¨¯©°:Ó)>×)DÐ)DÀ"×(LÑ(LÈSÓ(Q×(jÐ(jÐUY×UjÑUjØ—I‘I˜i¨Ó,ñlØ5:·Y±Y¸xÈ×I\ÑI\Ó5]ðlà—‘¨¯	©	°$·/±/Ó(BÐCñlàXjòlð lr;   c               ó   € V ^8„  d   QhRR/# r  r7   )r8   s   "r9   r:   r:   T  s   € ÷ ;ñ ;Ð<Tñ ;r;   c           
     óì   € \         P                  ! V 4      pV'       d   VP                  R 8X  g   R# \        P                  ! 4       p\        V RVR,          VR,          VP                  RR4      VR7      # )Úoauth_minimaxNrx   rz   r½   rœ  ÚoauthrÍ  )r   rL   rò  rh   Ú)resolve_minimax_oauth_runtime_credentialsrå   )r�   r×   r¬   rÓ  s   &&  r9   Ú_minimax_oauth_runtimer  T  sh   € Ü×#Ò# HÓ-€Gß˜×)Ñ)¨_Ô<ÙÜ×>Ò>Ó@€EÜ�HÐ2°E¸*Õ4EÀuÈYÕGWÐ`e×`iÑ`iÐjrÐt{Ó`|Ø'9ô;ð ;r;   c               ó    € V ^8„  d   QhRRRR/# rç   r7   )r8   s   "r9   r:   r:   `  s   € ÷ @ñ @¨ð @¸3ñ @r;   c                óÄ  € R Fe  p\        V P                  V4      ;'       g    R4      P                  4       pV'       g   K?  \        VR4      P                  4       ;p'       g   Kc  Vu # 	  \        V P                  R4      ;'       g    R4      P                  4       ;'       g=    \        RR4      P                  4       ;'       g    \        RR4      P                  4       # )z™Azure Anthropic key: `key_env` / `api_key_env` hints on the model config, then an inline
api_key (multi-profile setups), then the historical fixed names.r[   r½   ÚAZURE_ANTHROPIC_KEYÚANTHROPIC_API_KEY)Úkey_envÚapi_key_env)rW   rL   rq   r   )rŸ   Úhint_keyÚenv_varrE   s   &   r9   Ú_azure_anthropic_env_keyr  `  s¿   € ó /ˆÜ�i—m‘m HÓ-×3Ð3°Ó4×:Ñ:Ó<ˆß‰7¤°¸Ó!<×!BÑ!BÓ!DÐD˜×DÐDØŠLñ /ô �	—‘˜iÓ(×.Ð.¨BÓ/×5Ñ5Ó7÷ ?ð ?¼>ÐJ_ÐacÓ;d×;jÑ;jÓ;l÷ ?ð ?ÜÐ1°2Ó6×<Ñ<Ó>ð@r;   c               ó(   € V ^8„  d   QhRRRRRRRR/# )r5   r×   rW   rŸ   r6   r¹   r  rX   r7   )r8   s   "r9   r:   r:   k  s4   € ÷ }ñ }¨sð }¸~ð }Ð]gð }ð  tBñ }r;   c           	     óÎ   € \        V4      ;'       g    \        p\        VR4      '       d    \        V4      pV'       g   \	        R4      hM\        VR7      p\        RRW4RV R7      # )z»Native Anthropic (Messages API) from env/auth store; ``model.base_url`` honoured only when
the configured provider is anthropic (else a Codex endpoint would leak into Anthropic requests).ú	azure.comz£No Azure Anthropic API key found. Set AZURE_ANTHROPIC_KEY or ANTHROPIC_API_KEY, or point key_env/api_key_env in your config.yaml model section at a custom env var.r  rÿ   rx   ÚenvrÍ  )r   r¡  r.   r  r   r	  rå   )r×   rŸ   r¹   rz   rE   s   &&&  r9   Ú_anthropic_env_runtimer  k  sn   € ô ' yÓ1×PÐPÔ5P€Hô ˜X {×3Ò3Ü(¨Ó3ˆßÜð ió jð jð ô *°Ô=ˆÜ�KÐ!5°xÈuÐi{Ô|Ð|r;   c               ó   € V ^8„  d   QhRR/# rS  r7   )r8   s   "r9   r:   r:   {  s   € ÷ Eñ EÐaoñ Er;   c           
     óœ  € \        V 4      pV R8X  d–   \        VP                  R4      4      '       gv   \        W04      p\	        \        T;'       g"    VP                  RR4      P                  R4      4      4      '       d(   / VCR\        RVP                  R4      ;'       g    R/Cp\        VP                  R4      4      '       gH   VP                  '       d    RR	P                  VP                  4       R
2MRp\        RV  RV 2V RR7      h\        T \        W04      ;'       g"    VP                  RR4      P                  R4      4      p\        YVP                  RR4      TT;'       g    VP                  RR4      RR7      p	\        W	V4      p\        WP                  RR4      V4      p
\        W	WŠVP                  RR4      VR7      # )uW   Registry ``api_key`` providers (z.ai/GLM, Kimi, MiniMax, copilot, â€¦) from env/config.rÍ   r½   rz   r[   r}   rœ  zlocal-offlinez Set z, r\   z*No usable credentials found for provider 'z'.Úmissing_api_key©r�   Úcoder3   TrÕ   r  rÍ  )r   r!   rL   rì   r"   r$   rb   r   Úapi_key_env_varsr!  r   rã  rÖ   r_  rà  rå   )r�   r¬   r×   rŸ   r¹   rÓ  Úcfg_urlÚhintrz   r¢   r½   s   &&&&&      r9   Ú_api_key_provider_runtimer(  {  sÅ  € ä0°Ó:€Eð �8ÔÔ$5°e·i±iÀ	Ó6J×$KÒ$KÜ/°	ÓDˆÜ#Ô$=¸g×>nÐ>nÈÏÉÐS]Ð_aÓIb×IiÑIiÐjmÓInÓ$o×pÒpØ{�uÐ{˜iÔ)HÈ(ÐTY×T]ÑT]Ð^fÓTg×TzÐTzÐkzÑ{ˆEô ˜UŸY™Y yÓ1×2Ò2ØAH×AY×AYÐAY��t—y‘y ×!9Ñ!9Ó:Ð;¸1Ñ=Ð_aˆÜÐDÀXÀJÈbÐQUÐPVÐWÐbjð  rCô  Dð  	Dä˜8Ô%BÀ9Ó%W÷  &Að  &AÐ[`×[dÑ[dÐeoÐqsÓ[t×[{Ñ[{Ð|ó  \Aó  B€HÜ)¨(¸u¿y¹yÈÐTVÓ?WÐYaØ*6×*VÐ*V¸)¿-¹-È	ÐSUÓ:VÐjnôp€Hä! (°hÓ?€HÜ ¯)©)°I¸rÓ*BÀHÓM€GÜ�H¨À%Ç)Á)ÈHÐV[ÓB\ð  rDô  Eð  Er;   c               ó    € V ^8„  d   QhRRRR/# )r5   r×   rW   rX   ÚNoner7   )r8   s   "r9   r:   r:   ˜  s   € ÷ Mñ M°Cð M¸Dñ Mr;   c                óL  € \        4       p\        V\        4      '       d   VP                  R4      MRp\        V\        4      '       d   VP                  V 4      MRp\        V\        4      '       d2   \        P
                  ! V4      '       g   \        RV : RV  R24      hR# R# )zŸHonour ``providers.<name>.enabled: false`` for built-ins too (the custom lookup gate only
covers custom blocks); a typed error lets the fallback chain advance.Ú	providersNz	provider z" is disabled in config (providers.z.enabled: false))rM   r‰   rn  rL   r=   Úis_provider_enabledÚ
ValueError)r×   Úfull_cfgÚ	provs_cfgÚblocks   &   r9   Ú_raise_if_provider_disabledr2  ˜  s–   € ô ‹}€HÜ-7¸Ä$×-GÒ-G�—‘˜[Ô)ÈT€IÜ1;¸IÄt×1LÒ1LˆI�M‰MÐ,Ô-ÐRV€EÜ�%œ×Ò¤{×'FÒ'FÀu×'MÒ'MÜ˜9Ð%7Ñ$:ð ;'Ø'9Ð&:Ð:JðLó Mð 	Mñ (NÑr;   c               ó$   € V ^8„  d   QhRRRRRR/# )r5   r×   rW   r°  r{   rX   r*  r7   )r8   s   "r9   r:   r:   £  s#   € ÷ ñ ¸sð ÐWdð Ðimñ r;   c                óˆ  € T ;'       g    RP                  4       P                  4       pVR
9   g   V\        9   g   \        V4      '       g   R# \	        T;'       g    R4      P                  4       '       g!   \        RR4      P                  4       '       d   R# \        4       p\        \	        VP                  R4      ;'       g    R4      \        V4      4      '       d   R# \	        \        V 4      ;'       g    / P                  R4      ;'       g    R4      P                  4       '       d   R# \        RV  RV R2V RR	7      h)u�  A local-server alias (``ollama``, ``vllm`` â€” anything ``auth.resolve_provider`` maps to
``custom`` without a rung of its own) with NO endpoint configured anywhere would otherwise walk
the whole ladder to the OpenRouter fallback and spend an unrelated cloud key there (#113703).
Keyed on the ABSENCE of an endpoint, not on the alias name: ``/model <direct-alias>`` resolves
the alias label with the alias endpoint as ``explicit_base_url`` and must keep working, which
is why the name-keyed version was reverted (e9a54c48f2 / a9fabe43c4). Endpoint sources:
explicit call base_url, ``CUSTOM_BASE_URL``, a trusted ``model.base_url``, or a
``providers.<alias>`` block carrying a ``base_url``. ``OPENROUTER_BASE_URL`` is never the
alias endpoint, and an explicit api_key does not lift the guard â€” that key was meant for the
alias's own server. ``llamacpp`` fails fast on its own managed-server rung.r[   NÚCUSTOM_BASE_URLrz   ú
provider 'z~' has no endpoint configured, so the request is not sent anywhere (it would otherwise fall back to OpenRouter). Set providers.z+.base_url or model.base_url in config.yaml.Úmissing_base_urlr#  )r[   rg   )rq   ra   r|  rj   rW   r   rs  rt   rL   r¶   r�  r   )r×   r°  Úrequested_normrŸ   s   &&  r9   Ú&_raise_if_local_alias_missing_endpointr9  £  s  € ð )×.Ð.¨B×5Ñ5Ó7×=Ñ=Ó?€NØ˜.Ô(¨NÔ>OÔ,OÜ& ~×6Ò6ÙÜ
Ð×"Ð" Ó#×)Ñ)×+Ò+¬~Ð>OÐQSÓ/T×/ZÑ/Z×/\Ò/\ÙÜ!Ó#€IÜ3´C¸	¿¹ÀjÓ8Q×8WÐ8WÐUWÓ4XÔZgÐhqÓZr×sÒsÙÜ
Ô&Ð'9Ó:×@Ð@¸b×EÑEÀjÓQ×WÐWÐUWÓX×^Ñ^×`Ò`ÙÜ
Ø
Ð'Ð(ð )GØGUÐFVð W)ð	)ð $Øôð r;   c               ó    € V ^8„  d   QhRRRR/# )r5   r×   rW   rX   r6   r7   )r8   s   "r9   r:   r:   Â  s   € ÷ Mñ M°ð M¸ñ Mr;   c           	     óâ   € ^ RI HpHpHp \        P                  4       '       d	   Y1! 4       rTM	V! 4       w  rEV'       d	   V'       g   \        R4      h\        RRVP                  R4      VRV R7      # )a¶  Vertex AI (OAuth2). The credential *path* (GOOGLE_APPLICATION_CREDENTIALS) must never be
treated as a static API key; a short-lived token is minted per call, and mid-session expiry is
recovered on 401 by run_agent._try_refresh_vertex_client_credentials(). Under
:func:`deferred_token_mint` the credentials are loaded (same failure copy) but the token is a
callable minted on first use, so a process that only routes never exchanges a JWT.)Úget_vertex_base_urlÚget_vertex_configÚvertex_access_tokena“  Vertex AI credentials could not be resolved. Vertex uses OAuth2 (not a static API key): provide a service-account JSON via GOOGLE_APPLICATION_CREDENTIALS (or VERTEX_CREDENTIALS_PATH) in ~/.hermes/.env, or run 'gcloud auth application-default login' for ADC. Set the GCP project/region under vertex: in config.yaml if they aren't embedded in the credentials. Run `hermes setup` to install Vertex support.Úvertexrv   r}   zvertex-oauthrÍ  )	Úagent.vertex_adapterr<  r=  r>  rG   rL   r   rå   rb   )r×   r<  r=  r>  rE   rz   s   &     r9   Ú_resolve_vertex_runtimerA  Â  sv   € ÷ aÑ`Ü×Ñ×ÒØ-Ð/BÓ/D‰xá+Ó-‰ˆßŸÜð @ó Að 	Aô �HÐ0°(·/±/À#Ó2FÈÐVdð  zLô  Mð  Mr;   c               ó   € V ^8„  d   QhRR/# r  r7   )r8   s   "r9   r:   r:   Õ  s   € ÷ ñ ð  lDñ r;   c           	     óš  € V R8X  d   \        RRRRRV R7      # T;'       g    RP                  4       pV R8X  d^   \        VR4      '       dL   \        RR	VP                  R
4      T;'       g    RP                  4       ;'       g    \	        / 4      RV R7      # V R8X  d   \        V \        4       WVR7      # V \        9   d   \        V 4      # R# )zTProviders decided on the REQUESTED name alone, before custom / pool / generic paths.Úmoarv   zmoa://localzmoa-virtual-providerrÍ  r[   rÿ   r  rx   r}   zazure-explicitrŸ  )r×   rŸ   r¯  r°  r¹   N)	rå   rq   r.   rb   r  r�  rs  Ú_VERTEX_NAMESrA  )r×   r¯  r°  r¹   Úeff_bases   &&&& r9   Ú_resolve_requested_shortcutsrG  Õ  sÛ   € à˜UÔ"Ü˜Ð1°=ÐBXÐawØ+=ô?ð 	?ð "×'Ð' R×.Ñ.Ó0€HØ˜[Ô(Ô-BÀ8È[×-YÒ-YÜ˜Ð%9¸8¿?¹?È3Ó;OØ)×/Ð/¨R×6Ñ6Ó8×XÐXÔ<TÐUWÓ<XÐaqØ+=ô?ð 	?ð
 ˜_Ô,Ü-ÐASÔ_pÓ_rØ?OØ;GôIð 	Ið œ]Ô*Ü&Ð'9Ó:Ð:Ùr;   c               ó    € V ^8„  d   QhRRRR/# )r5   r×   rW   rX   rÙ   r7   )r8   s   "r9   r:   r:   ì  s   € ÷ 
Yñ 
Y¨sð 
YÐ\tñ 
Yr;   c                óX  a€ \        4       p\        VP                  R4      ;'       g    R4      P                  4       oS'       dY   \	        V4      R9  gI   \
        ;QJ d#    V3R l\         4       F  '       g   K   RM	  RM! V3R l\         4       4      '       d   R# \        WV4      # )ar  provider "auto"/unset with a config base_url at a custom/local endpoint routes through the
OpenAI-compatible resolver, so resolve_provider() cannot pick up an env ANTHROPIC/OPENAI key
and send the request to a cloud API. Only non-cloud roots take the bypass; match on HOST, not
substring, so a look-alike (api.anthropic.com.attacker.test) cannot leak a cloud credential.rz   r[   c              3  ó<   <"  € T F  p\        SV4      x € K  	  R # 5irK   )r.   )rñ   rV   rl   s   & €r9   rô   Ú)_local_endpoint_bypass.<locals>.<genexpr>ô  s   øé € ÐcÑIbÀÔ(¨°t×<Ð<ÓIbùs   ƒTFN)rp   r[   )rs  rW   rL   rq   r¶   rö   Ú_LOCAL_BYPASS_CLOUD_HOSTSÚ_openrouter_fallback)r×   r¯  r°  rŸ   rl   s   &&& @r9   Ú_local_endpoint_bypassrN  ì  su   ø€ ô
 "Ó#€IÜ�y—}‘} ZÓ0×6Ð6°BÓ7×=Ñ=Ó?€LßœM¨)Ó4¸LÔHß‹sÔcÕIbÓc�s�sŠsÔcÕIbÓc×cÒcÙÜÐ 2ÐFWÓXÐXr;   c               ó$   € V ^8„  d   QhRRRRRR/# )r5   ÚruntimerÙ   r×   rW   rX   r7   )r8   s   "r9   r:   r:   ù  s#   € ÷ ñ Ð*ð Àð ÐH`ñ r;   c                ó   € V '       d   WR&   V # )zWStamp ``requested_provider`` on a runtime built by a collaborator that does not set it.r×   r7   )rP  r×   s   &&r9   Ú_tagrR  ù  s   € çØ(:Ð$Ñ%Ø€Nr;   c               ó   € V ^8„  d   QhRR/# r  r7   )r8   s   "r9   r:   r:      s   € ÷ 	ñ 	Ðayñ 	r;   c           	     óÖ   € \        \        WW#R7      V 4      pV'       dJ   VP                  R4      R8X  d4   \        RVP                  R4      ;'       g    R\	        4       V R7      VR&   V# )zÀRung 3: a configured named custom provider. Honours the ``model.openai_runtime`` opt-in like the
pool path does for openai/openai-codex (codex resolves the provider from its own config by id).)r×   r¯  r°  r¹   r�   rg   r¢   rv   rà   )rR  r‡  rL   rá   rs  )r×   r¯  r°  r¹   rP  s   &&&& r9   Ú_named_custom_rungrU     sn   € ô Ô0ÐDVØBSôpð rDóE€Gç�7—;‘;˜zÓ*¨hÔ6ÜCØ¨¯©°JÓ(?×(UÐ(UÐCUÔarÓatØ1ô3ˆ�
Ñð €Nr;   c               ó   € V ^8„  d   QhRR/# rS  r7   )r8   s   "r9   r:   r:     s   € ÷ fñ fÐUcñ fr;   c                ó0   € \        \        WVR 7      V 4      # )©r×   r¯  r°  )rR  r“  rX  s   &&&r9   rM  rM    s#   € ÜÔ+Ð?QØ>OôQØRdófð fr;   ru  c          
     ó,   € V ^8„  d   QhRRRRRRRRRR/# )r5   ru  r{   r¯  r°  r¹   rX   r6   r7   )r8   s   "r9   r:   r:     s3   € ÷ 'ñ '¨=ð 'ÐS`ð 'Ø0=ð'ØTað'Øm{ñ'r;   c           	     ó¾  € \        V 4      p\        V4       Tp\        WB4      w  rB\        WB4       \	        R \        WAW#4       4       4      p\        WF4       \        VP                  RR4      VP                  RR4      \        4       VR7      pWvP                  R4      8w  d6   \        P                  RVP                  R4      VP                  R4      4       WvR&   V# )uÎ  Resolve runtime provider credentials for agent execution. Ladder (order is behavior â€” each
rung returns or raises, else falls to the next):
  1. disabled-provider guard (``providers.<name>.enabled: false``)
  2. requested-name shortcuts: moa, anthropic@azure, azure-foundry, vertex
  3. named custom provider / llamacpp alias / bare-custom direct alias
  4. local-endpoint bypass (no explicit creds, config base_url at a non-cloud host)
  5. ``auth.resolve_provider`` â†’ explicit --api-key/--base-url path
  6. credential pool (OpenRouter pool only without custom endpoint/override)
  7. OAuth specs (nous/codex/xai/qwen; "auto" swallows AuthError, logs, and stamps it on a
     keyless fallback as ``auth_error``) â†’ minimax-oauth
     â†’ external-process â†’ anthropic env â†’ bedrock â†’ registry api_key providers
  8. OpenRouter / bare-custom fallback
  9. ``model.openai_runtime`` overlay (openai/openai-codex, named custom providers): rewrites the picked rung's
     api_mode to ``codex_app_server``; the rung's credential/endpoint is then not used
target_model overrides model_cfg["default"] when computing provider-specific api_mode (e.g.
OpenCode Zen/Go where different models route through different API surfaces).c              3  ó8   "  € T F  q'       g   K  Vx € K  	  R # 5irK   r7   )rñ   Úrs   & r9   rô   Ú+resolve_runtime_provider.<locals>.<genexpr>,  s   é € ÐxÑr˜Óvw—1’1Órùs   ‚	�
r�   r[   r¢   rà   u£   model.openai_runtime=codex_app_server overrides the %s runtime (source=%s); its credential/endpoint is not used â€” the app-server authenticates with its own loginrœ  )r{  r2  rŠ  r9  ÚnextÚ_ladder_rungsÚ%_raise_for_credentialless_bare_customrá   rL   rs  r£   r¤   )ru  r¯  r°  r¹   r×   Úrequested_aliasrP  r¢   s   $$$$    r9   Úresolve_runtime_providerrb    sà   € ô$ 4°IÓ>ÐÜÐ 2Ô3ð
 )€OÜ,CÐDVÓ,jÑ)ÐÜ*Ð+=ÔQÜÑxœmÐ,>ÐRcÔrÓxÓx€GÜ)Ð*<ÔFô 5Ø—‘˜Z¨Ó,°w·{±{À:ÈrÓ7RÔ^oÓ^qØ*ô,€Hð —;‘;˜zÓ*Ô*Ü�‰ð VØW^×WbÑWbÐcmÓWnÐpw×p{Ñp{ð  }Eó  qFô	Gà"ˆJÑØ€Nr;   c               ó$   € V ^8„  d   QhRRRRRR/# )r5   r×   rW   rP  r6   rX   r*  r7   )r8   s   "r9   r:   r:   ;  s"   € ÷ ñ ¸cð ÈNð Ð_cñ r;   c                ó’   € V R8w  g.   VP                  R4      R8w  g   VP                  R4      '       d   R# \        RV  R2V RR7      h)	aé  Reject a bare ``custom`` placeholder request that fell through the whole ladder to the
OpenRouter default endpoint with no credential. Every other custom rung (named entry, local
bypass, pool, ``key_cmd``) yields a key, a callable or the ``no-key-required`` placeholder, so
an EMPTY key on a ``custom`` runtime is exactly the dead shape that otherwise dies at agent
construction as ``No LLM provider configured``. Keyed on the literal request, not the resolved
shape: local aliases (``ollama``, ``vllm``) are resolved tolerantly by ``/model`` direct-alias
switching, which supplies the alias endpoint AFTER this call and must not fail here. Typed
``AuthError`` so every caller's fallback chain (CLI, gateway, TUI, cron) still advances (#17929).
rg   r�   r½   Nr6  zš' resolved without credentials (no endpoint or API key configured). If this is a named custom provider, use its real name (see providers: in config.yaml).r"  r#  )rL   r   )r×   rP  s   &&r9   r`  r`  ;  sY   € ð ˜XÔ%¨¯©°ZÓ)@ÀHÔ)LÐPW×P[ÑP[Ð\e×PfÒPfÙÜ
Ø
Ð'Ð(ð )að 	aà#Øô	ð r;   c           	   #  óV  "  € \        WW#4      x € \        WW#4      x € V'       g   V'       g   \        WV4      x € \        WVR7      p\	        4       p\        W@VWVR7      x € \        W@WQW#4      x € RpV\        9   d    \        W@WS4      x € VR8X  d   \        W@4      x € \        V4      '       d   \        W@4      x € VR8X  d   \!        WV4      x € VR8X  d   \#        WV4      x € \$        P&                  ! V4      pV'       d!   VP(                  R	8X  d   \+        WHWV4      x € \-        WV4      p	Ve   V	P'                  R	4      '       g   WiR
&   V	x € R#   \         dA   pT R8w  d   h \        P                  R\        T,          P                  4       Tp Rp?ELRp?ii ; i5i)z­Ladder rungs 2-8, yielded lazily so each is evaluated only when the previous one returned
nothing; the last rung (OpenRouter / bare-custom fallback) always yields a runtime.)r¯  r°  )r�   r×   rŸ   r¯  r°  r¹   Nrp   z%%s; falling through to next provider.r•  rÿ   Úbedrockr½   Ú
auth_error)rG  rU  rN  r   rs  rô  rÊ  r  r  r   r£   r¤   rø  r  r�  r’  r  r‘  r   rL   rò  r(  rM  )
r×   r¯  r°  r¹   r�   rŸ   Úswallowed_auth_errorrj  r¬   Úfallbacks
   &&&&      r9   r_  r_  O  s”  é € ô 'Ð'9ÐM^Ó
mÒmÜ
Ð/ÐCTÓ
cÒc÷
 ×%5Ü$Ð%7ÐK\Ó]Ò]ÜÐ 2ÐizÔ{€HÜ!Ó#€IÜ
#¨XÐhqØ5EØ1=ô?ò ?ô ˜X¸9ÐXiÓ
xÒxØÐØÔ+Ô+ð	'Ü(¨ÀyÓ_Ò_ð �?Ô"Ü$ XÓBÒBÜ$ X×.Ò.Ü/°ÓMÒMØ�;ÔÜ$Ð%7ÀLÓQÒQØ�9ÔÜ&Ð'9ÀlÓSÒSÜ×#Ò# HÓ-€Gß�7×$Ñ$¨	Ô1Ü'¨Ð;MÐZfÓgÒgÜ#Ð$6ÐJ[Ó\€HØÒ'°·±¸Y×0GÒ0GØ!5�ÑØ
„Nøô+ ô 	'ð " VÔ+ØÜ�K‰KÐ?ÔAYÐZbÕAc×AoÑAoÔpØ#&Ö ûð	'üsC   ‚,F)¯AF)ÂE ÂA9F)Ä
AF)Å
F)ÅF&Å&5F!ÆF)Æ!F&Æ&F)c               ó    € V ^8„  d   QhRRRR/# )r5   Úerrorri   rX   rW   r7   )r8   s   "r9   r:   r:   |  s   € ÷ Tñ T¨ð T°sñ Tr;   c                óZ   € \        V \        4      '       d   \        V 4      # \        V 4      # rK   )r‰   r   r   rW   )rk  s   &r9   Úformat_runtime_provider_errorrm  |  s#   € Ü'1°%¼×'CÒ'CÔ˜UÓ#ÐSÌÈUËÐSr;   c               ó0   € V ^8„  d   QhRRRRRRRRRRRR	/# )
r5   r&   rÙ   ru  r{   r¹   r°  r¯  rX   z/tuple[dict[str, Any], Optional[dict[str, Any]]]r7   )r8   s   "r9   r:   r:   €  s?   € ÷ .ñ .Ð*Bð .ÐR_ð .Ø0=ð.ØYfð.à4Að.ð (Wñ.r;   c          	     ó&  € ^ RI HpHp  \        WW4R7      R3#   T Edp   p^ RIHpHp	Hp
 T	! T 4       EFQ  pTP                  R4      ;'       g    RP                  4       P                  4       pTP                  R4      ;'       g    RP                  4       pT'       d	   T'       g   Kv  RTR	T/pTP                  R
4      '       d   TR
,          TR&   T
! T4      ;p'       d   YþR&    \        R/ TB pMX  T d#   p\        P                  RYÍT4        Rp?Kä  Rp?i\         d$   p\        P                  RYÍT4        Rp?EK  Rp?ii ; iT! TT4      TR&   \        P                  RT! T4      ^ ,          Y|T4       TT3u u Rp?# 	  ThRp?ii ; i)uñ  ``resolve_runtime_provider`` plus resolution-time fallback: ``(runtime, fallback_entry_or_None)``.

Only an ``AuthError`` from the primary (missing/expired credentials, exhausted quota, cooled-down pool)
walks ``get_fallback_chain(config)`` in order and returns the first entry that resolves â€” the single
resolution-time walker shared by the gateway and oneshot. ``ValueError``/other errors are genuine
misconfiguration (unknown ``--provider`` ...) and propagate unchanged, so a typo is never silently
rerouted onto a provider the operator did not ask for. When every entry fails, the *primary* error is
re-raised: a fallback entry's failure is not what the operator configured first (#81209). The entry's
``model`` is the model the caller must send.
)r   Úprimary_failure_wording)ru  r¹   r°  r¯  N)Úeffective_runtime_providerÚget_fallback_chainÚresolve_entry_api_keyr�   r[   r�   ru  r¹   rz   r°  r¯  zFallback entry %s/%s failed: %sz9Fallback entry %s/%s is misconfigured and was skipped: %sz/Primary provider %s (%s). Falling back to %s/%sr7   )Úhermes_cli.authr   rp  rb  Úhermes_cli.fallback_configrq  rr  rs  rL   rq   ra   r£   rh  ri   Úwarning)r&   ru  r¹   r°  r¯  r   rp  Úprimary_excrq  rr  rs  r7  r�   r�   ÚkwargsÚ	entry_keyrP  Úfb_excs   &$$$$             r9   Úresolve_runtime_with_fallbackr{  €  sƒ  € ÷ CðÜ'°)Ø:KôpØquðvð 	vøàõ ßtÑtÙ'¨×/ˆEØŸ	™	 *Ó-×3Ð3°×:Ñ:Ó<×BÑBÓDˆHØ—Y‘Y˜wÓ'×-Ð-¨2×4Ñ4Ó6ˆEß§5ÙØ&1°8¸^ÈUÐ%SˆFØ�y‰y˜×$Ò$Ø.3°JÕ.?�Ð*Ñ+Ù1°%Ó8Ð8ˆyÖ8Ø-6Ð)Ñ*ðÜ2Ñ<°VÑ<‘øØô Ü—‘Ð>ÀÐQWÔXÝûÜô ä—‘ÐZÐ\dÐmsÔtÞûðúñ
 #=¸UÀGÓ"LˆG�JÑô �N‰NÐLÙ2°;Ó?ÀÕBÀKÐ[`ôbà˜E�>×!ñ3 0ð4 Ðûð9ús†   Š ™F¡-FÁ6FÂFÂFÂ'FÃFÃ"FÃ'C3Ã2FÃ3EÃ:DÄFÄEÄ$EÄ%EÄ<FÅEÅ9FÆFÆFÆFrK   >   ru   Úbedrock_converserv   rÜ   rx   )r[   )ru   r[   )r?  zgoogle-vertexz	vertex-aiz
gcp-vertexÚvertexai)ro   zanthropic.comr,  )¶Ú__conditional_annotations__rþ  Ú
__future__r   r?   Úloggingr¢  Ú
contextlibr   Úcontextvarsr   Údataclassesr   Útypingr   r   r   r	   Ú	getLoggerrú  r£   Ú
hermes_clir
   rh   rÁ  r   r   r   r   r   Úagent.secret_scoper   rt  r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r    r!   r"   r#   r$   r&   r=   r'   rÀ   Úhermes_constantsr(   Úhermes_cli.providersr)   r*   r+   r,   r-   Úutilsr.   r/   r0   r1   r2   rÿ  rF   rG   rI   rM   rQ   rS   rc   rj   rt   r~   rŒ   r„   r�   r•   r’   r§   r®   r³   r·   r»   rÄ   rÉ   rÐ   rÖ   rá   r¡  r  rå   r¶   rì   rø   rü   r   r	  r'  r4  r>  rB  rK  rQ  rY  r_  rk  rs  r{  Ú"hermes_cli.runtime_provider_customr|  r}  r~  r  r€  r�  r‚  rƒ  r„  r…  r†  r‡  rˆ  r‰  rß   rŠ  r‹  rŒ  r�  rŽ  Ú$hermes_cli.runtime_provider_backendsr�  r�  r‘  r’  r“  r˜  r§  r¬  r´  rº  rÄ  rÊ  rÎ  rÔ  r×  rÝ  rà  rã  ré  rï  rô  rö  r  r  r  r  r  r(  rE  rL  r2  r9  rA  rG  rN  rR  rU  rM  rb  r`  r_  rm  r{  )r~  s   @r9   Ú<module>r�     s†  øðôQõ #ã Û Û 	Ý %Ý "Ý !ß 0Ó 0à	×	Ò	˜8Ó	$€å '÷õ õ .÷÷ ÷ ÷ ÷ ó õ -Ý (Ý 0ß zÕ zß RÓ Rñ @JÐJbÐlpÔ?qÐ Ð<Ó qð ô,ó ð,ñ '1Ð1DÈeÔ&TÐ Ð#Ó Tð ñ'ó ð'òVô
?ò6õ\õõ|ð2 Ð! =Ð2CÐEUÐWiØÐ'Ð)<Ð>RðÐ ò yÐ õõ>	j÷õ*Uõ(
BõH÷uõEõ:ð"Ðhl÷ "õ2õpõAðØDF÷ð" :Ð ð"OÐ õkõ@õHõlõ_õQð
°T÷ 
õFõ":õ Yõ^õõEõxõ
õ õ"÷8/÷"÷ ÷ ÷ ÷ ó ÷õ ð Ð&Ð(>Ð?ÀÐO`Ðb|ÐN}ØÐ%Ð'<Ð=¸|ÐN`ÐbuÐMvØÐ*Ñ,}Ð~Ø	Ð"ð	.Ð Ð*ó õ,~ð^QØKOðQØrvðQàCG÷QõHõõ*õ*ò<DòCò;òRõGõ
UòAð4 Ð$ n°oÀvÈ~Øñ ~ðAÐ Ð=ó ðKØ@DðKØimðKà<@÷Kñ& �$Ô÷ð ó ðð ÑÐ1°=À(ÈLØRóTàÑ%Ñ&QÐSdÐfyØ&4Ð6kómàÑ"Ñ#RÐTeÐgzØ#1Ð3lð  oIóJàÑ#Ñ$NÐPbÐdnØ$3Ð5TóVð	:Ð Ð6ó 	õlõ;õ@÷}õ Eð2 S€ØLÐ õMõõ>Mõ&õ.
Yõõ	õfð
'¸4ð 'Ðcgð 'Ø@Dð'Ødh÷'õTò(*õZTð.Ðbfð .Ø@Dð.Øimð.àDH÷.ñ .r;   