+
    „WÝjef  ã                  óN  a € 0 t $ R t^ RIHt ^ RIt^ RIt^ RIt^ RIt^ RIt^ RIH	t	H
t
 ^ RIHt ^ RIHtHtHtHt ^ RIt^ RIHt ]P,                  ! ]4      tRTtRUtRtRVtRWtRtR	tRXt ]PB                  ! R
4      t"]PB                  ! R4      t#RYt$Rt%R R lt&]PB                  ! R4      t']	 ! R R4      4       t(]	 ! R R4      4       t)]	 ! R R4      4       t*R R lt+R R lt,R R lt-R R lt.R R lt/RZR  R! llt0RZR" R# llt1RZR$ R% llt2R& R' lt3R( R) lt4]PB                  ! R*4      t5R+ R, lt6RZR- R. llt7R/ R0 lt8R1 R2 lt9R3 R4 lt:R5 R6 lt;R7 R8 lt<R9s=R: R; lt>R<R=/R> R? llt?R[s@R@]ARA&   RB RC ltBRD RE ltCRF RG ltDRH RI ltERJ RK ltFR\tGRL RM ltHRN RO ltIRP RQ ltJRR RS ltKR# )]un  Plugin catalog â€” curated, Nous-approved Hermes plugins shipped with the repo.

Mirrors the ``optional-mcps/`` MCP-catalog pattern: one YAML file per entry under the in-tree
``plugin-catalog/`` directory, pinned to an exact 40-character commit SHA. Presence in the directory IS
the human-merged approval gate; SHA bumps are new, re-reviewed PRs; ``removed.yaml`` is the kill list
(installs of a removed name/repo are refused with the recorded reason). Full policy:
``plugin-catalog/README.md``.

Live refresh: the docs build publishes the same data as ONE JSON document
(``website/scripts/extract-plugins.py`` â†’ ``/docs/api/plugin-catalog.json``, like the skills index), so
an installed Hermes sees new entries and removals without updating. A fetch failure reuses the last valid
cached copy regardless of age, then falls back to the in-tree copy when no valid cache exists.
)ÚannotationsN)Ú	dataclassÚfield)ÚPath)ÚAnyÚDictÚListÚOptional)ÚUTCzBhttps://hermes-agent.nousresearch.com/docs/api/plugin-catalog.jsong      N@g      @z^[0-9a-f]{40}$z"^[A-Za-z0-9][A-Za-z0-9._+-]{0,31}$z.githubusercontent.comc               ó    € V ^8„  d   QhRRRR/# )é   ÚurlÚstrÚreturnÚbool© )Úformats   "ÚMC:\Users\johnn\AppData\Local\hermes\hermes-agent\hermes_cli\plugin_catalog.pyÚ__annotate__r   3   s   € ÷ pñ p˜cð p dñ pó    c                ó  € ^ RI Hp V! V 4      pVP                  ;'       g    RP                  4       pVP                  R8H  ;'       d:    \        V4      ;'       d'    V\        9   ;'       g    VP                  \        4      # )é    ©ÚurlsplitÚ Úhttps)	Úurllib.parser   ÚhostnameÚlowerÚschemer   ÚIMAGE_HOSTSÚendswithÚIMAGE_HOST_SUFFIX)r   r   ÚpartsÚhosts   &   r   Úis_allowed_image_urlr%   3   sb   € Ý%Ù�S‹M€EØ�N‰N× Ð ˜b×'Ñ'Ó)€DØ�<‰<˜7Ñ"×oÐo¤t¨D£z×oÐo°t¼{Ñ7J×7nÐ7nÈdÏmÉmÔ\mÓNnÐor   z^[a-z0-9_-]{1,64}$c                  óL   € ] tR t^;t$ R]R&   RtR]R&   RtR]R&   RtR]R&   RtR# )	ÚRemovedEntryr   Únamer   ÚrepoÚreasonÚdater   N)	Ú__name__Ú
__module__Ú__qualname__Ú__firstlineno__Ú__annotations__r)   r*   r+   Ú__static_attributes__r   r   r   r'   r'   ;   s#   ‡ à
ƒIØ€Dˆ#ƒNØ€FˆCÓØ€Dˆ#‡Nr   r'   c                  óˆ   € ] tR t^Ct$ ]! ]R7      tR]R&   ]! ]R7      tR]R&   ]! ]R7      t	R]R&   ]! ]R7      t
R]R&   RtR# )	ÚCatalogCapabilities©Údefault_factoryú	list[str]Úprovides_toolsÚprovides_hooksÚprovides_middlewareÚrequires_envr   N)r,   r-   r.   r/   r   Úlistr7   r0   r8   r9   r:   r1   r   r   r   r3   r3   C   s?   ‡ á %°dÔ ;€N�IÓ;Ù %°dÔ ;€N�IÓ;Ù%*¸4Ô%@Ð˜Ó@Ù#°DÔ9€L�)×9r   r3   c                  óh  € ] tR t^Kt$ R]R&   R]R&   R]R&   R]R&   R]R&   RtR]R&   R	tR]R
&   RtR]R&   RtR]R&   Rt	R]R&   Rt
R]R&   RtR]R&   ]! ]R7      tR]R&   RtR]R&   ]! ]R7      tR]R&   RtR]R&   RtR]R&   ]! ]R7      tR]R&   ]! ]R7      tR]R&   ]R R l4       tR R  ltR!tR"# )#ÚPluginCatalogEntryr   r(   r)   ÚshaÚdescriptionÚ
maintainerÚ	communityÚtierÚdesktopÚcategoryr   Úrequires_hermesÚsubdirÚdocs_urlÚversionÚimager4   r6   ÚscreenshotsFr   ÚreadmeÚ	platformsÚtitleÚ
onboardingr3   ÚcapabilitiesÚknown_issuesc               ó   € V ^8„  d   QhRR/# )r   r   r   r   )r   s   "r   r   ÚPluginCatalogEntry.__annotate__b   s   € ÷ Jñ J Cñ Jr   c                ót   € V P                   '       d   V P                   RV P                    2# V P                  # )zK``_install_plugin_core`` identifier (``repo#subdir`` for monorepo entries).Ú#)rF   r)   )Úselfs   &r   Úinstall_identifierÚ%PluginCatalogEntry.install_identifiera   s.   € ð 04¯{¯{¨{�$—)‘)�˜A˜dŸk™k˜]Ð+ÐIÀÇ	Á	ÐIr   c               ó   € V ^8„  d   QhRR/# )r   r   údict[str, Any]r   )r   s   "r   r   rR   f   s   € ÷ 
ñ 
˜ñ 
r   c                	óÖ  € V P                   p/ R V P                  bRV P                  bRV P                  bRV P                  bRV P
                  bRV P                  bRV P                  bRV P                  bRV P                  bR	V P                  bR
V P                  bRV P                  bR\        V P                  4      bRV P                  bR\        V P                   4      bRV P"                  bRV P$                  bRR\        VP&                  4      R\        VP(                  4      R\        VP*                  4      R\        VP,                  4      /R\        V P.                  4      /C# )r(   r)   r>   r?   r@   rB   rD   rE   rF   rG   rH   rI   rJ   rK   rL   rM   rN   rO   r7   r8   r9   r:   rP   )rO   r(   r)   r>   r?   r@   rB   rD   rE   rF   rG   rH   rI   r;   rJ   rK   rL   rM   rN   r7   r8   r9   r:   rP   )rU   Úcapss   & r   Úto_dictÚPluginCatalogEntry.to_dictf   s˜  € Ø× Ñ ˆð
Ø�D—I‘Ið
Ø% t§y¡yð
Ø27¸¿¹ð
ØCPÐRV×RbÑRbð
à˜$Ÿ/™/ð
à+1°4·9±9ð
à>HÈ$Ï-É-ð
ð ˜t×3Ñ3ð
ð �d—k‘kð	
ð $.¨t¯}©}ð	
ð ?HÈÏÉð	
ð X_Ð`d×`jÑ`jð	
ð
 œ4 × 0Ñ 0Ó1ð
ð
 4<¸T¿[¹[ð
ð œ˜dŸn™nÓ-ð
ð 07¸¿
¹
ð
ð EQÐRV×RaÑRað
ð Ø ¤$ t×':Ñ':Ó";Ð=MÌtÐTX×TgÑTgÓOhØ%¤t¨D×,DÑ,DÓ'EÀ~ÔW[Ð\`×\mÑ\mÓWnðð œD ×!2Ñ!2Ó3ñ
ð 	
r   r   N)r,   r-   r.   r/   r0   rB   rD   rE   rF   rG   rH   rI   r   r;   rJ   rK   rL   rM   rN   r3   rO   rP   ÚpropertyrV   r\   r1   r   r   r   r=   r=   K   sÚ   ‡ à
ƒIØ
ƒIØ	ƒHØÓØƒOØ€Dˆ#ÓØ€HˆcÓØ€O�SÓØ€FˆCÓØ€HˆcÓØ€GˆSÓØ€Eˆ3ƒOÙ"°4Ô8€K�Ó8Ø€FˆDÓÙ °Ô6€IˆyÓ6Ø€Eˆ3ƒOØ€J�ÓÙ(-Ð>QÔ(R€LÐ%ÓRÙ#°DÔ9€L�)Ó9àôJó ðJ÷
ñ 
r   r=   c               ó   € V ^8„  d   QhRR/# ©r   r   r   r   )r   s   "r   r   r   w   s   € ÷ Eñ E˜ñ Er   c                 ór   € \        \        4      P                  4       P                  P                  R,          # )z=The ``plugin-catalog/`` directory shipped with this checkout.úplugin-catalog)r   Ú__file__ÚresolveÚparentr   r   r   Úget_catalog_dirrf   w   s'   € ä”‹>×!Ñ!Ó#×*Ñ*×1Ñ1Ð4DÕDÐDr   c               ó    € V ^8„  d   QhRRRR/# )r   Úrawr   r   r6   r   )r   s   "r   r   r   ~   s   € ÷ fñ f�3ð f˜9ñ fr   c           	     ó¸   € \        V \        4      '       d?   V  Uu. uF1  p\        V\        \        \        34      '       g   K&  \        V4      NK3  	  up# . # u upi ©N)Ú
isinstancer;   r   ÚintÚfloat)rh   Úxs   & r   Ú	_str_listro   ~   sD   € ÜHRÐSVÔX\×H]ÒH]™CÓD™C�q¤:¨a´#´s¼EÐ1B×#CŒFŒC�ŽF™CÑDÐeÐceÐeùÒDs   ›#AÁAc               ó$   € V ^8„  d   QhRRRRRR/# )r   Údatar   Úlabelr   r   úOptional[PluginCatalogEntry]r   )r   s   "r   r   r   ‚   s"   € ÷ 0ñ 0˜Sð 0¨ð 0Ð1Mñ 0r   c                ó  € \        V \        4      '       g   \        P                  RV4       R# \	        V P                  R4      ;'       g    R4      p\	        V P                  R4      ;'       g    R4      p\	        V P                  R4      ;'       g    R4      P                  4       P                  4       p\	        V P                  R4      ;'       g    R4      p\	        V P                  R	4      ;'       g    R
4      p\        P                  V4      '       g   RV: R2M VP                  R4      '       g   RV: R2M‚\        P                  V4      '       g   RV P                  R4      : R2MQV\        9  d   RRP                  \        4       RV: R2M)V\        9  d   RRP                  \        4       RV: R2MRpV'       d   \        P                  RW4       R# V P                  R4      p\        V\        4      '       d   TM/ p	\	        V P                  R4      ;'       g    R4      P                  4       p
V
'       d4   \        P                  V
4      '       g   \        P                  RW4       Rp
\	        V P                  R4      ;'       g    R4      P                  4       pV'       d*   \!        V4      '       g   \        P                  RW4       Rp\#        V P                  R4      4       Uu. uF  p\!        V4      '       g   K  VNK  	  pp\%        V4      \%        \#        V P                  R4      4      4      8w  d   \        P                  RV4       \'        R./ RVbRVbRVbR\	        V P                  R4      ;'       g    R4      P                  4       bR\	        V P                  R4      ;'       g    R4      P                  4       bRVbR	VbR\	        V P                  R4      ;'       g    R4      P                  4       bR \	        V P                  R 4      ;'       g    R4      P                  4       bR!\	        V P                  R!4      ;'       g    R4      P                  4       bRV
bRVbRVbR"V P                  R"4      R#JbR$\#        V P                  R$4      4      bR%\	        V P                  R%4      ;'       g    R4      P                  4       bR&V P                  R&4      R'J bR(\#        V P                  R(4      4      bR\)        \#        V	P                  R)4      4      \#        V	P                  R*4      4      \#        V	P                  R+4      4      \#        V	P                  R,4      4      R-7      b # u upi )/z_Validate one entry mapping (YAML file or live-JSON element); ``None`` + warning on any failure.z+Plugin catalog: %s: entry must be a mappingNr(   r   r)   r>   rB   rA   rD   rC   zinvalid name z (must match [a-z0-9_-]{1,64})zhttps://z"repo must be an https:// URL (got Ú)z4sha must be a full 40-character hex commit SHA (got ztier must be one of Ú/z (got zcategory must be one of zPlugin catalog: %s: %srO   rH   zIPlugin catalog: %s: ignoring version %r (max 32 chars of [A-Za-z0-9._+-])rI   zFPlugin catalog: %s: ignoring image %r (must be https on a GitHub host)rJ   z9Plugin catalog: %s: ignoring screenshots off GitHub hostsr?   r@   rE   rF   rG   rK   FrL   rM   rN   TrP   r7   r8   r9   r:   )r7   r8   r9   r:   r   )rk   ÚdictÚloggerÚwarningr   ÚgetÚstripr   Ú_NAME_REÚmatchÚ
startswithÚ_SHA_REÚCATALOG_TIERSÚjoinÚCATALOG_CATEGORIESÚ_VERSION_REr%   ro   Úlenr=   r3   )rq   rr   r(   r)   r>   rB   rD   ÚproblemÚcaps_rawr[   rH   rI   ÚsrJ   s   &&            r   Úentry_from_mappingrˆ   ‚   s±  € ä�dœD×!Ò!Ü�‰ÐDÀeÔLÙÜˆt�x‰x˜Ó×%Ð% 2Ó&€DÜˆt�x‰x˜Ó×%Ð% 2Ó&€DÜ
ˆd�h‰h�u‹o×#Ð# Ó
$×
*Ñ
*Ó
,×
2Ñ
2Ó
4€CÜˆt�x‰x˜Ó×.Ð. ;Ó/€DÜ�4—8‘8˜JÓ'×4Ð4¨9Ó5€HäHPÏÉÐW[×H\ÒH\ˆ-˜‘xÐ?Ñ@ØCGÇ?Á?ÐS]×C^ÒC^Ð1°$±¸Ñ;Ü`g×`mÑ`mÐnq×`rÒ`rÐCÀDÇHÁHÈUÃOÑCVÐVWÑXØPTÔ\iÔPiÐ# C§H¡H¬]Ó$;Ð#<¸FÀ4Á(È!ÑLàÔ-Ô-ð (¨¯©Ô1CÓ(DÐ'EÀVÈHÉ<ÐWXÑYàð ÷ Ü�‰Ð/°Ô@ÙØ�x‰x˜Ó'€HÜ'1°(¼D×'AÒ'A™8Àr€DÜ�$—(‘(˜9Ó%×+Ð+¨Ó,×2Ñ2Ó4€Gß”{×(Ñ(¨×1Ò1Ü�‰ÐbÐdiÔsØˆÜ�—‘˜Ó!×'Ð' RÓ(×.Ñ.Ó0€EßÔ)¨%×0Ò0Ü�‰Ð_ÐafÔnØˆÜ'¨¯©°Ó(?Ô@Ó\Ñ@˜ÔDXÐYZ×D[—1�1Ñ@€KÐ\Ü
ˆ;Óœ3œy¨¯©°-Ó)@ÓAÓBÔBÜ�‰ÐRÐTYÔZÜò ÙðÙðÙ"%ðä˜Ÿ™ Ó/×5Ð5°2Ó6×<Ñ<Ô>ðô �t—x‘x Ó-×3Ð3°Ó4×:Ñ:Ô<ðñ DHðñ S[ðô ˜DŸH™HÐ%6Ó7×=Ð=¸2Ó>×DÑDÔFð	ô
 �4—8‘8˜HÓ%×+Ð+¨Ó,×2Ñ2Ô4ðô
 @CÀ4Ç8Á8ÈJÓCW×C]ÐC]Ð[]Ó?^×?dÑ?dÔ?fðñ ðñ  %ðñ 3>ðð GKÇhÁhÈxÓFXÐ`eÑFeðô ˜DŸH™H [Ó1Ô2ðô �$—(‘(˜7Ó#×)Ð) rÓ*×0Ñ0Ô2ðð @D¿x¹xÈÓ?UÐY]Ñ?]ðô ˜tŸx™x¨Ó7Ô8ðô )Ü$ T§X¡XÐ.>Ó%?Ó@ÔQZÐ[_×[cÑ[cÐdtÓ[uÓQvÜ )¨$¯(©(Ð3HÓ*IÓ JÜ" 4§8¡8¨NÓ#;Ó<õ>ðð ùò ]s   Ë9VÌVc               ó    € V ^8„  d   QhRRRR/# )r   Úpathr   r   r   r   )r   s   "r   r   r   µ   s   € ÷ ñ �Tð ˜cñ r   c                óÂ   €  \         P                  ! V P                  R R7      4      ;'       g    / #   \         d"   p\        P                  RY4        Rp?R# Rp?ii ; i)ú	utf-8-sig©Úencodingz%Plugin catalog: failed to read %s: %sN)ÚyamlÚ	safe_loadÚ	read_textÚ	Exceptionrx   ry   )rŠ   Úexcs   & r   Ú
_read_yamlr”   µ   sK   € ðÜ�~Š~˜dŸn™n°k˜nÓBÓC×IÐIÀrÐIøÜô Ü�‰Ð>ÀÔJÝûðús   ‚,2 ¯2 ²A½AÁAc               ó    € V ^8„  d   QhRRRR/# )r   Úraw_listr   r   úlist[RemovedEntry]r   )r   s   "r   r   r   ½   s   € ÷ Dñ D ð DÐ);ñ Dr   c                óÈ  € \        V \        4      '       g   . # V  Uu. uF¹  p\        V\        4      '       g   K  VP                  R 4      '       g   K4  \	        \        VR ,          4      \        VP                  R4      ;'       g    R4      \        VP                  R4      ;'       g    R4      \        VP                  R4      ;'       g    R4      R7      NK»  	  up# u upi )r(   r)   r   r*   r+   )r(   r)   r*   r+   )rk   r;   rw   rz   r'   r   )r–   Úrs   & r   Ú_removed_from_listrš   ½   s¸   € Ü�h¤×%Ò%Øˆ	ñ óDñ ˆAœZ¨¬4×0ô	4à56·U±U¸6·]ô	4Œœ#˜a �i›.¬s°1·5±5¸³=×3FÐ3FÀBÓ/GÔPSÐTU×TYÑTYÐZbÓTc×TiÐTiÐgiÓPjÜ˜aŸe™e F›m×1Ð1¨rÓ2÷	4áñDð Dùò Ds   �CºCÁACÂ)"CÃCc               ó    € V ^8„  d   QhRRRR/# )r   Úcatalog_dirúOptional[Path]r   úlist[PluginCatalogEntry]r   )r   s   "r   r   r   È   s   € ÷ ñ ˜nð Ð8Pñ r   c                óD  € T ;'       g    \        4       pVP                  4       '       g   . # . p\        VP                  R4      4       FS  pVP                  R8X  d   K  \        V4      pVe   \        V\        V4      4      MRpVf   KB  VP                  V4       KU  	  V# )u    Every valid ``*.yaml`` entry in the catalog dir (``removed.yaml`` excluded), sorted by file name.
Malformed entries are skipped with a warning â€” never raises.z*.yamlúremoved.yamlN)	rf   Úis_dirÚsortedÚglobr(   r”   rˆ   r   Úappend)rœ   ÚrootÚentriesrŠ   rq   Úentrys   &     r   Úload_catalogr¨   È   s‹   € ð ×+Ð+œ/Ó+€DØ�;‰;�=Š=Øˆ	Ø€GÜ�t—y‘y Ó*Ö+ˆØ�9‰9˜Ô&ÙÜ˜$ÓˆØ7;Ò7GÔ" 4¬¨T«Ô3ÈTˆØÔØ�N‰N˜5Ö!ñ ,ð €Nr   c               ó    € V ^8„  d   QhRRRR/# )r   rœ   r�   r   r—   r   )r   s   "r   r   r   Ù   s   € ÷ Uñ U >ð UÐ=Oñ Ur   c                óâ   € T ;'       g    \        4       R,          pVP                  4       '       d   \        V4      MRp\        V\        4      '       d   \        VP                  R4      4      # . # )uB   ``removed.yaml``'s ``removed:`` list; missing/malformed â†’ empty.r    NÚremoved)rf   Úis_filer”   rk   rw   rš   rz   )rœ   rŠ   rq   s   &  r   Úload_removed_listr­   Ù   sT   € à×,Ð,œ?Ó,°Õ>€DØ#Ÿ|™|Ÿ~š~Œ:�dÔ°4€DÜ6@ÀÄt×6LÒ6LÔ˜dŸh™h yÓ1Ó2ÐTÐRTÐTr   c               ó$   € V ^8„  d   QhRRRRRR/# )r   r(   r   rœ   r�   r   rs   r   )r   s   "r   r   r   à   s'   € ÷ Pñ P˜Cð P¨nð PÐHdñ Pr   c                óB   a € \        V 3R  l\        V4       4       R4      # )c              3  óL   <"  € T F  qP                   S8X  g   K  Vx € K  	  R # 5irj   ©r(   ©Ú.0Úer(   s   & €r   Ú	<genexpr>Ú$get_catalog_entry.<locals>.<genexpr>á   s   øé € ÐHÑ5�q¿¹À4¹—’Ó5ùó   ƒ$š
$N)Únextr¨   )r(   rœ   s   f&r   Úget_catalog_entryr¹   à   s   ø€ ÜÔHœL¨Ô5ÓHÈ$ÓOÐOr   c               ó$   € V ^8„  d   QhRRRRRR/# )r   r¦   rž   Úqueryr   r   r   )r   s   "r   r   r   ä   s(   € ÷ eñ eÐ4ð e¸Sð eÐE]ñ er   c                óÊ  a€ T;'       g    RP                  4       P                  4       oS'       g   V # V  Uu. uFŸ  p\        ;QJ dK    V3R lVP                  VP                  .VP
                  P                  O 4       F  '       g   K   RM@	  RM<! V3R lVP                  VP                  .VP
                  P                  O 4       4      '       g   K�  VNK¡  	  up# u upi )z^Case-insensitive substring match over name, description and declared tools; empty query = all.r   c              3  óJ   <"  € T F  pSVP                  4       9   x € K  	  R # 5irj   )r   )r³   ÚhÚqs   & €r   rµ   Ú!filter_entries.<locals>.<genexpr>ê   s   øé € ÐcÑ+b a�1˜Ÿ™›	–>Ó+bùs   ƒ #TF)r{   r   Úanyr(   r?   rO   r7   )r¦   r»   r´   r¿   s   && @r   Úfilter_entriesrÂ   ä   s§   ø€ à	�ˆ�"×ÑÓ×#Ñ#Ó%€AßØˆÙó e‘w�!ß‹sÔc¨A¯F©F°A·M±MÐ+bÀAÇNÁN×DaÑDaÑ+bÓc�s�sŠsÔc¨A¯F©F°A·M±MÐ+bÀAÇNÁN×DaÑDaÑ+bÓc×c÷ ˆA‘wñ eð eùò es   ¸C ÁA C ÂAC ÃC c               ó    € V ^8„  d   QhRRRR/# )r   r»   r   r   rž   r   )r   s   "r   r   r   í   s   € ÷ 1ñ 1˜#ð 1Ð":ñ 1r   c                ó*   € \        \        4       V 4      # rj   )rÂ   r¨   )r»   s   &r   Úsearch_catalogrÅ   í   s   € Üœ,›.¨%Ó0Ð0r   z%^(?:[^@/\s]+@)?([^:/\s]+):(?!//)(.+)$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 V P                  4       p\        P	                  V4      pV'       d#   VP                  ^4      VP                  ^4      rTM4RV9   d+   V! V4      pVP                  ;'       g    RVP                  rTMRTrTVP                  4       P                  R4      pVP                  R4      P                  R4      P                  R4      P                  4       pV'       d   V RV 2# T# )uä   Canonical ``host/path`` for a repo URL: scheme, user, ``www.``, ``.git`` and trailing slashes are
spelling, not identity â€” the kill list must match ``git@github.com:Evil/Bad.git`` when it names
``https://github.com/evil/bad``.r   z://r   zwww.rv   ú.git)r   r   r{   Ú_SCP_URL_REr}   Úgroupr   rŠ   r   ÚremoveprefixÚremovesuffixÚrstrip)r   r   ÚtextÚscpr$   rŠ   r#   s   &      r   Ú_normalize_reporÐ   ö   sÄ   € õ &Ø�9‰9‹;€DÜ
×
Ñ
˜DÓ
!€Cß
Ø—Y‘Y˜q“\ 3§9¡9¨Q£<‰dØ	�$ŒÙ˜“ˆØ—^‘^×)Ð) r¨5¯:©:‰dà˜ˆdØ�:‰:‹<×$Ñ$ VÓ,€DØ�:‰:�c‹?×'Ñ'¨Ó/×6Ñ6°sÓ;×AÑAÓC€Dß#ˆdˆV�1�T�FÐÐ-¨Ð-r   c               ó$   € V ^8„  d   QhRRRRRR/# )r   Úname_or_repor   rœ   r�   r   úOptional[RemovedEntry]r   )r   s   "r   r   r   	  s"   € ÷ 0ñ 0˜sð 0°ð 0ÐKañ 0r   c                ól   € V '       g   R# \        V4      pVf   V\        4       ,           p\        W4      # )a  Match a catalog name or repo URL (``.git``/trailing-slash insensitive) against the kill list.

The in-tree list and the live-fetched list are UNIONED: a removal published after this checkout
shipped must still block, and a stale live cache must not un-block an in-tree removal.
N)r­   Úlive_removed_listÚmatch_removed)rÒ   rœ   r¦   s   && r   Úfind_removedr×   	  s3   € ÷ ÙÜ Ó,€GØÒØÔ-Ó/Õ/ˆÜ˜Ó/Ð/r   c               ó   € V ^8„  d   QhRR/# ©r   r   r—   r   )r   s   "r   r   r     s   € ÷ 5ñ 5Ð"4ñ 5r   c                 ó4   € \        4       \        4       ,           # )uî   The full kill list (in-tree UNION live) in one resolution. Callers that match many candidates
â€” e.g. a plugins-hub rebuild annotating every installed plugin â€” resolve the list once instead
of paying a live-catalog fetch per candidate.)r­   rÕ   r   r   r   Úresolved_removed_entriesrÛ     s   € ô ÓÔ!2Ó!4Õ4Ð4r   c               ó   € V ^8„  d   QhRR/# rÙ   r   )r   s   "r   r   r     s   € ÷ Kñ KÐ 2ñ Kr   c                 óŽ   € \        \        4       4      ;'       g    / p \        4       \        V P	                  R4      4      ,           # )u¼   In-tree list UNION the last fetched live copy, with NO network round-trip â€” for the load-time and
``enable`` checks that run in every process and must never block on a dead catalog host.r«   )Ú_stale_live_cacheÚ_live_cache_pathr­   rš   rz   )Úcacheds    r   Úcached_removed_entriesrá     s7   € ô Ô/Ó1Ó2×8Ð8°b€FÜÓÔ!3°F·J±J¸yÓ4IÓ!JÕJÐJr   c               ó$   € V ^8„  d   QhRRRRRR/# )r   Ú	candidater   r¦   r—   r   rÓ   r   )r   s   "r   r   r   %  s$   € ÷ ñ ØðØ/ðàñr   c                óæ   € V '       g   R# V P                  4       p\        V4      pV FE  pW$P                  8X  g1   VP                  '       g   K'  V\        VP                  4      8X  g   KC  Vu # 	  R# )zXOne candidate against a pre-resolved kill list: exact name or normalized repo URL match.N)r{   rÐ   r(   r)   )rã   r¦   rÎ   Ú	text_repor§   s   &&   r   rÖ   rÖ   %  sW   € ÷ ÙØ�?‰?Ó€DÜ Ó%€IÛˆØ—:‘:ÔØ�J�JŠJ˜9¬¸¿
¹
Ó(CÖCàŠLñ	 ñ
 r   c               ó   € V ^8„  d   QhRR/# r`   r   )r   s   "r   r   r   7  s   € ÷ ?ñ ?˜$ñ ?r   c                 ó8   € ^ RI Hp  V ! 4       R,          R,          # )r   ©Úget_hermes_homeÚcacheúplugin-catalog.json)Úhermes_constantsré   rè   s    r   rß   rß   7  s   € Ý0ÙÓ˜wÕ&Ð)>Õ>Ð>r   c               ó    € V ^8„  d   QhRRRR/# )r   Úhomer   r   ÚNoner   )r   s   "r   r   r   <  s   € ÷ ^ñ ^¨ð ^°$ñ ^r   c                ó¸   €  \        V 4      R,          R,          P                  RR7       R#   \         d"   p\        P	                  RY4        Rp?R# Rp?ii ; i)uh  Best-effort removal of the cached live catalog under *home* (any profile's home).

``hermes update`` drops it for every profile after the checkout changes: a snapshot fetched
before the bump would otherwise out-vote the newer in-tree catalog (pins the update just
changed, entries it just added) for the rest of :data:`LIVE_CATALOG_TTL_SECONDS` (#119340).
The next :func:`fetch_live_catalog` re-fetches the published doc, or falls back to the
in-tree catalog while the network is down â€” both newer than what was deleted. Safe when the
cache is absent (first run, other profiles that never opened the plugins hub).
rê   rë   T)Ú
missing_okz:Plugin catalog: could not drop the live cache under %s: %sN)r   Úunlinkr’   rx   Údebug)rî   r“   s   & r   Úinvalidate_live_cache_for_homerô   <  sM   € ð^Ü	ˆd‹�gÕ	Ð 5Õ	5×=Ñ=ÈÐ=ÖNøÜô ^Ü�‰ÐQÐSW×]Ò]ûð^ús   ‚)- ­A¸AÁAg        c               ó    € V ^8„  d   QhRRRR/# )r   rê   r   r   úOptional[dict[str, Any]]r   )r   s   "r   r   r   R  s   € ÷ ñ ˜Tð Ð&>ñ r   c                ó2  €  V P                  4       '       g   R# \        P                  ! V P                  RR7      4      p\        P                  ! 4       V P                  4       P                  ,
          \        8”  d	   / VCR. /CpV#   \         d     R# i ; i)uL  A previously fetched copy still beats the in-tree one when the network is down â€” for
:data:`LIVE_CATALOG_MAX_STALE_SECONDS`. Past that its pins may trail the checkout's own catalog
(a 90-day-old cache outranked a freshly updated in-tree pin), so the entries are dropped and the
caller falls back to in-tree; the removals are kept.NrŒ   r�   r¦   )	r¬   ÚjsonÚloadsr‘   ÚtimeÚstatÚst_mtimeÚLIVE_CATALOG_MAX_STALE_SECONDSr’   )rê   rq   s   & r   rÞ   rÞ   R  sv   € ð
Ø�}‰}�ŠÙÜ�zŠz˜%Ÿ/™/°;˜/Ó?Ó@ˆÜ�9Š9‹;˜Ÿ™›×.Ñ.Õ.Ô1OÔOØ*�dÐ*˜I rÑ*ˆDØˆøÜô Úðús   ‚B šA,B ÂBÂBÚforceFc               ó    € V ^8„  d   QhRRRR/# )r   rþ   r   r   rö   r   )r   s   "r   r   r   b  s   € ÷ #(ñ #( ð #(Ð2Jñ #(r   c                ó„  € \        4       p V '       gz   VP                  4       '       dd   \        P                  ! 4       VP                  4       P                  ,
          \
        8  d'   \        P                  ! VP                  RR7      4      # T '       g*   \        P                  ! 4       \        8  d   \        T4      #  ^ RIp^ RIHp ^ RIHp TP'                  \(        \*        RR7      pTP-                  4        \/        TP0                  4      \2        8”  d   \5        R	4      hTP                  4       p\7        T\8        4      '       d&   \7        TP'                  R
4      \:        4      '       g   \5        R4      hT! TP<                  4       T! T\        P>                  ! T4      TP@                   R2R7       T#   \         d"   p\        P                  RY4        Rp?ELTRp?ii ; i  \         dL   p\        P                  RT4       \        P                  ! 4       \B        ,           s\        T4      u Rp?# Rp?ii ; i)u˜  The published ``plugin-catalog.json`` (``{"entries": [...], "removed": [...]}``), cached under
``HERMES_HOME/cache`` for :data:`LIVE_CATALOG_TTL_SECONDS`. ``None`` on ANY failure â€” callers fall
back to the in-tree catalog. A failed network attempt is remembered for
:data:`LIVE_CATALOG_FAILURE_TTL_SECONDS` so a dead host costs one timeout per TTL window, not one
per call (``force`` bypasses both caches).rŒ   r�   z,Plugin catalog: unreadable live cache %s: %sN)Úmkdir_under_hermes_home)Úatomic_write_textT)ÚtimeoutÚfollow_redirectszlive catalog payload too larger¦   zunexpected live catalog payloadz.tmp-)Ú
tmp_prefixz%Plugin catalog: live fetch failed: %s)"rß   r¬   rú   rû   rü   ÚLIVE_CATALOG_TTL_SECONDSrø   rù   r‘   r’   rx   ró   Ú_live_fetch_failed_untilrÞ   Úhttpxrì   r  Úutilsr  rz   ÚLIVE_CATALOG_URLÚ_REQUEST_TIMEOUTÚraise_for_statusr„   ÚcontentÚ_MAX_LIVE_BYTESÚ
ValueErrorrk   rw   r;   re   Údumpsr(   Ú LIVE_CATALOG_FAILURE_TTL_SECONDS)rþ   rê   r“   r  r  r  Úresprq   s   $       r   Úfetch_live_catalogr  b  s“  € ô Ó€EðQß˜Ÿ™Ÿš¬T¯YªY«[¸5¿:¹:»<×;PÑ;PÕ-PÔSkÔ-kÜ—:’:˜eŸo™o°{˜oÓCÓDÐD÷ ”T—Y’Y“[Ô#;Ô;Ü  Ó'Ð'ð(ÛÝ<Ý+à�y‰yÔ)Ô3CÐVZˆyÓ[ˆØ×ÑÔÜˆt�|‰|ÓœÔ.ÜÐ=Ó>Ð>Ø�y‰y‹{ˆÜ˜$¤×%Ò%¬Z¸¿¹ÀÓ8KÌT×-RÒ-RÜÐ>Ó?Ð?Ù §¡Ô-ñ 	˜%¤§¢¨DÓ!1ÀÇÁÀÈEÐ>RÕSØˆøô) ô QÜ�‰ÐCÀU×PÒPûðQûô* ô (Ü�‰Ð<¸cÔBÜ#'§9¢9£;Ô1QÕ#QÐ Ü  Ó'Õ'ûð(ús=   ŒF: ªA"F: Â?C:G) Æ:G&ÇG!Ç!G&Ç)H?Ç4A H:È4H?È:H?úOptional[float]Ú_in_tree_catalog_timec               ó   € V ^8„  d   QhRR/# ©r   r   r  r   )r   s   "r   r   r   ‹  s   € ÷  ñ  ˜oñ  r   c            
     óx  € \         R8w  d   \         # \        4       P                  p RpV R,          P                  4       '       dF    ^ RIHp V! RR\        V 4      RRRR	R
.^
R7      pV'       d   \        V4      MRpVf   \        4       pVs V#   \         d!   p\        P                  RT4        Rp?L8Rp?ii ; i)uë  Commit time (epoch) of the last change to this checkout's ``plugin-catalog/``, or ``None`` when
the install is not a git checkout (a release/pip install cannot be newer than the published doc).
On a git checkout whose path history is unreadable without network â€” the treeless ``tree:0`` layout
``hermes update`` produces â€” the newest checked-out catalog file's mtime stands in for it, so a
freshly updated checkout still outranks a doc fetched before the bump. Resolved once per process.NrÈ   )Úbounded_git_probeÚgitz-CÚlogz-1z--format=%ctz--rb   )r  z6Plugin catalog: could not date the in-tree catalog: %sç      ð¿)r  rf   re   ÚexistsÚhermes_cli._subprocess_compatr  r   rm   r’   rx   ró   Ú_catalog_worktree_mtime)r¥   Úresolvedr  Úoutr“   s        r   Úin_tree_catalog_timer"  ‹  s¼   € ô  Ô$Ü$Ð$ÜÓ×#Ñ#€DØ $€HØˆv�×Ñ×Òð	XÝGñ $Ø˜œc $›i¨°°nÀdÐL\Ð]ØôˆC÷ &)”u˜S”z¨dˆHð Òô /Ó0ˆHØ$ÐØ€Oøô ô 	XÜ�L‰LÐQÐSV×WÑWûð	Xús   Á6B ÂB9ÂB4Â4B9c               ó   € V ^8„  d   QhRR/# r  r   )r   s   "r   r   r   ®  s   € ÷ )ñ ) ñ )r   c                 ó
  €  \        4       P                  R4       U u. uF4  q P                  4       '       g   K  V P                  4       P                  NK6  	  pp T'       d   \        T4      # R# u up i   \
         d     R# i ; i)z¾Newest mtime under the checkout's ``plugin-catalog/``: a no-network freshness signal for clones
whose path history is unreachable (treeless or offline). ``None`` when nothing is checked out.Ú*N)rf   Úrglobr¬   rû   rü   ÚOSErrorÚmax)ÚpÚtimess     r   r  r  ®  sk   € ðÜ,;Ó,=×,CÑ,CÀCÔ,HÓXÑ,H qÏIÉIÏKÔ"�—‘“×"Ô"Ñ,HˆÐX÷ Œ3ˆu‹:Ð( DÐ(ùò YøÜô Úðús'   ‚A3 �A.¹A.ÁA3 Á.A3 Á3BÂBc               ó    € V ^8„  d   QhRRRR/# )r   rq   rY   r   r  r   )r   s   "r   r   r   ¸  s   € ÷ 	ñ 	˜~ð 	°/ñ 	r   c                óH  € V P                  R 4      p\        V\        4      '       d	   V'       g   R#  ^ RIHpHp VP                  V4      pVP                  '       d   VP                  4       # VP                  \        R7      P                  4       #   \         d     R# i ; i)Úgenerated_atN)ÚdatetimeÚtimezone)Útzinfo)rz   rk   r   r.  r/  Úfromisoformatr0  Úreplacer
   Ú	timestampr  )rq   rh   r.  r/  Úparseds   &    r   Ú_live_generated_timer5  ¸  s|   € Ø
�(‰(�>Ó
"€CÜ�cœ3×Ò§sÙðß/Ø×'Ñ'¨Ó,ˆØ Ÿ-Ÿ-˜-�×RÑRÓTÐT¨V¯^©^Ä3¨^Ó-G×RÑRÓTÐTøÜô Úðús   ³*B ÁB Á.#B ÂB!Â B!c               ó(   € V ^8„  d   QhRRRRRRRR/# )r   Útreer=   ÚliveÚtree_is_newerzOptional[bool]r   r   r   )r   s   "r   r   r   Ä  s,   € ÷ ñ Ð 2ð Ð:Lð Ð]kð Ðptñ r   c                ó  € V P                   VP                   8X  d   R# Ve   V# V P                  '       d?   VP                  '       d-    ^ RIHp V! V P                  4      V! VP                  4      8„  # R#   \         d     R# i ; i)aS  For one entry present in both sources with a different pin: the newer catalog wins. Newer is
decided by the checkout's catalog commit time vs the doc's ``generated_at`` when both resolve;
otherwise by the entries' ``version`` labels when both parse; otherwise the live doc wins (a release
install's in-tree copy is frozen at release time).F)ÚVersion)r>   rH   Úpackaging.versionr;  r’   )r7  r8  r9  r;  s   &&& r   Ú_prefer_in_tree_entryr=  Ä  sr   € ð
 ‡x�x�4—8‘8ÔÙØÒ ØÐØ‡|‡|€|˜ŸŸ˜ð	Ý1Ù˜4Ÿ<™<Ó(©7°4·<±<Ó+@Ñ@Ð@ñ øô ô 	Úð	ús   Á	*A6 Á6BÂBc               ó   € V ^8„  d   QhRR/# )r   r   rž   r   )r   s   "r   r   r   Ö  s   € ÷ ñ Ð3ñ r   c            
     óV  € \        4       p V f   \        4       # \        V R,          4       UUu. uF"  w  r\        V\         RV 24      ;pf   K   VNK$  	  pppV'       g   \        4       # \        4        Uu/ uF  q3P
                  VbK  	  pp\        V 4      \        4       rvVe	   Ve   Wv8„  MRpV R,           Uu/ uF6  p\        V\        4      '       g   K  \        VP                  R4      4      VbK8  	  p	pV Uu. uF�  pVP
                  V9   d5   \        WSP
                  ,          W84      '       d   WSP
                  ,          MG\        Y5P                  VP
                  4      V	P                  VP
                  4      ;'       g    / 4      NK’  	  up# u uppi u upi u upi u upi )u(  Entries from the live (or cached) catalog, else the in-tree catalog. When both name an entry at
different pins the NEWER source supplies it â€” right after ``hermes update`` bumps an in-tree pin,
a cache fetched before the bump must not re-install the old one (see :func:`_prefer_in_tree_entry`).Nr¦   rT   r(   )r  r¨   Ú	enumeraterˆ   r
  r(   r5  r"  rk   rw   r   rz   r=  Ú_with_curated_fields)
rq   Úirh   r´   r¦   Úin_treeÚlive_tÚtree_tr9  Úraw_by_names
             r   Úload_catalog_liverG  Ö  sv  € ô Ó€DØ‚|Ü‹~ÐÜ(¨¨i­Ô9ô YÑ9‘V�QÜ*¨3Ô3CÐ2DÀAÀaÀSÐ0IÓJÐJ�1÷ ˆqÑ9€Gñ YçÜ‹~ÐÜ".¤.Ó1¡.˜Q�v‰v�qŠy¡.€GÐ1Ü)¨$Ó/Ô1EÓ1GˆFØ*0Ò*<ÀÒAS�V’_ÐZ^€MØ8<¸Y¾Óa¹°Ì:ÐVYÔ[_×K`Ô,”3�s—w‘w˜v“Ó'¨Ò,¹€KÐañ óá�ð  !Ÿv™v¨Ô0Ô5JÈ7×SYÑSYÍ?Ð\]×5mÒ5mˆG—F‘FŽOÜ% a¯©°Q·V±VÓ)<¸k¿o¹oÈaÏfÉfÓ>U×>[Ð>[ÐY[Ó\ò]áñð ùóYùò 2ùò bùòs*   ®FÁFÁ7FÂ;F!ÃF!Ã=B
F&ÆF&c               ó(   € V ^8„  d   QhRRRRRRRR/# )r   r8  r=   r7  rs   rh   rY   r   r   )r   s   "r   r   r   ð  s2   € ÷ Eñ EÐ1ð EÐ9Uð EÐ\jð EØ0ñEr   c                óÞ   € Ve   VP                   V P                   8w  d   V # \         Uu/ uF  q3V9  g   K  V\        W4      bK  	  ppV'       d   \        P                  ! V 3/ VB # T # u upi rj   )r>   Ú_CURATED_FIELDSÚgetattrÚdataclassesr2  )r8  r7  rh   ÚkeyÚmissings   &&&  r   rA  rA  ð  sd   € à‚|�t—x‘x 4§8¡8Ô+ØˆÝ2AÓT±/¨3ÐPSÁ^Ô&ˆs”G˜DÓ&Ò&±/€GÐTß3:Œ;×Ò˜tÑ/ wÑ/ÐDÀÐDùò Us
   ªA*·A*c               ó   € V ^8„  d   QhRR/# rÙ   r   )r   s   "r   r   r   ø  s   € ÷ Cñ CÐ-ñ Cr   c                 ó^   € \        4       p V '       d   \        V P                  R 4      4      # . # )r«   )r  rš   rz   )rq   s    r   rÕ   rÕ   ø  s&   € ÜÓ€Dß6:Ô˜dŸh™h yÓ1Ó2ÐBÀÐBr   c               ó    € V ^8„  d   QhRRRR/# )r   r(   r   r   rs   r   )r   s   "r   r   r   ý  s   € ÷ Jñ J ð JÐ)Eñ Jr   c                ó@   a € \        V 3R  l\        4        4       R4      # )c              3  óL   <"  € T F  qP                   S8X  g   K  Vx € K  	  R # 5irj   r±   r²   s   & €r   rµ   Ú)get_live_catalog_entry.<locals>.<genexpr>þ  s   øé € ÐBÑ/�q·6±6¸T±>—’Ó/ùr·   N)r¸   rG  r±   s   fr   Úget_live_catalog_entryrU  ý  s   ø€ ÜÔBÔ-Ô/ÓBÀDÓIÐIr   c               ó    € V ^8„  d   QhRRRR/# )r   r§   r=   r   r   r   )r   s   "r   r   r     s   € ÷ ñ Ð$6ð ¸3ñ r   c           	     ó‚  € V P                   pRVP                  3RVP                  3RVP                  3RVP                  33 UUu. uF%  w  r#V'       g   K  V RRP                  V4       2NK'  	  pppV P                   RV P                   RV P                   R	2.pV P                  '       d   VP                  V P                  4       TP                  R
V'       d   RP                  V4      MR R24       V P                  '       d/   VP                  RRP                  V P                  4       R24       V P                  '       d    VP                  RV P                   R24       V P                  '       d/   VP                  RRP                  V P                  4       R24       RP                  V4      # u uppi )zIOne paragraph shown at install/enable prompts: what the user is granting.zregisters tool(s):zhook(s):zmiddleware:zrequires env var(s):Ú z, z (z, maintained by ru   zThis plugin z; z1declares no tools, hooks, middleware, or env varsÚ.zPlatforms: zRequires Hermes zKnown issues: )rO   r7   r8   r9   r:   r�   r(   rB   r@   r?   r¤   rL   rE   rP   )r§   r[   rr   Úitemsr#   Úbitss   &     r   Úentry_capability_summaryr\    s—  € à×Ñ€Dà	˜t×2Ñ2Ð3°jÀ$×BUÑBUÐ5VØ	˜×0Ñ0Ð1Ð4JÈD×L]ÑL]Ð3^ñ@`ô jñ @`©|¨uächô +�ˆw�a˜Ÿ	™	 %Ó(Ð)Ó*ñ @`€Eñ jð �z‰zˆl˜"˜UŸZ™Z˜LÐ(8¸×9IÑ9IÐ8JÈ!ÐLÐM€DØ××ÐØ�‰�E×%Ñ%Ô&Ø‡K�K�,·5˜tŸy™y¨Ô/Ð>qÐrÐrsÐtÔuØ‡‡€Ø�‰�k $§)¡)¨E¯O©OÓ"<Ð!=¸QÐ?Ô@Ø××ÐØ�‰Ð& u×'<Ñ'<Ð&=¸QÐ?Ô@Ø××Ðð 	�‰�n T§Y¡Y¨u×/AÑ/AÓ%BÐ$CÀ1ÐEÔFØ�8‰8�D‹>Ðùó!js   ÁF;ÁF;)ÚofficialÚverifiedrA   )	rC   ÚmemoryÚplatformÚwebÚtoolsÚvoiceÚ
automationÚmodelsÚgenerali`T  i€Q i    )zraw.githubusercontent.comz
github.comrj   r  )rN   rM   )LÚ__conditional_annotations__Ú__doc__Ú
__future__r   rL  rø   ÚloggingÚrerú   r   r   Úpathlibr   Útypingr   r   r   r	   Úhermes_yamlr�   r.  r
   Ú	getLoggerr,   rx   r€   r‚   r
  r  rý   r  r  r  Úcompiler   rƒ   r    r"   r%   r|   r'   r3   r=   rf   ro   rˆ   r”   rš   r¨   r­   r¹   rÂ   rÅ   rÉ   rÐ   r×   rÛ   rá   rÖ   rß   rô   r  rÞ   r  r  r0   r"  r  r5  r=  rG  rJ  rA  rÕ   rU  r\  )rg  s   @r   Ú<module>rq     sÎ  øðôõ #ã Û Û Û 	Û ß (Ý ß ,Ó ,ã Ý à	×	Ò	˜8Ó	$€à5€ð sÐ ØWÐ Ø&Ð à!-Ð Ø#'Ð  ØÐ Ø!€à
�*Š*Ð&Ó
'€Ø�jŠjÐ>Ó?€ð :€Ø,Ð õpð
 �:Š:Ð+Ó,€ð ÷ð ó ðð ÷:ð :ó ð:ð ÷(
ð (
ó ð(
õVEõfõ0õfõD÷÷"U÷Põeõ1ð �jŠjÐAÓB€õ.÷&0õ5õKõõ$?õ
^ð& Ð õð #(¨÷ #(ðL *.Ð �Ó -õ õF)õ	õõ$ð. *€õEõCõ
J÷r   