+
    „WÝjnN  ã                   ó   € R t ^ RIt^ RIt^ RIHt ^ RIHtHt ^ RIH	t	H
t
Ht ^ RIHt ^ RIHtHt ^ RIHt ^ RIHt ^ R	IHtHtHtHtHt ^ R
IHtHt ^ RIHtH t H!t!H"t"H#t# ]PH                  ! R4      t%]	! 4       t&]! R4      t']! R4      t(]! RR4      t)]! RR4      t*]! RR4      t+]! R4      t,RuR R llt-]&P]                  R4      RuR R ll4       t/]&Pa                  R4      RuR R ll4       t1Rt2]3! 0 Rvm4      t4]&P]                  R4      RuR R  ll4       t5]&Pa                  R4      RuR! R" ll4       t6]&P]                  R#4      RuR$ R% ll4       t7]&P]                  R&4      RuR' R( ll4       t8]&P]                  R)4      RuR* R+ ll4       t9R,Rw/R- R. llt:]&P]                  R/4      R0 R1 l4       t;R2 R3 lt<]&P{                  R44      R5 R6 l4       t>R7 R8 lt?R,Rw/R9 R: llt@]&P{                  R;4      R< R= l4       tA]&P{                  R>4      R? R@ l4       tB]&P{                  RA4      RB RC l4       tC]&P‰                  RD4      RE RF l4       tE]&P{                  RG4      RH RI l4       tF]&Pa                  RJ4      RuRK RL ll4       tG]&P{                  RM4      RuRN RO ll4       tH/ RPRQbRRRQbRSRTbRURVbRWRXbRYRZbR[R\bR]R^bR_R^bR`RabRbRcbRdRebRfRgbRhRibRjRkbRlRmbRnRVbtI]&P]                  Ro4      Rp Rq l4       tJ]&P]                  Rr4      RuRs Rt ll4       tKR# )xa   Dashboard theme/font and dashboard-plugin (discovery, hub, install/enable, asset serving) routes.

Extracted from ``hermes_cli.web_server``; helpers/state that tests monkeypatch on
``web_server`` stay there and are resolved late at call time (cycle-safe).
N)ÚPath)ÚCallableÚOptional)Ú	APIRouterÚHTTPExceptionÚRequest)ÚFileResponse)Ú	LateStateÚlate)Úcfg_get©Úconfig_scoped_to_thread)Ú_BUILTIN_DASHBOARD_THEMESÚ_discover_user_themesÚ_invalidate_plugins_hub_cacheÚ_merged_plugins_hubÚ_plugin_consent_withheld)Ú_normalize_memory_provider_nameÚ_require_memory_provider_ready)ÚFontSetBodyÚThemeSetBodyÚ_AgentPluginInstallBodyÚ_PluginProvidersPutBodyÚ_PluginVisibilityBodyzhermes_cli.web_serverÚ_get_dashboard_pluginsÚ_require_tokenÚload_configzhermes_cli.configÚsave_configÚ_config_profile_scopezhermes_cli.web_server_profilesÚ_CONFIG_MUTATION_LOCKc                óJ   € V ^8„  d   QhR\         R\        \         ,          RR/# )é   ÚkeyÚprofileÚreturnN©Ústrr   )Úformats   "ÚWC:\Users\johnn\AppData\Local\hermes\hermes-agent\hermes_cli\web_routers\dashboard_ui.pyÚ__annotate__r)   *   s%   € ÷ ñ œCð ´¼#µð È$ñ ó    c           	     ó  € \        V4      ;_uu_ 4        \        ;_uu_ 4        \        4       pRV9  d   / VR&   WR,          V &   \        V4       RRR4       RRR4       R#   + '       g   i     L; i  + '       g   i     R# ; i)zVWrite ``dashboard.<key>`` to the profile's config.yaml under the config mutation lock.Ú	dashboardN)r   r   r   r   )r"   Úvaluer#   Úconfigs   &&& r(   Ú_set_dashboard_keyr/   *   s]   € ä	˜w×	'Õ	'×)>Ö)>Ü“ˆØ˜fÔ$Ø"$ˆF�;ÑØ#(ˆ{Õ˜CÑ Ü�FÔ÷ *?×	'Ñ	'×)>×)>ú×	'×	'Ð	'ús"   ”A5£-A"	ÁA5Á"A2Á-A5Á5B	z/api/dashboard/themesc                ó:   € V ^8„  d   QhR\         \        ,          /# ©r!   r#   ©r   r&   )r'   s   "r(   r)   r)   5   s   € ÷ 8ñ 8¬´­ñ 8r*   c              ƒ  ó:   "  € R p\        W4      G Rj  x€L
 #  L5i)zìAvailable themes + the active one. Built-ins ship name/label/description only
(the frontend owns their definitions in `web/src/themes/presets.ts`); user themes
from `~/.hermes/dashboard-themes/*.yaml` ship their normalised `definition`.c                  ód  € \        4       p \        V R RRR7      p\        \        4      pV Uu0 uF  q3R,          kK  	  pp\	        4        FY  pVR,          V9   d   K  VP                  RVR,          RVR,          RVR,          RV/4       VP                  VR,          4       K[  	  RVR	V/# u upi )
r,   ÚthemeÚdefault©r6   ÚnameÚlabelÚdescriptionÚ
definitionÚthemesÚactive)r   r   Úlistr   r   ÚappendÚadd)r.   r=   r<   ÚtÚseens        r(   Ú_runÚ"get_dashboard_themes.<locals>._run9   s¬   € Ü“ˆÜ˜ ¨g¸yÔIˆÜÔ/Ó0ˆÙ#)Ó*¡6˜a�&—	�	¡6ˆÐ*Ü&Ö(ˆAØ��y˜DÔ ÙØ�M‰M˜6 1 V¥9¨g°q¸µzÀ=ÐRSÐTaÕRbÐdpÐrsÐtÔuØ�H‰H�Q�v•YÖñ	 )ð
 ˜& (¨FÐ3Ð3ùò +s   ­B-Nr   ©r#   rC   s   & r(   Úget_dashboard_themesrF   4   s   é € ò

4ô )¨Ó7×7Ð7Ñ7ùó   ‚”•z/api/dashboard/themec                óF   € V ^8„  d   QhR\         R\        \        ,          /# ©r!   Úbodyr#   )r   r   r&   )r'   s   "r(   r)   r)   I   s   € ÷ ,ñ ,¤Lð ,¼8ÄC½=ñ ,r*   c              ƒ  óŒ   "  € \         P                  ! \        RV P                  V4      G Rj  x€L
  RRRV P                  /#  L5i)z9Set the active dashboard theme (persists to config.yaml).r5   NÚokT)ÚasyncioÚ	to_threadr/   r8   )rJ   r#   s   &&r(   Úset_dashboard_themerO   H   s?   é € ô ×
Ò
Ô.°¸¿¹ÀGÓ
L×LÐLØ�$˜ §¡Ð+Ð+ñ Mùs   ‚+A­A®Ar5   z/api/dashboard/fontc                ó:   € V ^8„  d   QhR\         \        ,          /# r1   r2   )r'   s   "r(   r)   r)   \   s   € ÷ 8ñ 8¤h¬s¥mñ 8r*   c              ƒ  ó:   "  € R p\        W4      G Rj  x€L
 #  L5i)zEReturn the active font override (``"theme"`` = use the theme's font).c                  ód   € \        \        4       R R\        R7      p RV \        9   d   V /# \        /# )r,   Úfontr7   )r   r   Ú_FONT_DEFAULT_IDÚ_FONT_CHOICES)rS   s    r(   rC   Ú get_dashboard_font.<locals>._run^   s0   € Ü”{“} k°6ÔCSÔTˆØ ¬Ô 5˜ÐLÐLÔ;KÐLÐLr*   Nr   rE   s   & r(   Úget_dashboard_fontrW   [   s   é € òMô )¨Ó7×7Ð7Ñ7ùrG   c                óF   € V ^8„  d   QhR\         R\        \        ,          /# rI   )r   r   r&   )r'   s   "r(   r)   r)   f   s   € ÷ &ñ &¤;ð &¼Ä#½ñ &r*   c              ƒ  ó°   "  € V P                   \        9   d   V P                   M\        p\        P                  ! \
        RW!4      G Rj  x€L
  RRRV/#  L
5i)z€Set the font override (config.yaml). Unknown ids coerce to ``"theme"`` rather than
400 so a stale client can't wedge the picker.rS   NrL   T)rS   rU   rT   rM   rN   r/   )rJ   r#   rS   s   && r(   Úset_dashboard_fontrZ   e   sL   é € ð Ÿ	™	¤]Ô2ˆ4�9Š9Ô8H€DÜ
×
Ò
Ô.°¸Ó
F×FÐFØ�$˜ Ð%Ð%ñ Gùs   ‚AAÁ	AÁ
Az/api/dashboard/pluginsc                ó:   € V ^8„  d   QhR\         \        ,          /# r1   r2   )r'   s   "r(   r)   r)   o   s   € ÷ 
Cñ 
C¬´#­ñ 
Cr*   c              ƒ  óò   "  € R p\        W4      G Rj  x€L
  UUUu. uF@  pVP                  4        UUu/ uF   w  r4VP                  R4      '       d   K  W4bK"  	  uppNKB  	  uppp#  LSu uppi u upppi 5i)zPReturn discovered dashboard plugins (excludes user-hidden and non-enabled ones).c                  óÚ   € \        \        4       R R. R7      ;'       g    . p \        4        Uu. uF1  pVP                  RR4      V 9  g   K  \	        V4      '       d   K/  VNK3  	  up# u upi )r,   Úhidden_pluginsr7   r8   Ú )r   r   r   Úgetr   )ÚhiddenÚps     r(   rC   Ú#get_dashboard_plugins.<locals>._runq   sn   € Üœ{›}¨kÐ;KÐUWÔX×^Ð^Ð\^ˆä1Ô3ó XÑ3�aØ—5‘5˜ Ó$¨FÑ2ô Ü;SÐTU×;V÷ �Ñ3ñ Xð 	Xùò Xs   ®A(ÁA(ÁA(NÚ_)r   ÚitemsÚ
startswith)r#   rC   rb   ÚkÚvs   &    r(   Úget_dashboard_pluginsri   n   sp   é € òXô 3°7ÓA×AÐAõCÙA�ð  Ÿg™gœiÔA™i‘d�a¨q¯|©|¸C×/@ŒTˆQŠT™iÕAÙAóCð CÙAùó Bùô Cùs7   ‚A7”A(•A7�A0µA*ÁA*ÁA0Á#A7Á*A0Á0A7z/api/dashboard/plugins/rescanc                ó:   € V ^8„  d   QhR\         \        ,          /# r1   r2   )r'   s   "r(   r)   r)   }   s   € ÷ /ñ /¬H´S­Mñ /r*   c              ƒ  óV   "  € \        V R 4      G Rj  x€L
 pRRR\        V4      /#  L5i)zQForce re-scan of the selected profile's dashboard plugins (its own cache, PLG-3).c                  ó   € \        R R7      # )T©Úforce_rescan)r   © r*   r(   Ú<lambda>Ú*rescan_dashboard_plugins.<locals>.<lambda>   s   € Ô=SÐaeÕ=fr*   NrL   TÚcount)r   Úlen)r#   Úpluginss   & r(   Úrescan_dashboard_pluginsru   |   s0   é € ô ,¨GÑ5fÓg×g€GØ�$˜¤ W£Ð.Ð.ñ hùs   ‚)“'”)z/api/dashboard/plugins/hubc                óF   € V ^8„  d   QhR\         R\        \        ,          /# )r!   Úrequestr#   )r   r   r&   )r'   s   "r(   r)   r)   „   s"   € ÷ 	]ñ 	]¤7ð 	]´X¼cµ]ñ 	]r*   c              ƒ  óÚ   "  € \        V 4        \        V\        4      G Rj  x€L
 #  L  \         d    h \         d*   p\
        P                  RT4       \        RRR7      ThRp?ii ; i5i)zIUnified agent plugins + dashboard extension metadata (session protected).Nzplugins/hub failed: %séô  zFailed to build plugins hub.©Ústatus_codeÚdetail)r   r   r   r   Ú	ExceptionÚ_logÚwarning)rw   r#   Úexcs   && r(   Úget_plugins_hubr�   ƒ   se   é € ô �7Ôð]Ü,¨WÔ6IÓJ×JÐJÑJøÜô ØÜô ]Ü�‰Ð-¨sÔ3Ü¨Ð4RÔSÐY\Ð\ûð]üs5   ‚A+�) ¢'£) ¦A+§) ©A(¾A(¿$A#Á#A(Á(A+Úclient_decidesc          
      ón   € V ^8„  d   QhR\         R\        R\        R\        \        R3,          R\         /# )r!   ÚresultÚfallback_errorÚrescanr‚   .r$   )Údictr&   ÚboolÚtuple)r'   s   "r(   r)   r)   �   s9   € ÷ ñ œ4ð ´ð Äð Ü#(¬¨c¨¥?ðÜOSñr*   c               óB  a € \         ;QJ d    V 3R lV 4       F  '       g   K   RM	  RM! V 3R lV 4       4      '       d   S # S P                  R4      '       g'   \        RS P                  R4      ;'       g    TR7      hV'       d   \        RR7       \	        4        S # )	a9  Common tail of agent-plugin mutations: 400 on ``ok=False``, then invalidate caches
(rescanning discovery when files changed on disk). An answer flagged by one of *client_decides*
is not a failure: nothing changed, the client shows it (the capability delta, the scan findings)
and retries with the user's decision.c              3   óF   <"  € T F  pSP                  V4      x € K  	  R # 5i©N)r`   )Ú.0Úflagr„   s   & €r(   Ú	<genexpr>Ú!_plugin_action.<locals>.<genexpr>–   s   øé € Ð
7© ˆ6�:‰:�d×Ð«ùs   ƒ!TFrL   é�  Úerrorrz   rm   )Úanyr`   r   r   r   )r„   r…   r†   r‚   s   f&$$r(   Ú_plugin_actionr”   �   sn   ø€ ÷ ƒsÔ
7©Ó
7‡s‡s‚sÔ
7©Ó
7×7Ò7ØˆØ�:‰:�d×ÒÜ¨°F·J±J¸wÓ4G×4YÐ4YÈ>ÔZÐZßÜ¨DÕ1Ü!Ô#Ø€Mr*   z/api/dashboard/plugins/catalogc                ó$   € V ^8„  d   QhR\         /# ©r!   rw   ©r   )r'   s   "r(   r)   r)   ¡   s   € ÷ añ a¤wñ ar*   c              ƒ  óÖ   "  € \        V 4       R p \        P                  ! V4      G Rj  x€L
 #  L  \         d*   p\        P                  RT4       \        RRR7      ThRp?ii ; i5i)zGCurated plugin catalog merged with installed state (session protected).c            	      óþ   € ^ RI Hp HpHp ^ RIHp ^ RIHp V! 4       V! 4       re/ pV ! 4        FA  w  r‰r«rÍW�0R0,
          pRVRV! WåV4      /pTP                  V Uu/ uF  pVVbK  	  up4       KC  	  V! V4      # u upi )é    )Ú_discover_all_pluginsÚ_get_disabled_setÚ_get_enabled_set)Úinstalled_catalog_state)Ú_plugin_runtime_statusr_   ÚdirÚruntime_status)	Úhermes_cli.plugins_cmdr›   rœ   r�   Úhermes_cli.plugins_cmd_catalogrž   Úhermes_cli.web_server_dashboardrŸ   Úupdate)r›   rœ   r�   rž   rŸ   ÚenabledÚdisabledÚ	installedr8   Ú_vÚ_dÚ_sÚdir_strr"   ÚaliasesÚinfoÚaliass                    r(   rC   Ú!get_plugins_catalog.<locals>._run¥   s�   € ßeÑeÝJÝJÙ,Ó.Ñ0AÓ0C�Øˆ	Ù.CÖ.EÑ*ˆD�b˜gØ�k R DÕ(ˆGØ˜7Ð$4Ñ6LÈWÐ_gÓ6hÐiˆDØ×Ñ±wÓ?±w¨e˜e Tšk±wÑ?Ö@ñ /Fñ ' yÓ1Ð1ùò @s   ÁA:
Nzplugins/catalog failed: %sry   z Failed to build plugins catalog.rz   )r   rM   rN   r}   r~   r   r   )rw   rC   r€   s   &  r(   Úget_plugins_catalogr±       sb   é € ô �7Ôò
2ðaÜ×&Ò& tÓ,×,Ð,Ñ,øÜô aÜ�‰Ð1°3Ô7Ü¨Ð4VÔWÐ]`Ð`ûðaüs0   ‚A)’2 «0¬2 ¯A)°2 ²A&½$A!Á!A&Á&A)c                óJ   € V ^8„  d   QhR\         . \        3,          R\        /# )r!   Úfnr$   )r   r‡   )r'   s   "r(   r)   r)   ¸   s#   € ÷ )ñ )œx¨¬D¨Õ1ð )´dñ )r*   c              ƒ  óX   a "  € V 3R lp\         P                  ! V4      G Rj  x€L
 #  L5i)u  Run a dashboard plugin mutation inside the dashboard profile's home + secret scope, off the
event loop.

Scope: the git-credential path reaches ``get_secret("GITHUB_TOKEN")``, which fails closed once
the process serves more than its launch profile â€” an unhandled ``UnscopedSecretError`` was the
bare 500 on install/update (#115256). Off-loop: the bodies clone/pull and rescan the plugins
directory. ``_config_profile_scope`` not ``_profile_scope``: the latter holds the process-wide
skills lock for the whole (network-bound) body.
c                  óv   <€ \        R 4      ;_uu_ 4        S ! 4       uuR R R 4       #   + '       g   i     R # ; irŒ   )r   )r³   s   €r(   rC   Ú_plugin_mutation.<locals>._runÂ   s"   ø€ Ü" 4×(Õ(Ù“4÷ )×(×(Ó(ús   •'§8	N)rM   rN   )r³   rC   s   f r(   Ú_plugin_mutationr·   ¸   s$   øé € õô ×"Ò" 4Ó(×(Ð(Ñ(ùs   ƒ *£(¤*z$/api/dashboard/agent-plugins/installc                ó0   € V ^8„  d   QhR\         R\        /# )r!   rw   rJ   )r   r   )r'   s   "r(   r)   r)   Ê   s   € ÷ ñ ¬Wð Ô<Sñ r*   c              ƒ   óJ  aaaa"  € \        V 4       ^ RIHo SP                  ;'       g    RP	                  4       oSP
                  P	                  4       oS'       g   S'       g   \        RRR7      h\        VVVV3R l4      G Rj  x€L
 pVP                  RR4       V#  L5i)	rš   )Údashboard_install_pluginr_   r‘   z(Provide an identifier or a catalog_name.rz   c            
      ó†   <€ \        S! SS P                  S P                  S;'       g    R S P                  R7      RRR7      # )N)ÚforceÚenableÚcatalog_nameÚrefzInstall failed.T©r†   )r”   r¼   r½   r¿   )rJ   r¾   rº   Ú
identifiers   €€€€r(   rp   Ú+post_agent_plugin_install.<locals>.<lambda>Ò   s:   ø€ ¬NÙ Ø˜dŸj™j°·±È<×K_ÐK_Ð[_Ø—‘ô	ð 	 $õ	-(r*   NÚafter_install_path)	r   r¢   rº   r¾   ÚstriprÁ   r   r·   Úpop)rw   rJ   r„   r¾   rº   rÁ   s   &f @@@r(   Úpost_agent_plugin_installrÆ   É   s�   ûé € ä�7ÔÝ?à×%Ñ%×+Ð+¨×2Ñ2Ó4€LØ—‘×&Ñ&Ó(€JßŸlÜ¨Ð4^Ô_Ð_Ü#÷ %(ó )÷ )€Fð ‡J�JÐ# TÔ*Ø€Mñ)ùs   †AB#ÁB#Á&"B#ÂB!Â	B#c                ó0   € V ^8„  d   QhR\         R\         /# )r!   r8   r$   ©r&   )r'   s   "r(   r)   r)   Ü   s   € ÷ ñ ¤ð ¬ñ r*   c                ón   € V P                  R4      p V '       d   RV 9   g   RV 9   d   \        RRR7      hV # )z=Reject path-traversal attempts in plugin name URL parameters.Ú/z..Ú\r‘   zInvalid plugin name.rz   )rÄ   r   )r8   s   &r(   Ú_validate_plugin_namerÌ   Ü   s1   € à�:‰:�c‹?€Dß�4˜4”< 4¨4¤<Ü¨Ð4JÔKÐKØ€Kr*   c                óª   € V ^8„  d   QhR\         R\        R\        \        .\        3,          R\        R\        R\
        \        R3,          R\        /# )	r!   rw   r8   Úactionr…   r†   r‚   .r$   )r   r&   r   r‡   rˆ   r‰   )r'   s   "r(   r)   r)   ä   s^   € ÷ lñ l¬ð l´sð lÄHÌcÈUÔTXÈ[ÕDYð lÔknð lÜ'+ðlÜ=BÄ3ÈÀ8½_ðlÜimñlr*   c             ƒ   ód   aaaaa"  € \        V 4       \        VVVVV3R  l4      G Rj  x€L
 #  L5i)c                  ó@   <€ \        S ! \        S4      4      SSSR 7      # )©r†   r‚   )r”   rÌ   )rÎ   r‚   r…   r8   r†   s   €€€€€r(   rp   Ú&_named_plugin_action.<locals>.<lambda>ç   s    ø€ ¬.ÙÔ$ TÓ*Ó+¨^ÀFÐ[iõ+kr*   N)r   r·   )rw   r8   rÎ   r…   r†   r‚   s   &fffddr(   Ú_named_plugin_actionrÓ   ä   s5   üé € ä�7ÔÜ!÷ #kð #kó l÷ lð lñ lùs   ‡"0©.ª0z//api/dashboard/agent-plugins/{name:path}/enablec                ó0   € V ^8„  d   QhR\         R\        /# ©r!   rw   r8   ©r   r&   )r'   s   "r(   r)   r)   ì   s   € ÷ Fñ F¬Gð F¼3ñ Fr*   c              ƒ   óR   a"  € ^ RI Ho \        WV3R lRRR7      G Rj  x€L
 #  L5i)rš   ©Ú"dashboard_set_agent_plugin_enabledc                 ó   <€ S! V R R7      # )T©r¦   ro   ©ÚnrÙ   s   &€r(   rp   Ú*post_agent_plugin_enable.<locals>.<lambda>î   s   ø€ Ñ?aÐbcÐmqÕ?rr*   zEnable failed.FrÀ   N©r¢   rÙ   rÓ   ©rw   r8   rÙ   s   &&@r(   Úpost_agent_plugin_enablerá   ë   s.   øé € åIÜ% gÔ5rØ&6¸uôF÷ Fð Fñ Fùó   ƒ' %¡'z0/api/dashboard/agent-plugins/{name:path}/disablec                ó0   € V ^8„  d   QhR\         R\        /# rÕ   rÖ   )r'   s   "r(   r)   r)   ó   s   € ÷ Gñ G¬Wð G¼Cñ Gr*   c              ƒ   óR   a"  € ^ RI Ho \        WV3R lRRR7      G Rj  x€L
 #  L5i)rš   rØ   c                 ó   <€ S! V R R7      # )FrÛ   ro   rÜ   s   &€r(   rp   Ú+post_agent_plugin_disable.<locals>.<lambda>õ   s   ø€ Ñ?aÐbcÐmrÕ?sr*   zDisable failed.FrÀ   Nrß   rà   s   &&@r(   Úpost_agent_plugin_disablerç   ò   s.   øé € åIÜ% gÔ5sØ&7ÀôG÷ Gð Gñ Gùrâ   z//api/dashboard/agent-plugins/{name:path}/updatec                ó0   € V ^8„  d   QhR\         R\        /# rÕ   rÖ   )r'   s   "r(   r)   r)   ú   s   € ÷ \ñ \¬Gð \¼3ñ \r*   c           	   ƒ   ó:  aaa"  € ^ RI Ho  V P                  4       G Rj  x€L
 p\	        V\
        4      '       d   TM/ pVP                  R4      RJ VP                  R4      RJ uoo\        WVVV3R lRRR	R7      G Rj  x€L
 #  Lc  \         d    / p Lpi ; i L5i)
rš   )Údashboard_update_user_pluginNÚaccept_capabilitiesTr¼   c                 ó   <€ S! V SSR 7      # ))rë   r¼   ro   )rÝ   Úacceptrê   r¼   s   &€€€r(   rp   Ú*post_agent_plugin_update.<locals>.<lambda>  s   ø€ Ñ!=¸aÐU[ÐchÕ!ir*   zUpdate failed.rÑ   )Úconsent_requiredÚscan_blocked)r¢   rê   Újsonr}   Ú
isinstancer‡   r`   rÓ   )rw   r8   rJ   rí   rê   r¼   s   && @@@r(   Úpost_agent_plugin_updateró   ù   sœ   úé € åCðØ—\‘\“^×#ˆô ˜d¤D×)Ò)‰4¨r€DØ—H‘HÐ2Ó3°tÐ;¸T¿X¹XÀgÓ=NÐRVÐ=V€M€FˆEÜ%ØÖiØ Ð6Zô\÷ \ð \ñ $øÜô ØŠðúñ\ùsD   …B�B  B¡B ¥ABÁ?BÂ BÂB ÂBÂBÂBÂBz(/api/dashboard/agent-plugins/{name:path}c                ó0   € V ^8„  d   QhR\         R\        /# rÕ   rÖ   )r'   s   "r(   r)   r)     s   € ÷ rñ r¤wð r´cñ rr*   c              ƒ   óH   "  € ^ RI Hp \        WVRRR7      G Rj  x€L
 #  L5i)rš   )Údashboard_remove_user_pluginzRemove failed.TrÀ   N)r¢   rö   rÓ   )rw   r8   rö   s   && r(   Údelete_agent_pluginr÷   
  s"   é € åCÜ% gÐ5QÐScÐlpÔq×qÐqÑqùs   ‚"› œ"z%/api/dashboard/agent-plugins/activatec                ó$   € V ^8„  d   QhR\         /# r–   r—   )r'   s   "r(   r)   r)     s   € ÷ )ñ )¬gñ )r*   c              ƒ  óL  aaaaaa	"  € \        V 4        V P                  4       G Rj  x€L
 p\        \	        T;'       g    / P                  R4      ;'       g    R4      4      o^ RIHoHoH	p \        \	        T;'       g    / P                  R4      ;'       g    R4      4      P                  4       o\	        S4      R9  d	   V! S4      MRo	S	f   \        RRR7      h^ R	IHo VVVVVV	3R
 lp\        P                   ! V4      G Rj  x€L
 #  Lä  \         d    / p Lñi ; i L5i)a  ``hermes plugins install`` / ``enable`` in another process asks this backend to load the plugin
for ``home`` and hand its MCP servers and skills to that profile's open chats
(``hermes_cli.plugins_activation.load_and_go_live``). ``home`` must be a profile this host serves.Nr8   r_   )Úget_hermes_homeÚhermes_home_keyÚprofile_name_for_homeÚhomer‘   zNot a Hermes profile home.rz   )Úload_and_go_livec                  óÜ   <€ \        SR 8X  d   RMS4      ;_uu_ 4        S! S ! 4       4      S! S4      8w  d   \        RRR7      hRRRS! S4      /uuRRR4       #   + '       g   i     R# ; i)r6   Nr‘   z#Home is not served by this backend.rz   rL   TÚ
activation)r   r   )rú   rû   rý   rþ   r8   r#   s   €€€€€€r(   rC   Ú(post_agent_plugin_activate.<locals>._run"  s\   ø€ Ü"¨7°iÔ+?¡4ÀW×MÕMÙ™Ó0Ó1±_ÀTÓ5JÔJÜ#°Ð<aÔbÐbØ˜$ Ñ.>¸tÓ.DÐE÷ N×M×MÓMús   ž1AÁA+	)r_   Ú.)r   rñ   r}   rÌ   r&   r`   Úhermes_constantsrú   rû   rü   r   Ú
expanduserr   Úhermes_cli.plugins_activationrþ   rM   rN   )
rw   rJ   rü   rC   rú   rû   rý   rþ   r8   r#   s
   &   @@@@@@r(   Úpost_agent_plugin_activater    sò   ýé € ô
 �7ÔðØ—\‘\“^×#ˆô !¤ d§j j¨b×%5Ñ%5°fÓ%=×%CÐ%CÀÓ!DÓE€DßXÑXÜ”�T—Z�Z˜R×$Ñ$ VÓ,×2Ð2°Ó3Ó4×?Ñ?ÓA€DÜ-0°«Y¸iÔ-GÑ# DÔ)ÈT€GØ‚Ü¨Ð4PÔQÐQÝ>÷Fò Fô ×"Ò" 4Ó(×(Ð(ñ# $øÜô ØŠðúñ  )ùs\   ˆD$•D ¨D©D ­D$Á D$Á'D$ÂD$ÂA.D$ÄD"Ä	D$ÄD ÄDÄD$ÄDÄD$z/api/dashboard/plugin-providersc                óR   € V ^8„  d   QhR\         R\        R\        \        ,          /# )r!   rw   rJ   r#   )r   r   r   r&   )r'   s   "r(   r)   r)   ,  s'   € ÷ )ñ )¬ð )Ô7Nð )Ü(0´­ñ)r*   c              ƒ  óŠ   aaaa"  € \        V 4       ^ RIHoHo VVVV3R lp\        P
                  ! V4      G Rj  x€L
 #  L5i)zHPersist memory provider / context engine selection (writes config.yaml).)Ú_save_context_engineÚ_save_memory_providerc            	      ó~  <€ \        S4      ;_uu_ 4        \        ;_uu_ 4        SP                  e)   \        SP                  4      p \	        V 4       S! V 4       SP
                  e   S! SP
                  4       R R R 4       R R R 4       \        4        RR/#   + '       g   i     L&; i  + '       g   i     L1; i)NrL   T)r   r   Úmemory_providerr   r   Úcontext_enginer   )r  r	  r
  rJ   r#   s    €€€€r(   rC   Ú"put_plugin_providers.<locals>._run2  sŠ   ø€ ô # 7×+Õ+×-BÖ-BØ×#Ñ#Ò/Ü"AÀ$×BVÑBVÓ"W�ô /¨Ô?Ù% oÔ6Ø×"Ñ"Ò.Ù$ T×%8Ñ%8Ô9÷ .C×+ô 	&Ô'Ø�dˆ|Ð÷ .C×-Bú×+×+ús#   •B,¤AB	Á;B,ÂB)Â$B,Â,B<	N)r   r¢   r	  r
  rM   rN   )rw   rJ   r#   rC   r	  r
  s   &ff @@r(   Úput_plugin_providersr  +  s6   ûé € ô �7ÔßR÷ð ô$ ×"Ò" 4Ó(×(Ð(Ñ(ùs   †6A¼A½Az-/api/dashboard/plugins/{name:path}/visibilityc          	      ó^   € V ^8„  d   QhR\         R\        R\        R\        \        ,          /# )r!   rw   r8   rJ   r#   )r   r&   r   r   )r'   s   "r(   r)   r)   H  s.   € ÷ )ñ )¬'ð )¼ð )ÔDYð )Ü*2´3­-ñ)r*   c              ƒ  óŒ   aaa"  € \        V 4       \        S4      oVVV3R lp\        P                  ! V4      G Rj  x€L
 #  L5i)zXToggle a plugin's sidebar visibility (persists to config.yaml dashboard.hidden_plugins).c            	      ó®  <€ \        S4      ;_uu_ 4        \        ;_uu_ 4        \        4       p R V 9  g&   \        V P	                  R 4      \
        4      '       g   / V R &   V R ,          P	                  R4      ;'       g    . p\        V\        4      '       g   . pSP                  '       d   SV9  d   VP                  S4       M*SP                  '       g   SV9   d   VP                  S4       WR ,          R&   \        V 4       RRR4       RRR4       \        4        RRRSRSP                  /#   + '       g   i     L4; i  + '       g   i     L?; i)r,   r^   NrL   Tr8   ra   )r   r   r   rò   r`   r‡   r>   ra   r?   Úremover   r   )r.   Úhidden_listrJ   r8   r#   s     €€€r(   rC   Ú$post_plugin_visibility.<locals>._runN  sþ   ø€ Ü" 7×+Õ+×-BÖ-BÜ “]ˆFØ &Ô(´
¸6¿:¹:ÀkÓ;RÔTX×0YÒ0YØ&(��{Ñ#Ø & {Õ 3× 7Ñ 7Ð8HÓ I× OÐ OÈRˆKÜ˜k¬4×0Ò0Ø �Ø�{�{ˆ{˜t¨;Ô6Ø×"Ñ" 4Õ(Ø—[—[�[ T¨[Ô%8Ø×"Ñ" 4Ô(Ø4?�;ÕÐ 0Ñ1Ü˜Ô÷ .C×+ô 	&Ô'Ø�d˜F D¨(°D·K±KÐ@Ð@÷ .C×-Bú×+×+ús5   •E¤AD1	Á?,D1	Â,*D1	Ã.D1	ÄEÄ1EÄ<EÅE	N)r   rÌ   rM   rN   )rw   r8   rJ   r#   rC   s   &fff r(   Úpost_plugin_visibilityr  G  s9   úé € ô �7ÔÜ  Ó&€D÷Aô" ×"Ò" 4Ó(×(Ð(Ñ(ùs   …8A½A¾Az.jszapplication/javascriptz.mjsz.cssztext/cssz.jsonzapplication/jsonz.htmlz	text/htmlz.svgzimage/svg+xmlz.pngz	image/pngz.jpgz
image/jpegz.jpegz.gifz	image/gifz.webpz
image/webpz.icozimage/x-iconz.woff2z
font/woff2z.woffz	font/woffz.ttfzfont/ttfz.otfzfont/otfz.mapz</dashboard-plugins/@{profile}/{plugin_name}/{file_path:path}c                ó<   € V ^8„  d   QhR\         R\         R\         /# )r!   r#   Úplugin_nameÚ	file_pathrÈ   )r'   s   "r(   r)   r)   n  s'   € ÷ Eñ E¬cð EÄð EÔPSñ Er*   c              ƒ  ó6   "  € \        WV 4      G Rj  x€L
 #  L5i)z»``serve_plugin_asset`` with the profile as a path segment (PLG-3): URLs relative to a stylesheet
or bundle (``url("./icon.svg")``, chunk imports) drop a query string but keep this prefix.N)Úserve_plugin_asset)r#   r  r  s   &&&r(   Úserve_profile_plugin_assetr  m  s   é € ô $ K¸GÓD×DÐDÑDùs   ‚’“z1/dashboard-plugins/{plugin_name}/{file_path:path}c                óR   € V ^8„  d   QhR\         R\         R\        \         ,          /# )r!   r  r  r#   r%   )r'   s   "r(   r)   r)   u  s+   € ÷ $yñ $y¬#ð $y¼#ð $yÌÔQTÍñ $yr*   c              ƒ  óT  a "  € R V 3R llp \        W#4      G Rj  x€L
 pVf   \        RRR7      h\        VR,          4      pWQ,          P                  4       pVP	                  VP                  4       4      '       g   \        RR	R7      hVP                  4       '       d   VP                  4       '       g   \        RR
R7      h\        P                  VP                  P                  4       4      pVf   \        RR
R7      h\        WgRR/R7      #  Lõ  \         d    Rp ELi ; i5i)uè  Serve static assets from a dashboard plugin's ``dashboard/`` directory.

Unauthenticated on purpose: the SPA loads plugin JS via ``<script src>`` and CSS
via ``<link href>``, which cannot attach an auth header. Hence the suffix
allowlist â€” user plugins ship a ``plugin_api.py`` backend the browser never
fetches, and without it anyone on the loopback port could curl a private
plugin's source. Path traversal is blocked via ``resolve().is_relative_to()``;
user plugins must be enabled (bundled ones not disabled) (GHSA-mcfc-hp25-cjv7) in the profile
whose copy these files are: a native ticket's, the ``?profile=`` the browser's plugin list used
(PLG-3), else the launch profile. An unknown profile answers as an unknown plugin.

See #46435.
c                ó:   € V ^8„  d   QhR\         \        ,          /# )r!   r$   )r   r‡   )r'   s   "r(   r)   Ú(serve_plugin_asset.<locals>.__annotate__ƒ  s   € ÷ Rñ Rœ¤�ñ Rr*   c                  óz   <€ \        V3R  l\        4        4       R4      p V '       d   \        V 4      '       d   R# T # )c              3   óF   <"  € T F  qR ,          S8X  g   K  Vx € K  	  R# 5i)r8   Nro   )r�   rb   r  s   & €r(   r�   Ú9serve_plugin_asset.<locals>._consented.<locals>.<genexpr>„  s   øé € ÐWÑ":˜QÀ½iÈ;Ñ>V—q’qÓ":ùs   ƒ!—
!N)Únextr   r   )Úpluginr  s    €r(   Ú
_consentedÚ&serve_plugin_asset.<locals>._consentedƒ  s2   ø€ ÜÔWÔ"8Ô":ÓWÐY]Ó^ˆß!Ô%=¸f×%EÒ%EˆtÐQÈ6ÐQr*   Ni”  zPlugin not foundrz   Ú_diri“  zPath traversal blockedzFile not foundzCache-Controlz#no-store, no-cache, must-revalidate)Ú
media_typeÚheaders)r   r   r   ÚresolveÚis_relative_toÚexistsÚis_fileÚ_PLUGIN_ASSET_CONTENT_TYPESr`   ÚsuffixÚlowerr   )r  r  r#   r&  r%  ÚbaseÚtargetr)  s   f&&     r(   r  r  t  sÿ   øé € ÷Rð RðÜ.¨wÓC×Cˆð ‚~Ü¨Ð4FÔGÐGä��v•Ó€DØÕ×'Ñ'Ó)€Fà× Ñ  §¡£×0Ò0Ü¨Ð4LÔMÐMØ�=‰=�?Š? &§.¡.×"2Ò"2Ü¨Ð4DÔEÐEä,×0Ñ0°·±×1DÑ1DÓ1FÓG€JØÒÜ¨Ð4DÔEÐEÜ˜ÀÐQvÐ?wÔxÐxñ# DøÜô Ø‹ðüsE   ƒ
D(ŽD œD�D ¡B D(Â"D(Â8AD(ÄD ÄD%Ä!D(Ä$D%Ä%D(rŒ   >   ÚinterÚfrauncesÚspectralúdm-sansú	work-sansú
space-monoúsystem-monoúsystem-sansúsource-serifúsystem-serifúibm-plex-monoúibm-plex-sansújetbrains-monoúatkinson-hyperlegible)rï   )LÚ__doc__rM   ÚloggingÚpathlibr   Útypingr   r   Úfastapir   r   r   Úfastapi.responsesr   Úhermes_cli.web_depsr	   r
   Úhermes_cli.configr   Úhermes_cli.web_routers._commonr   r¤   r   r   r   r   r   Úhermes_cli.web_server_memoryr   r   Úhermes_cli.web_modelsr   r   r   r   r   Ú	getLoggerr~   Úrouterr   r   r   r   r   r   r/   r`   rF   ÚputrO   rT   Ú	frozensetrU   rW   rZ   ri   ru   r�   r”   r±   r·   ÚpostrÆ   rÌ   rÓ   rá   rç   ró   Údeleter÷   r  r  r  r/  r  r  ro   r*   r(   Ú<module>rS     sô  ðñó Û Ý ß %ç 5Ñ 5Ý *ç /Ý %Ý B÷õ ÷ i÷õ ð ×ÒÐ0Ó1€Ù	‹€ñ Ð6Ó7Ð ÙÐ&Ó'€Ù�=Ð"5Ó6€Ù�=Ð"5Ó6€ñ Ð4Ð6VÓWÐ Ù!Ð"9Ó:Ð ÷ð ‡�Ð#Ó$ö8ó %ð8ð& ‡�Ð"Ó#ö,ó $ð,ð Ð Ùò ó €ð ‡�Ð!Ó"ö8ó #ð8ð ‡�Ð!Ó"ö&ó #ð&ð ‡�Ð$Ó%ö
Có &ð
Cð ‡�Ð+Ó,ö/ó -ð/ð ‡�Ð(Ó)ö	]ó *ð	]ðØ5J÷ð  ‡�Ð,Ó-ôaó .ðaõ.)ð" ‡�Ð3Ó4ôó 5ðõ$ðlØOd÷lð ‡�Ð>Ó?ôFó @ðFð ‡�Ð?Ó@ôGó AðGð ‡�Ð>Ó?ô\ó @ð\ð  ‡�Ð9Ó:ôró ;ðrð
 ‡�Ð4Ó5ô)ó 6ð)ð4 ‡�Ð-Ó.ö)ó /ð)ð6 ‡�Ð<Ó=ö)ó >ð)ð8Ø	Ð#ðØ%+Ð-EðØGMÈzðàÐðà!(¨+ðà7=¸ðð ˆKðð   ðð 07¸ðð GMÈkðð ˆ\ð	ð " >ð	ð 4<¸\ð	ð LSÐT_ð	ð
 ˆJðð
  
ðð
 -3Ð4FðÐ ð ‡�ÐJÓKôEó LðEð ‡�Ð?Ó@ö$yó Aò$yr*   