+
    „WÝj‰&  ã                  óŽ   € R t ^ RIHt ^ RIHtHtHt . ROtR R ltR R lt	R R lt
R	 R
 ltRR/R R lltR R ltR R ltR# )aô  Unified provider-credential lifecycle across every store Hermes reads.

Deleting a key from ``.env`` alone leaves the stale ``credential_pool`` entry (and the
``provider_models_cache.json`` row) behind, so the provider keeps appearing in the model picker
even across restarts (the pool loader is additive-only). Every surface that saves or removes a
provider credential should route through :func:`save_provider_env_credential` /
:func:`remove_provider_env_credential` so all stores stay consistent.
)Úannotations)ÚAnyÚDictÚListc               ó    € V ^8„  d   QhRRRR/# ©é   Úenv_varÚstrÚreturnú	list[str]© )Úformats   "ÚSC:\Users\johnn\AppData\Local\hermes\hermes-agent\hermes_cli\credential_lifecycle.pyÚ__annotate__r      s   € ÷ ñ  Cð ¨Iñ ó    c                óð   €  ^ RI Hp . pTP                  4        F3  w  r4 YP                  ;'       g    R9   d   TP                  T4       K3  K5  	  T#   \         d    . u # i ; i  \         d     KZ  i ; i)zCProvider ids whose registered api_key_env_vars include ``env_var``.)ÚPROVIDER_REGISTRYr   )Úhermes_cli.authr   Ú	ExceptionÚitemsÚapi_key_env_varsÚappend)r	   r   ÚhitsÚpidÚcfgs   &    r   Ú_providers_for_env_varr      s€   € ðÝ5ð €DØ%×+Ñ+Ö-‰ˆð	Ø×/Ñ/×5Ð5°2Ô6Ø—‘˜CÖ ñ 7ñ .ð €Køô ô ØŠ	ðûô ô 	Úð	ús"   ‚A  +A&ÁA#Á"A#Á&A5Á4A5c               ó(   € V ^8„  d   QhRRRRRRRR/# )	r   Ú	providersr   Úimport_pathr
   Úargsr   r   ÚNoner   )r   s   "r   r   r   %   s(   € ÷ 
ñ 
 )ð 
¸#ð 
Àcð 
Èdñ 
r   c                ó¸   €  ^ RI pVP                  R^4      w  rE\        VP                  V4      V4      pV  F  pV! V.VO5!   K  	  R#   \         d     R# i ; i)zXBest-effort ``module.fn(provider, *args)`` for every provider; failures never propagate.NÚ.)Ú	importlibÚrsplitÚgetattrÚimport_moduler   )r   r   r    r$   Úmodule_nameÚfn_nameÚfnÚproviders   &&*     r   Ú_for_each_providerr,   %   s_   € ðÛà*×1Ñ1°#°qÓ9ÑˆÜ�Y×,Ñ,¨[Ó9¸7ÓCˆÛ!ˆHÙˆxÐ˜$Öó "øäô Úðús   ‚AA
 Á
AÁAc               ó    € V ^8„  d   QhRRRR/# r   r   )r   s   "r   r   r   2   s   € ÷ ñ  Sð ¨Yñ r   c           
     ó”  € ^ RI HpHpHp RV  2p. pV! 4       ;_uu_ 4        V! 4       pVP	                  R4      p\        V\        4      '       g   VuuRRR4       # \        VP                  4       4       Fž  pWx,          p	\        V	\        4      '       g   K#  V	 U
u. uF3  p
\        V
\        4      '       d   V
P	                  R4      V8X  d   K1  V
NK5  	  pp
\        V4      \        V	4      8X  d   K}  VP                  V4       V'       d   W·V&   Kœ  Wx K   	  V'       d	   V! V4       RRR4       V# u up
i   + '       g   i     T# ; i)zýDrop ``credential_pool`` entries seeded from ``env:<env_var>``; return providers pruned.

Spans ALL providers (shared vars like GITHUB_TOKEN seed several). Entries with any other
source (OAuth, device-code, manual, borrowed-CLI) are preserved verbatim.
)Ú_auth_store_lockÚ_load_auth_storeÚ_save_auth_storeúenv:Úcredential_poolNÚsource)r   r/   r0   r1   ÚgetÚ
isinstanceÚdictÚlistÚkeysÚlenr   )r	   r/   r0   r1   r4   ÚprunedÚ
auth_storeÚpoolr+   ÚentriesÚeÚkepts   &           r   Ú_prune_env_pool_entriesrA   2   s  € ÷ UÑTà�G�9Ð€FØ€FÙ	×	Õ	Ù%Ó'ˆ
Ø�~‰~Ð/Ó0ˆÜ˜$¤×%Ò%Ø÷	 
Ò	ô
 ˜TŸY™Y›[Ö)ˆHØ•nˆGÜ˜g¤t×,Ò,ÙÙ&Ób™w˜!¬z¸!¼T×/BÒ/BÀqÇuÁuÈXÃÐZ`ÑG`—A�A™wˆDÐbÜ�4‹yœC ›LÔ(ÙØ�M‰M˜(Ô#ßØ!%�X“à’Nñ *÷ Ù˜ZÔ(÷% 
ð& €Mùò c÷ 
Ö	ð& €Mús6   ¡0D6ÁA D6Â.D1
ÃD1
Ã5D6ÄD6ÄD6Ä1D6Ä6E	c               ó$   € V ^8„  d   QhRRRRRR/# )r   Ú	old_valuer
   Ú	new_valuez
str | Noner   r   r   )r   s   "r   r   r   R   s!   € ÷ :ñ :¨#ð :¸*ð :Èñ :r   c                óJ  a aa€ S '       g   . # ^ RI HpHpHp V! 4       pVP	                  4       '       g   . #  V! V4      pT'       g   . # . oRR TT T3R lllpR R lpT! TP                  R4      R4       T! TP                  R4      R4       F  w  ršT! T
R	T	 24       K  	  T! TP                  R
4      R4       F  w  r¼T! TRT 24       K  	  T! TP                  R4      R4       F  w  rÜT! TRT 2RR7       K  	  S'       d	   T! YV4       S#   \
         d    . u # i ; i)aA  Reconcile config.yaml api_key mirrors holding ``old_value``; return dotted paths touched.

Value-matched on purpose: only an entry holding the SAME credential that just changed in
``.env`` is touched. ``new_value=None`` removes the field. Operates on the RAW user config
so defaults are never baked into the user's file.
)Úatomic_config_replaceÚget_config_pathÚread_user_config_rawc               ó(   € V ^8„  d   QhRRRRRRRR/# )	r   Úsectionr   Úkey_pathr
   Úfieldsztuple[str, ...]r   r!   r   )r   s   "r   r   Ú0_scrub_config_yaml_mirrors.<locals>.__annotate__i   s)   € ÷ 6ñ 6�cð 6 Sð 6°/ð 6Ð[_ñ 6r   c                ó  <€ \        V \        4      '       g   R # V Fj  pV P                  V4      p\        V\        4      '       g   K,  VS8X  g   K5  S'       d   SW&   MV P	                  VR 4       SP                  V RV 24       Kl  	  R # )Nr#   )r6   r7   r5   r
   Úpopr   )rJ   rK   rL   ÚfieldÚcurrentrD   rC   Útoucheds   &&&  €€€r   Ú_fixÚ(_scrub_config_yaml_mirrors.<locals>._fixi   sp   ø€ ô ˜'¤4×(Ò(ÙÛˆEØ—k‘k %Ó(ˆGÜ˜'¤3×'Ô'¨G°yÖ,@ßØ%.�G’Nà—K‘K  tÔ,Ø—‘ ( ¨1¨U¨GÐ4Ö5ó r   c               ó    € V ^8„  d   QhRRRR/# )r   Úvaluer   Ú
allow_listÚboolr   )r   s   "r   r   rM   x   s   € ÷ Rñ R�cð R tñ Rr   c                ó¤   € \        V \        4      '       d   V P                  4       # V'       d"   \        V \        4      '       d   \	        V 4      # R# )Nr   )r6   r7   r   r8   Ú	enumerate)rV   rW   s   &&r   Ú_itemsÚ*_scrub_config_yaml_mirrors.<locals>._itemsx   s9   € Ü�eœT×"Ò"Ø—;‘;“=Ð ß#-´*¸UÄD×2IÒ2IŒy˜ÓÐQÈrÐQr   ÚmodelÚ	auxiliaryFz
auxiliary.Úcustom_providersTzcustom_providers.r   z
providers.)rL   ))Úapi_keyÚapi)r`   )Úhermes_cli.configrF   rG   rH   Úexistsr   r5   )rC   rD   rF   rG   rH   Úconfig_pathÚuser_configrS   r[   ÚtaskÚslot_cfgÚnameÚentryÚprovider_idrR   s   ff            @r   Ú_scrub_config_yaml_mirrorsrk   R   s,  ú€ ÷ Øˆ	ß^Ñ^á!Ó#€KØ×Ñ×ÒØˆ	ðÙ*¨;Ó7ˆ÷ Øˆ	à€G÷6ô 6õRñ
 	ˆ�‰˜Ó	! 7Ô+Ù  §¡°Ó!=¸uÖE‰ˆÙˆX˜ D 6Ð*Ö+ñ Fá˜kŸo™oÐ.@ÓAÀ4ÖH‰ˆÙˆUÐ'¨ vÐ.Ö/ñ Iñ % [§_¡_°[Ó%AÀ5ÖIÑˆÙˆU�j  Ð.°|×Dñ J÷ Ù˜kÔ7Ø€NøôU ô ØŠ	ðús   ¸D ÄD"Ä!D"Úclear_models_cacheTc               ó$   € V ^8„  d   QhRRRRRR/# )r   r	   r
   rl   rX   r   údict[str, Any]r   )r   s   "r   r   r   �   s$   € ÷ ;ñ ;Øð;Ø)-ð;Ø9Gñ;r   c               óÖ   € \        V 4      p\        \        V4      \        \        V 4      4      ,          4      p\	        VRRV  24       V'       d   V'       d   \	        VR4       RVRV/# )zèRemove non-.env references to an env-var credential.

Prunes env-seeded pool entries and (optionally) the affected ``provider_models_cache.json`` rows
so the model picker stops advertising a provider whose key is gone.

See #59761.
z*hermes_cli.auth.suppress_credential_sourcer2   z-hermes_cli.models.clear_provider_models_cacheÚpool_prunedr   )rA   ÚsortedÚsetr   r,   )r	   rl   r;   r   s   &$  r   Úpurge_env_credential_referencesrs   �   sd   € ô % WÓ-€FÜ”s˜6“{¤SÔ)?ÀÓ)HÓ%IÕIÓJ€Iô �yÐ"NÐRVÐW^ÐV_ÐP`ÔaßŸiä˜9Ð&UÔVØ˜6 ;°	Ð:Ð:r   c               ó$   € V ^8„  d   QhRRRRRR/# )r   r	   r
   rV   r   rn   r   )r   s   "r   r   r   ¤   s&   € ÷ $Jñ $J¨#ð $J°cð $J¸nñ $Jr   c                ó  € ^ RI HpHpHp V! V R4       V! 4       P	                  V 4      pV! W4       . pV'       d   V'       d   WQ8w  d   \        WQ4      p\        V 4      p\        VRRV  24       \        VR4       RRRV R	V/# )
u  Save/update a credential in ``.env`` and reconcile every mirror.

config.yaml mirrors of the PREVIOUS value are updated so a stale higher-precedence copy cannot
shadow the rotation, and ``load_pool()`` runs now so the env-seeded ``credential_pool`` entry
lands in ``auth.json`` (a ``.env``-only write left env-backed providers 401'ing).

Suppressed ``env:<VAR>`` pool sources are re-enabled so a deliberate re-add through the UI behaves like
``hermes auth add``. See #62269.
The save also forces an immediate ``load_pool()`` for every provider registered against this env var so
the env-seeded ``credential_pool`` entry is materialized to ``auth.json`` right now â€” the live runtime
reads from the pool, and before #96058 the Desktop "Save" action only touched ``.env`` while
``auth.json``'s mtime stayed unchanged, so an OpenCode Go (or any other env-backed provider) request
kept 401'ing until the user ran ``hermes auth add <provider> --type api-key`` separately. This makes the
Desktop save's effect on disk match what ``hermes auth add`` does.
)Úload_envÚrequire_env_writableÚsave_env_valuerr   z,hermes_cli.auth.unsuppress_credential_sourcer2   zagent.credential_pool.load_poolÚokTÚkeyÚconfig_updates)rb   rv   rw   rx   r5   rk   r   r,   )r	   rV   rv   rw   rx   rC   r{   r   s   &&      r   Úsave_provider_env_credentialr|   ¤   sŒ   € ÷  QÑPñ ˜ %Ô(Ù“
—‘˜wÓ'€IÙ�7Ô"à "€Nß—˜yÔ1Ü3°IÓEˆô ' wÓ/€IÜ�yÐ"PÐTXÐY`ÐXaÐRbÔcô �yÐ"CÔDà�$˜˜wÐ(8¸.ÐIÐIr   c               ó    € V ^8„  d   QhRRRR/# )r   r	   r
   r   rn   r   )r   s   "r   r   r   Ë   s   € ÷ Sñ S¨Cð S°Nñ Sr   c                ó*  € ^ RI HpHpHp V! V R4       V! 4       P	                  V 4      pV! V 4      p\        V 4      pV'       d   \        VR4      M. pRRRT RTRVR,          R	VR	,          R
TR\        T;'       g    VR,          ;'       g    T4      /# )z¢Remove a credential from EVERY store: ``.env`` (and process env), env-seeded
``credential_pool`` entries, model-cache rows, config.yaml mirrors of the same value.)rv   Úremove_env_valuerw   ÚremoveNry   Trz   Úremovedrp   r   Úconfig_scrubbedÚfound)rb   rv   r   rw   r5   rs   rk   rX   )r	   rv   r   rw   rC   Úremoved_from_envÚrefsr‚   s   &       r   Úremove_provider_env_credentialr†   Ë   s¥   € ÷ SÑRñ ˜ (Ô+Ù“
—‘˜wÓ'€IÙ'¨Ó0ÐÜ*¨7Ó3€DßENÔ0°¸DÔAÐTV€Oð 	ˆdØˆwØÐ#Ø�t˜MÕ*Ø�T˜+Õ&Ø˜?Ø”Ð&×PÐP¨$¨}Õ*=×PÐPÀÓQðSð Sr   N)rs   r†   r|   )Ú__doc__Ú
__future__r   Útypingr   r   r   Ú__all__r   r,   rA   rk   rs   r|   r†   r   r   r   Ú<module>r‹      sL   ðñõ #ç "Ñ "ò€õõ 
õõ@:ðz;Ø04÷;õ*$J÷NSr   