+
    jHàj¬/  ã                  óN  a € 0 t $ R t^ RIHt ^ RIt^ RIHtHtHt ]P                  ! ]
4      t]! 0 R&m4      tR't]! 4       tR]R&   R R ltR R	 ltR
 R ltR R ltR R ltR R ltR R ltR R ltR R ltR R ltR R ltR R ltR R ltR  R! ltR" R# lt R$ R% lt!R# )(uÅ  Model-provider plugins as first-class citizens of ``hermes auth`` and the credential pool.

A ``plugins/model-providers/<name>/`` profile (``providers.base.ProviderProfile``) is mirrored into
``hermes_cli.auth.PROVIDER_REGISTRY`` with the ``auth_type`` it declares, so ``resolve_provider()``
accepts it whatever its auth shape. Non-api-key plugins own their login through two optional profile
callables that core consults BEFORE any built-in, name-keyed path:

- ``auth_handler(action, args) -> bool`` for ``hermes auth add|status|logout|refresh <name>``
  (``args`` is the parsed CLI namespace; truthy = the plugin owned the action, falsy = built-in path).
- ``refresh_credential(entry) -> Mapping | None`` for the credential pool: given the pooled
  ``PooledCredential`` it returns the rotated fields (``access_token``, ``refresh_token``,
  ``expires_at_ms`` â€¦) or raises. A separate hook rather than ``auth_handler("refresh", â€¦)`` because
  the pool has a credential row, not an argparse namespace, and needs tokens back, not a bool.

Every function here late-imports ``hermes_cli.auth`` names: this module is imported by the auth facade
right after ``PROVIDER_REGISTRY`` exists, and by ``agent.credential_pool``.
)ÚannotationsN)ÚAnyÚCallableÚOptionalzset[str]ÚPLUGIN_MIRRORED_PROVIDERSc               ó    € V ^8„  d   QhRRRR/# )é   Úppr   Úreturnztuple[tuple, str]© )Úformats   "ÚE/home/ubuntu/.hermes/hermes-agent/hermes_cli/auth_plugin_providers.pyÚ__annotate__r   &   s   € ÷ Eñ E˜Cð EÐ$5ñ Eó    c                ó  a€ R o\         ;QJ d!    . V3R lV P                   4       F  NK  	  5M! V3R lV P                   4       4      ;'       g    V P                  \        V3R lV P                   4       R4      ;'       g    R3# )zXSplit a profile's ``env_vars`` into (api-key vars, base-URL var); the URL var may be "".c                óV   € V P                  R 4      ;'       g    V P                  R4      # )Ú	_BASE_URLÚ_URL)Úendswith)Úvs   &r   Ú<lambda>Ú%_api_key_env_fields.<locals>.<lambda>(   s!   € �q—z‘z +Ó.×DÐD°!·*±*¸VÓ2DÐDr   c              3  óH   <"  € T F  pS! V4      '       d   K  Vx € K  	  R # 5i©Nr   ©Ú.0r   Úis_urls   & €r   Ú	<genexpr>Ú&_api_key_env_fields.<locals>.<genexpr>)   s   øé € Ð:™[˜±°q·	—!’!›[ùó   ƒ"˜
"c              3  óH   <"  € T F  pS! V4      '       g   K  Vx € K  	  R # 5ir   r   r   s   & €r   r   r   *   s   øé € Ð6™[˜©F°1¯I—!’!›[ùr   NÚ )ÚtupleÚenv_varsÚnext)r	   r   s   &@r   Ú_api_key_env_fieldsr%   &   s`   ø€ áD€FßŒEÔ:˜RŸ[š[Ó:�E‰EÔ:˜RŸ[š[Ó:Ó:×IÐI¸b¿k¹kÜÔ6˜RŸ[š[Ó6¸Ó=×CÐCÀðEð Er   c               ó    € V ^8„  d   QhRRRR/# )r   r	   r   r
   ÚNoner   )r   s   "r   r   r   -   s   € ÷  ñ   ð  ¨ñ  r   c                ó"  € ^ RI HpHpHp V P                  \
        9   d   R# V P                  R8X  d]   V P                  '       g   R# T! V P                  V P                  ;'       g    V P                  V P                  .\        V 4      O5!  pMHT! V P                  V P                  ;'       g    V P                  V P                  V P                  R7      pWAV P                  &   \        P                  V P                  4       \        W@4       R# )a  Mirror one profile into ``PROVIDER_REGISTRY`` under the ``auth_type`` it declares.

Registering is what lets an out-of-tree provider pass ``resolve_provider()``'s known-provider
gate ("Unknown provider"); OAuth-shaped plugins carry their own login via ``auth_handler``.
)ÚPROVIDER_REGISTRYÚProviderConfigÚ_api_key_providerNÚapi_key)Úinference_base_url)Úhermes_cli.authr)   r*   r+   ÚnameÚ_REGISTRY_PLUGIN_SKIPÚ	auth_typer#   Údisplay_nameÚbase_urlr%   r   ÚaddÚmirror_aliases)r	   r)   r*   r+   Úpconfigs   &    r   Úregister_plugin_providerr7   -   sº   € ÷ UÑTà	‡w�wÔ'Ô'ÙØ	‡|�|�yÔ Ø�{�{ˆ{ÙÙ# B§G¡G¨R¯_©_×-GÐ-GÀÇÁÈÏÉÐoÔWjÐkmÓWnÓo‰á  §¡¨"¯/©/×*DÐ*D¸R¿W¹WÀbÇlÁlÐgi×grÑgrÔsˆØ!(�b—g‘gÑÜ×!Ñ! "§'¡'Ô*Ü�7Ör   c               ó$   € V ^8„  d   QhRRRRRR/# )r   r	   r   ÚaliasÚstrr
   Úboolr   )r   s   "r   r   r   B   s&   € ÷ ^ñ ^˜ð ^ Sð ^¨Tñ ^r   c                óÌ   €  ^ RI HpHp T! T4      pTRJ;'       d7    TP                  T P                  8H  ;'       d    T! T P                  4      R8H  #   \         d     R# i ; i)zZTrue when *alias* resolves to the ``$HERMES_HOME`` plugin *pp* in the ``providers`` layer.)Úget_provider_profileÚprovider_sourceFNÚuser)Ú	providersr=   r>   Ú	Exceptionr/   )r	   r9   r=   r>   Úowners   &&   r   Ú_user_owns_aliasrC   B   sa   € ðßCñ ! Ó'€EØ˜Ð×]Ð] §¡¨r¯w©wÑ!6×]Ð]¹?È2Ï7É7Ó;SÐW]Ñ;]Ð]øô ô Úðús   ‚A ÁA#Á"A#c               ó$   € V ^8„  d   QhRRRRRR/# ©r   r6   r   r	   r
   r'   r   )r   s   "r   r   r   L   s!   € ÷ /ñ /˜Cð / Sð /¨Tñ /r   c                ór   € ^ RI Hp VP                   F   pW29  g   \        W4      '       g   K  WV&   K"  	  R# )u±  Point ``pp.aliases`` at *pconfig* so ``resolve_provider()`` resolves them too.

A bundled plugin never steals an alias another row already holds; a ``$HERMES_HOME`` plugin
whose alias the ``providers`` layer already resolves to it does â€” the same ownership rule as
:func:`override_registry_row`, otherwise the alias kept resolving to the built-in row while
``providers.get_provider_profile`` followed the user's profile (#116668).
©r)   N)r.   r)   ÚaliasesrC   )r6   r	   r)   r9   s   &&  r   r5   r5   L   s.   € õ 2à—”ˆØÔ)Ô-=¸b×-HÔ-HØ'.˜eÓ$ó r   c               ó$   € V ^8„  d   QhRRRRRR/# rE   r   )r   s   "r   r   r   [   s!   € ÷ /ñ / 3ð /¨Cð /°Dñ /r   c                óR  € VP                   '       d   VP                   V n        VP                  '       d   VP                  V n        VP                  Ru;8X  d   V P                  8X  d>   M R# VP
                  '       d&   \        V4      w  V n        pV'       d	   W n        R# R# R# R# )u�  A ``$HERMES_HOME`` plugin re-registering a name that already has a row wins for the fields
it declares â€” ``display_name``, ``base_url`` and, on api-key rows, ``env_vars`` (#48450, #116668). ``register_provider()``
is last-writer-wins for the profile; without this the runtime kept reading the built-in
endpoint. In place, so alias rows sharing the object follow; idempotent, so re-sync is free.
r,   N)	r2   r/   r3   r-   r1   r#   r%   Úapi_key_env_varsÚbase_url_env_var)r6   r	   Úurl_vars   && r   Úoverride_registry_rowrN   [   sx   € ð 
‡‡€Ø—‘ˆŒØ	‡{‡{€{Ø%'§[¡[ˆÔ"Ø	‡|�|�yÖ5 G×$5Ñ$5×5Ð5¸"¿+¿+¸+Ü,?ÀÓ,CÑ)ˆÔ  'ßØ'.Ö$ñ ñ ;FÑ5r   c               ó   € V ^8„  d   QhRR/# )r   r
   Úintr   )r   s   "r   r   r   k   s   € ÷ ñ  sñ r   c                 ó  € ^ RI Hp Hp  ^ RIHpHp V! 4       p^ pT FÌ  pTP                  T9   d™   TP                  T 9   ;'       g    TP                  \        9   pT'       de   TP                  \        9  dP   T! TP                  4      R8X  d9   \        YP                  ,          T4       \        YP                  ,          T4       K¬  \        T4       YVP                  T9   ,          pKÎ  	  T#   \         d     ^ # i ; i)uµ  Mirror provider-plugin profiles into ``PROVIDER_REGISTRY``; return how many were added.

Idempotent (existing entries are never replaced â€” a user plugin re-registering a bundled name
only rewrites the fields it declares, see :func:`override_registry_row`), so it is safe from
resolution paths. It runs at
auth import and again whenever a name is missing (:func:`registry_lookup`) or when ``providers``
finishes discovery, because the import-time pass can observe a *partial* profile list: a plugin
whose own imports pull ``hermes_cli.auth`` in mid-``_discover_providers()`` sees only what was
registered so far, and every later plugin would otherwise fail with "Unknown provider" (#102123).
)ÚBUILTIN_PROVIDER_IDSr)   )Úlist_providersr>   r?   )r.   rR   r)   r@   rS   r>   rA   r/   r   r0   rN   r5   r7   )rR   r)   rS   r>   ÚprofilesÚaddedr	   Úcore_rows           r   Úsync_plugin_provider_registryrW   k   sØ   € ÷ Hðß=Ù!Ó#ˆð €EÛˆØ�7‰7Ð'Ô'ð —w‘wÐ"6Ñ6×^Ð^¸"¿'¹'ÔE^Ñ:^ˆHß˜BŸG™GÔ+@Ô@Á_ÐUW×U\ÑU\ÓE]ÐagÔEgÜ%Ð&7¿¹Õ&@À"ÔEÜÐ0·±Õ9¸2Ô>ÙÜ  Ô$Ø—‘Ð-Ñ-Õ-Šñ ð €Løô ô Úðús   ŠC/ Ã/C>Ã=C>c               ó    € V ^8„  d   QhRRRR/# )r   Úprovider_idr:   r
   úOptional[Any]r   )r   s   "r   r   r   Œ   s   € ÷ ñ  ð ¨ñ r   c                ó~   € ^ RI Hp VP                  V 4      pVf"   \        4       '       d   VP                  V 4      pV# )zB``PROVIDER_REGISTRY.get`` that re-syncs plugin profiles on a miss.rG   )r.   r)   ÚgetrW   )rY   r)   r6   s   &  r   Úregistry_lookupr]   Œ   s8   € å1à×#Ñ# KÓ0€GØ‚Ô8×:Ò:Ø#×'Ñ'¨Ó4ˆØ€Nr   c               ó    € V ^8„  d   QhRRRR/# )r   Úproviderr:   r
   rZ   r   )r   s   "r   r   r   –   s   € ÷ *ñ *˜Sð * ]ñ *r   c                óD   €  ^ RI Hp T! T 4      #   \         d     R# i ; i)z`The registered ``ProviderProfile`` for *provider*, or None (also when the layer is unavailable).)r=   N)r@   r=   rA   )r_   r=   s   & r   Úplugin_profilera   –   s+   € ðÝ2ñ   Ó)Ð)øô ô Úðús   ‚ �žc               ó$   € V ^8„  d   QhRRRRRR/# )r   r_   r:   r/   r
   zOptional[Callable[..., Any]]r   )r   s   "r   r   r   Ÿ   s"   € ÷ ,ñ ,˜Cð , sð ,Ð/Kñ ,r   c                óX   € \        \        V 4      VR 4      p\        V4      '       d   V# R # r   )Úgetattrra   Úcallable)r_   r/   Úhooks   && r   Ú_profile_hookrg   Ÿ   s(   € Ü”> (Ó+¨T°4Ó8€DÜ˜D—>’>ˆ4Ð+ tÐ+r   c               ó    € V ^8„  d   QhRRRR/# )r   r_   r:   r
   z#Optional[Callable[[str, Any], Any]]r   )r   s   "r   r   r   ¤   s   € ÷ 3ñ 3 #ð 3Ð*Mñ 3r   c                ó   € \        V R 4      # )Úauth_handler©rg   ©r_   s   &r   Úplugin_auth_handlerrm   ¤   s   € Ü˜ >Ó2Ð2r   c               ó    € V ^8„  d   QhRRRR/# )r   r_   r:   r
   zOptional[Callable[[Any], Any]]r   )r   s   "r   r   r   ¨   s   € ÷ 9ñ 9 #ð 9Ð*Hñ 9r   c                ó   € \        V R4      # )z^The profile's ``refresh_credential`` hook, i.e. whether its pooled OAuth rows are refreshable.Úrefresh_credentialrk   rl   s   &r   Úplugin_refresh_hookrq   ¨   s   € ä˜Ð#7Ó8Ð8r   c               ó    € V ^8„  d   QhRRRR/# )r   r_   r:   r
   r;   r   )r   s   "r   r   r   ­   s   € ÷ `ñ `¨Cð `°Dñ `r   c                ó@   € ^ RI Hp W9   ;'       g    \        V 4      RJ# )zMBuilt-in refreshable set OR a plugin profile shipping ``refresh_credential``.)ÚREFRESHABLE_OAUTH_PROVIDERSN)Úagent.credential_poolrt   rq   )r_   rt   s   & r   Úis_refreshable_oauth_providerrv   ­   s"   € åAàÑ2×_Ð_Ô6IÈ(Ó6SÐ[_Ð6_Ð_r   c               ó(   € V ^8„  d   QhRRRRRRRR/# )r   Úactionr:   Úargsr   r_   r
   r;   r   )r   s   "r   r   r   ´   s.   € ÷ qñ q ð q¨Cð q¸3ð qÀ4ñ qr   c           
     ó  € ^ RI Hp V! WV4      pVe   V# \        V4      pVf   R#  \        V! W4      4      #   \         d    h \
         d0   p\	        T RT  R\        T4      P                   RT 24      ThRp?ii ; i)al  Offer ``hermes auth <action> <provider>`` to the provider's ``auth_handler``.

True = the plugin owned the action (core prints nothing more). False = run the built-in path. A
handler exception becomes a readable ``SystemExit`` naming provider and action.
``<plugin>:<id>`` names an OAuth client a plugin declares under ``oauth:`` (:mod:`hermes_cli.plugin_oauth`).
)Úhandle_auth_actionNFz auth handler failed for `z`: z: )Úhermes_cli.plugin_oauthr{   rm   r;   Ú
SystemExitrA   ÚtypeÚ__name__)rx   ry   r_   r{   ÚownedÚhandlerÚexcs   &&&    r   Údispatch_plugin_authrƒ   ´   s˜   € õ ;á˜v¨XÓ6€EØÒØˆÜ! (Ó+€GØ‚ÙðqÜ‘G˜FÓ)Ó*Ð*øÜô ØÜô qÜ˜H˜:Ð%?À¸xÀsÌ4ÐPSË9×K]ÑK]ÐJ^Ð^`ÐadÐ`eÐfÓgÐmpÐpûðqús   ¨9 ¹A>ÁA>Á*A9Á9A>c               ó$   € V ^8„  d   QhRRRRRR/# )r   r_   r:   rx   r
   zOptional[SystemExit]r   )r   s   "r   r   r   Ë   s'   € ÷ Yñ Y°ð Y¸Sð YÐEYñ Yr   c                ó¾   € V \         9  d   R# \        V 4      pVe   VP                  R8X  g   \        V 4      e   R# \	        RV  RVP                   RV RV  R2	4      # )a  Fail loud for a registered non-api-key plugin that ships no ``auth_handler``.

Its login is not something core can perform (there is no token endpoint to call), and silently
running the api-key prompt or reporting "Unknown provider" both hide the plugin bug.
Nr,   z
Provider 'z' declares auth_type 'z8' but its plugin ships no auth_handler, so `hermes auth Ú zf` cannot be handled. Add `auth_handler=` to its ProviderProfile (see the model-provider plugin guide).)r   ra   r1   rm   r}   )r_   rx   Úprofiles   && r   Ú!plugin_missing_auth_handler_errorrˆ   Ë   s|   € ð Ô0Ô0ÙÜ˜XÓ&€GØ‚˜'×+Ñ+¨yÔ8Ô<OÐPXÓ<YÒ<eÙÜØ
�X�JÐ4°W×5FÑ5FÐ4Gð H)Ø)/¨°°(°ð <Xð	XóYð Yr   c               ó    € V ^8„  d   QhRRRR/# )r   Úentryr   r
   r;   r   )r   s   "r   r   r   Ü   s   € ÷ 
ñ 
˜sð 
 tñ 
r   c                ó&  € ^ RI p^ RIHp V P                  e7   \	        V P                  4      \	        VP                  4       R,          4      8*  # V P
                  '       d1   V! V P
                  4      pVRJ;'       d    W1P                  4       8*  # R# )z]A pooled OAuth row is expired when its ``expires_at_ms`` / ISO ``expires_at`` is in the past.N)Ú_parse_iso_timestampiè  F)Útimer.   rŒ   Úexpires_at_msrP   Ú
expires_at)rŠ   r�   rŒ   Úepochs   &   r   Ú_pool_entry_expiredr‘   Ü   su   € ãÝ4à×ÑÒ&Ü�5×&Ñ&Ó'¬3¨t¯y©y«{¸TÕ/AÓ+BÑBÐBØ××ÐÙ$ U×%5Ñ%5Ó6ˆØ˜DÐ ×9Ð9 U¯i©i«kÑ%9Ð9Ùr   c               ó    € V ^8„  d   QhRRRR/# )r   rY   r:   r
   zdict[str, Any]r   )r   s   "r   r   r   é   s   € ÷ Tñ T¨cð T°nñ Tr   c                ó�  € V \         9  d   RR/# ^ RIHp V! V 4      P                  4        Uu. uFD  q"P                  ;'       g    VP
                  ;'       g    RP                  4       '       g   KB  VNKF  	  ppV Uu. uF  p\        V4      '       d   K  VNK  	  ppV'       g7   \        V 4      '       d&   V Uu. uF  q"P                  '       g   K  VNK  	  upM. pRRRT R\        V4      R\        V4      R	\        V4      R
\        R WE,            4       R4      ;'       g    RRV'       d   R/# RV  R2/# u upi u upi u upi )uÙ  Status for an OAuth-shaped PLUGIN provider, read from the credential pool its ``auth_handler`` fills.

``configured`` = the profile is registered; ``logged_in`` = a pool row carries a live token;
``needs_refresh`` = every token is expired but refresh material (and a ``refresh_credential`` hook)
exists. Bundled OAuth providers keep their bespoke builders (``_BESPOKE_STATUS_FUNCTIONS``) â€” this
one is gated on the plugin-mirrored set so their status bytes never change.
Ú	logged_inF)Ú	load_poolr!   Ú
configuredTr_   Úneeds_refreshÚaccountsr3   c              3  ó`   "  € T F$  qP                   '       g   K  VP                   x € K&  	  R # 5ir   )r3   )r   Úes   & r   r   Ú/get_plugin_oauth_auth_status.<locals>.<genexpr>û   s   é € ÐOÑ.@¨ÇJÅJœ*˜!Ÿ*ž*Ó.@ùs   ‚.š.ÚhintzRun `hermes auth add z` to sign in.)r   ru   r•   ÚentriesÚaccess_tokenÚ	agent_keyÚstripr‘   rq   Úrefresh_tokenr;   Úlenr$   )rY   r•   rš   r�   ÚliveÚrefreshables   &     r   Úget_plugin_oauth_auth_statusr¥   é   s*  € ð Ô3Ô3Ø˜UÐ#Ð#Ý/á# KÓ0×8Ñ8Ô:ÓlÑ:�Q¿~¹~×?bÐ?bÐQR×Q\ÑQ\×?bÐ?bÐ`b×>iÑ>i×>k�qˆqÑ:€GÐlÙÓ=‘w�!Ô&9¸!×&<�AˆA‘w€DÐ=ßAEÔJ]Ð^i×JjÒJj™gÓ9™g˜¯­—1�1™gÒ9Ðpr€Kà�d˜J¨°[Ä$ÀtÃ*Øœ˜kÓ*¨J¼¸G»Ø”DÑO¨dÖ.@ÓOÐQSÓT×ZÐZÐXZØ—d�ð	Tð Tð #8¸°}ÀMÐ Rð	Tð Tùò mùÚ=ùÚ9s/   ®D9ÁD9ÁD9Á2D9Á>D>ÂD>Â;EÃE>   ÚzaiÚcustomÚcopilotÚ
openrouterúkimi-codingúkimi-coding-cn)r4   ÚstatusÚlogoutÚrefresh)"Ú__conditional_annotations__Ú__doc__Ú
__future__r   ÚloggingÚtypingr   r   r   Ú	getLoggerr   ÚloggerÚ	frozensetr0   ÚPLUGIN_AUTH_ACTIONSÚsetr   Ú__annotations__r%   r7   rC   r5   rN   rW   r]   ra   rg   rm   rq   rv   rƒ   rˆ   r‘   r¥   )r¯   s   @r   Ú<module>rº      s£   øðôõ" #ã ß *Ñ *à	×	Ò	˜8Ó	$€ñ
 "Ò"mÓnÐ à<Ð ñ
 '*£eÐ ˜8Ó +õEõ õ*^õ/õ/õ õBõ*õ,õ
3õ9õ
`õqõ.Yõ"
÷Tr   