+
    „WÝjø  ã                  óº   € R t ^ RIHt ^ RIt^ RIHt ]P                  ! ]4      tR R lt	R R lt
R R	 ltR
 R ltR R ltR R ltR R ltR R ltR R ltR# )zFHelpers for reading the effective fallback provider chain from config.)ÚannotationsN)ÚAnyc               ó    € V ^8„  d   QhRRRR/# )é   Úvaluer   ÚreturnÚstr© )Úformats   "ÚNC:\Users\johnn\AppData\Local\hermes\hermes-agent\hermes_cli\fallback_config.pyÚ__annotate__r      s   € ÷ Gñ G ð G¨ñ Gó    c                óp   € \        V \        4      '       d    V P                  4       P                  R 4      # R# )Ú/Ú )Ú
isinstancer   ÚstripÚrstrip)r   s   &r   Ú_normalized_base_urlr      s*   € Ü(2°5¼#×(>Ò(>ˆ5�;‰;‹=×Ñ Ó$ÐFÀBÐFr   c               ó    € V ^8„  d   QhRRRR/# )r   r   r   r   r	   )r
   s   "r   r   r      s   € ÷ %ñ % #ð %¨#ñ %r   c                ó�   €  ^ RI Hp T! T 4      #   \         d+    \        P	                  RRR7       T P                  4       u # i ; i)al  Collapse provider aliases to the canonical id (lazy to avoid import cycles).

``opencode-zen`` is the legacy pre-rename id of ``opencode``; ``zen`` is a
short alias. Without normalization, two fallback entries naming the same
backend under different ids are kept as separate slots, shifting the chain
and letting an alias slip past the same-backend skip (#85235).
)Únormalize_providerzpfallback provider alias collapse degraded to lowercase: could not import hermes_cli.providers.normalize_providerT)Úexc_info)Úhermes_cli.providersr   Ú	ExceptionÚloggerÚwarningÚlower)r   r   s   & r   Ú_normalize_provider_idr      sR   € ðÝ;ñ ˜eÓ$Ð$øô ô 	ô 	�‰ðGàð 	ô 	
ð
 �{‰{‹}Òð	ús   ‚ �2AÁAc               ó    € V ^8„  d   QhRRRR/# )r   Úentryúdict[str, Any] | Noner   z
str | Noner	   )r
   s   "r   r   r   &   s   € ÷ ñ Ð!6ð ¸:ñ r   c                ó´  € \        V \        4      '       g   R# \        V P                  R4      ;'       g    R4      P	                  4       ;p'       d   V# \        V P                  R4      ;'       g    V P                  R4      ;'       g    R4      P	                  4       ;p'       d1   ^ RIHp V! V4      ;'       g    RP	                  4       ;'       g    R# R# )aÑ  API key for one fallback entry: inline ``api_key``, else ``key_env``.

Mirrors the custom-provider convention (``api_key_env`` accepted as alias); None when neither
yields a value so ``resolve_runtime_provider`` falls through to standard credential resolution.
``key_env`` goes through ``agent.secret_scope.get_secret``, not raw ``os.getenv``: in a
multiplexed gateway a bare env read ignores the active profile's scope and can return another
profile's credential.
NÚapi_keyr   Úkey_envÚapi_key_env)Ú
get_secret)r   Údictr   Úgetr   Úagent.secret_scoper&   )r    Úinliner$   r&   s   &   r   Úresolve_entry_api_keyr+   &   s¨   € ô �eœT×"Ò"ÙÜ�U—Y‘Y˜yÓ)×/Ð/¨RÓ0×6Ñ6Ó8Ð8€vÖ8ØˆÜ�e—i‘i 	Ó*×LÐL¨e¯i©i¸Ó.F×LÐLÈ"ÓM×SÑSÓUÐU€wÖUÝ1Ù˜7Ó#×)Ð) r×0Ñ0Ó2×:Ð:°dÐ:Ùr   c               ó$   € V ^8„  d   QhRRRRRR/# )r   r    r!   Úruntimer   r   r	   )r
   s   "r   r   r   9   s$   € ÷ ñ Ø ðØ+@ðàñr   c                ó˜  € T;'       g    / p\        VP                  R4      ;'       g    R4      P                  4       pVP                  4       R8w  d   V# \        VP                  R4      ;'       g&    T ;'       g    / P                  R4      ;'       g    R4      P                  4       pV'       d   VP                  4       R8w  d   V# V# )u  Provider identity to persist/display for a resolved fallback entry.

``resolve_runtime_provider`` returns the bare billing class ``"custom"``
for every named ``providers:`` / ``custom_providers:`` entry; the entry's
configured id only survives in ``requested_provider``. Fallback resolvers
that persist ``runtime["provider"]`` as the agent identity therefore label
sessions/billing rows ``custom`` instead of the configured provider name â€”
while the manual ``/model`` switch path correctly persists the named id
(#98739). Same class as the delegation fix in ``tools/delegate_tool.py``.

Returns the entry's requested identity when the resolved provider is the
bare ``custom`` class; a genuinely ad-hoc endpoint (requested provider IS
``custom``) keeps the bare class unchanged.
Úproviderr   ÚcustomÚrequested_provider)r   r(   r   r   )r    r-   ÚresolvedÚ	requesteds   &&  r   Úeffective_runtime_providerr4   9   s³   € ð" �mˆm˜€GÜ�7—;‘;˜zÓ*×0Ð0¨bÓ1×7Ñ7Ó9€HØ‡~�~Ó˜8Ô#ØˆÜØ�‰Ð(Ó)÷ 	ð 	Ø�KˆK�R×Ñ˜ZÓ(÷	ð 	àó÷ �eƒgð	 ÷
 �Y—_‘_Ó&¨(Ô2ØÐØ€Or   c          
     ó,   € V ^8„  d   QhRRRRRRRRRR/# )r   Úprimary_providerr   Úprimary_modelÚfallback_providerÚfallback_modelr   r   r	   )r
   s   "r   r   r   X   s;   € ÷ mñ mØðmØ*-ðmØBEðmØWZðmàñmr   c                ó    € RP                  R W3 4       4      ;'       g    RpRP                  R W#3 4       4      ;'       g    RpRV RV R2# )	zøUser-visible one-shot line for a provider switch made during credential resolution, before
any AIAgent exists (#74349). Shared by the messaging gateway, the TUI/Desktop gateway and cron
so the three pre-agent fallback paths cannot drift in wording.r   c              3  óf   "  € T F'  q'       g   K  \        V4      P                  4       x € K)  	  R # 5i©N©r   r   ©Ú.0Úps   & r   Ú	<genexpr>Ú,pre_agent_fallback_notice.<locals>.<genexpr>^   s#   é € Ð[Ñ4U¨qÓYZœNœC ›FŸL™LŸN˜NÓ4Uùó   ‚	1�!1Úprimaryc              3  óf   "  € T F'  q'       g   K  \        V4      P                  4       x € K)  	  R # 5ir<   r=   r>   s   & r   rA   rB   _   s#   é € Ð^Ñ5X°Ó\]œ^œS ›VŸ\™\Ÿ^˜^Ó5XùrC   Úfallbacku   âš ï¸� Provider fallback: z unavailable; using z for this response.)Újoin)r6   r7   r8   r9   Úprimary_descÚfallback_descs   &&&&  r   Úpre_agent_fallback_noticerJ   X   s]   € ð —8‘8Ñ[Ð5EÑ4UÓ[Ó[×hÐhÐ_h€LØ—H‘HÑ^Ð6GÑ5XÓ^Ó^×lÐlÐbl€MØ'¨ ~Ð5IÈ-ÈÐXkÐlÐlr   c               ó    € V ^8„  d   QhRRRR/# )r   Úrawr   r   úlist[dict[str, Any]]r	   )r
   s   "r   r   r   d   s   € ÷ ñ  ð Ð(<ñ r   c                ó   € \        V \        4      '       d   V .M\        V \        4      '       d   T M. p. pV FÒ  p\        V\        4      '       g   K  \        VP	                  R 4      ;'       g    R4      P                  4       p\        VP	                  R4      ;'       g    R4      P                  4       pV'       d	   V'       g   K‘  / VCR VRV/Cp\        VP	                  R4      4      pV'       d   WvR&   VP                  V4       KÔ  	  V# ©r/   r   ÚmodelÚbase_url)r   r'   Úlistr   r(   r   r   Úappend)rL   Ú
candidatesÚentriesr    r/   rP   Ú
normalizedrQ   s   &       r   Ú_iter_fallback_entriesrW   d   sÛ   € Ü$ S¬$×/Ò/�#‘¼JÀsÌD×<QÒ<Q±SÐWY€JØ$&€GÛˆÜ˜%¤×&Ò&ÙÜ�u—y‘y Ó,×2Ð2°Ó3×9Ñ9Ó;ˆÜ�E—I‘I˜gÓ&×,Ð,¨"Ó-×3Ñ3Ó5ˆßŸuÙØD˜ÐD˜z¨8°W¸eÑDˆ
Ü'¨¯	©	°*Ó(=Ó>ˆßØ%-�zÑ"Ø�‰�zÖ"ñ ð €Nr   c               ó    € V ^8„  d   QhRRRR/# )r   r    zdict[str, Any]r   ztuple[str, str, str]r	   )r
   s   "r   r   r   v   s   € ÷ ñ ˜>ð Ð.Bñ r   c                óF  € \        \        V P                  R 4      ;'       g    R4      P                  4       4      \        V P                  R4      ;'       g    R4      P                  4       P	                  4       \        V P                  R4      4      P	                  4       3# rO   )r   r   r(   r   r   r   )r    s   &r   Ú_entry_identityrZ   v   sx   € äœs 5§9¡9¨ZÓ#8×#>Ð#>¸BÓ?×EÑEÓGÓHÜˆE�I‰I�gÓ×$Ð$ "Ó%×+Ñ+Ó-×3Ñ3Ó5Ü˜UŸY™Y zÓ2Ó3×9Ñ9Ó;ðð r   c               ó    € V ^8„  d   QhRRRR/# )r   Úconfigr!   r   rM   r	   )r
   s   "r   r   r   ~   s   € ÷ ñ Ð4ð Ð9Mñ r   c                óô   € T ;'       g    / p . p\        4       pR FY  p\        V P                  V4      4       F8  p\        V4      pWR9  g   K  VP	                  V4       VP                  V4       K:  	  K[  	  V# )aZ  Return the effective fallback chain merged across old and new config keys.

``fallback_providers`` remains the primary source of truth and keeps its order. Legacy
``fallback_model`` entries are appended afterwards unless they target the same
provider/model/base_url route as an earlier entry. The returned list always contains fresh dict
copies.
)Úfallback_providersr9   )ÚsetrW   r(   rZ   ÚaddrS   )r\   ÚchainÚseenÚkeyr    Úidentitys   &     r   Úget_fallback_chainre   ~   sk   € ð �\ˆ\�r€FØ"$€EÜ&)£e€DÛ7ˆÜ+¨F¯J©J°s«OÖ<ˆEÜ& uÓ-ˆHØÖ#Ø—‘˜Ô"Ø—‘˜UÖ#ó	 =ñ 8ð €Lr   c          
     ó,   € V ^8„  d   QhRRRRRRRRR	R/# )
r   Ú	inheritedzlist[dict[str, Any]] | NoneÚdeclaredr   ÚpinnedÚboolÚownerr   r   r	   )r
   s   "r   r   r   ’   s4   € ÷ !ñ !Ø*ð!Ø69ð!ØFJð!ØSVð!à ñ!r   c               óÎ   € V'       d   RMT ;'       g    RpVf   V# V. 8X  d   R# \        RV/4      pV'       g!   \        P                  RY2'       d   RMR4       T;'       g    T# )a‡  Fallback chain for a route owner that can pin its own primary (delegated child, cron job).

A pinned owner (explicit provider, endpoint or model) never borrows the *inherited* chain: the
operator chose that route, and a chain entry is a different provider and usually a different
model. Predictability beats liveness for an explicit pin. An unpinned owner inherits the chain
when *declared* is absent/None. An explicit ``[]`` disables fallback either way; any other
*declared* value is the owner's own chain, normalized by :func:`get_fallback_chain` (malformed
entries are dropped; nothing usable left falls back to the pinned/inherited default).
Nr^   z@%s fallback_providers has no usable routes; using the %s defaultri   rg   )re   r   r   )rg   rh   ri   rk   ÚdefaultrV   s   &&$$  r   Úscoped_fallback_chainrn   ’   sd   € ÷ ‰d 9×#4Ð#4°€GØÒØˆØ�2„~ÙÜ#Ð%9¸8Ð$DÓE€JßÜ�‰ÐYØ®&™h°kô	Cà× Ð ˜Ð r   )Ú__doc__Ú
__future__r   ÚloggingÚtypingr   Ú	getLoggerÚ__name__r   r   r   r+   r4   rJ   rW   rZ   re   rn   r	   r   r   Ú<module>ru      sP   ðÙ Lå "ã Ý à	×	Ò	˜8Ó	$€õGõ%õ.õ&õ>mõõ$õ÷(!r   