
    p#jb                    ~   d Z ddlmZ ddlZddlZddlZddlZddlZddlZddl	Z	ddl
mZ ddlmZmZ ddlmZ ddlmZ ddlmZ  ej        e          Z ej        d	
          d^d            Z G d de          Zd	Zd_dZddd`dZdadZdbdZ dcd Z!ddd"Z"ded%Z#dfd&Z$dgd'Z%dhd(Z&did)Z'djd,Z(	 	 dkdld/Z)dmd0Z*dmd1Z+dnd3Z,dod5Z-dnd6Z.dpd8Z/dmd9Z0dmd:Z1dqd;Z2drd=Z3dsd>Z4dtdBZ5dudvdDZ6dwdFZ7dwdGZ8dxdHZ9dxdIZ:dmdJZ;dmdKZ<dydLZ=dydMZ>dzdNZ?dO Z@dP ZAd{dRZBd|dSZCd}dTZDd~dUZEddWZFddXZGdd[ZHdd\ZIdzd]ZJdS )uq  ``hermes plugins`` CLI subcommand — install, update, remove, and list plugins.

Plugins are installed from Git repositories into ``~/.hermes/plugins/``.
Supports full URLs and ``owner/repo`` shorthand (resolves to GitHub).

After install, if the plugin ships an ``after-install.md`` file it is
rendered with Rich Markdown.  Otherwise a default confirmation is shown.
    )annotationsN)Path)AnyOptional)get_hermes_home)cfg_get)masked_secret_prompt   )maxsizereturnOptional[str]c            
     8   t          j        d          } | r| S t          j        dk    rBt          j                            dd          }t          j                            dd          }t          j                            dd          }t          j                            |d	d
d          t          j                            |d	dd          t          j                            |d	d
d          t          j                            |d	dd          g}|rY|                    t          j                            |dd	d
d          t          j                            |dd	dd          f           ng d}|D ]'}|r#t          j        	                    |          r|c S (dS )zResolve a git binary for subprocess use when ``PATH`` may be minimal.

    Matches other Hermes subprocess resolution: :func:`shutil.which` first,
    then common Git for Windows install paths and POSIX defaults.
    gitntProgramFileszC:\Program FileszProgramFiles(x86)zC:\Program Files (x86)LOCALAPPDATA Gitcmdzgit.exebinPrograms)z/usr/bin/gitz/usr/local/bin/gitz/bin/gitN)
shutilwhichosnameenvirongetpathjoinextendisfile)foundprogprog_x86local
candidatescs         ;/home/ubuntu/.hermes/hermes-agent/hermes_cli/plugins_cmd.py_resolve_git_executabler)      ss    LE 	w$z~~n.ABB:>>"57PQQ
~r22GLLueY77GLLueY77GLL5%;;GLL5%;;	

  	GLL
E5)LLGLL
E5)LL   HGG
   	"" 	HHH4    c                      e Zd ZdZdS )PluginOperationErrorzHRecoverable plugin install/update failure (CLI exits; HTTP maps to 4xx).N)__name__
__module____qualname____doc__ r*   r(   r,   r,   @   s        RRRRr*   r,   r   c                 V    t                      dz  } |                     dd           | S )z9Return the user plugins directory, creating it if needed.pluginsT)parentsexist_ok)r   mkdir)r3   s    r(   _plugins_dirr7   J   s-    )+GMM$M...Nr*   Fallow_subdirr   strplugins_dirr9   boolc                  | st          d          |r&|                     d          } | st          d          | dv rt          d|  d          |rdnd}|D ]}|| v rt          d|  d| d	          || z                                  }|                                }||k    rt          d|  d
          	 |                    |           n!# t           $ r t          d|  d          w xY w|S )a  Validate a plugin name and return the safe target path inside *plugins_dir*.

    Raises ``ValueError`` if the name contains path-traversal sequences or would
    resolve outside the plugins directory.

    ``allow_subdir=True`` permits a single forward slash inside *name* so
    category-namespaced plugin keys like ``observability/langfuse`` or
    ``image_gen/openai`` (the registry keys emitted by ``_discover_all_plugins``)
    can be looked up. ``..`` and backslash are still rejected, leading and
    trailing slashes are stripped, and the resolved target must still live
    inside *plugins_dir*. Install paths leave this at the default ``False``
    because a freshly-cloned plugin always lands top-level under
    ``~/.hermes/plugins/<name>/``.
    zPlugin name must not be empty./>   ...zInvalid plugin name 'z3': must not reference the plugins directory itself.)\r@   )r>   rA   r@   z': must not contain 'z'.z,': resolves to the plugins directory itself.z*': resolves outside the plugins directory.)
ValueErrorstripresolverelative_to)r   r;   r9   	bad_charsbadtargetplugins_resolveds          r(   _sanitize_plugin_namerJ   Q   s|   (  ;9::: ?zz# 	?=>>>{]D]]]
 
 	

 !-C2CI Y Y$;;WTWWPSWWWXXX  D ))++F"**,,!!!VDVVV
 
 	

+,,,, 
 
 
TDTTT
 
 	


 Ms   ;C C/
identifierc                    |                      d          r| S |                     d                              d          }t          |          dk    r|\  }}d| d| dS t	          d|  d          )u  Turn an identifier into a cloneable Git URL.

    Accepted formats:
    - Full URL: https://github.com/owner/repo.git
    - Full URL: git@github.com:owner/repo.git
    - Full URL: ssh://git@github.com/owner/repo.git
    - Shorthand: owner/repo  →  https://github.com/owner/repo.git

    NOTE: ``http://`` and ``file://`` schemes are accepted but will trigger a
    security warning at install time.
    )zhttps://http://zgit@zssh://file://r>      zhttps://github.com/.gitzInvalid plugin identifier: 'z)'. Use a Git URL or owner/repo shorthand.)
startswithrC   splitlenrB   )rK   partsownerrepos       r(   _resolve_git_urlrW      s     QRR  S!!'',,E
5zzQt7U77T7777
	1z 	1 	1 	1  r*   urlc                   |                      d          }|                    d          r
|dd         }|                    dd          d         }d|v r6|                    dd          d                             dd          d         }|S )zCExtract the repo name from a Git URL for the plugin directory name.r>   rP   Nr
   :)rstripendswithrsplit)rX   r   s     r(   _repo_name_from_urlr`      s     ::c??D}}V CRCy;;sAr"D
d{{{{3""2&--c155b9Kr*   
plugin_dirdictc                0   | dz  }|                                 si S 	 ddl}t          |d          5 }|                    |          pi cddd           S # 1 swxY w Y   dS # t          $ r(}t
                              d| |           i cY d}~S d}~ww xY w)z;Read plugin.yaml and return the parsed dict, or empty dict.plugin.yamlr   Nutf-8encodingz$Failed to read plugin.yaml in %s: %s)existsyamlopen	safe_load	Exceptionloggerwarning)ra   manifest_fileri   fes        r(   _read_manifestrr      s    .M!! 	-'222 	+a>>!$$*	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+   =z1MMM						s@   A# A	A# AA# AA# #
B-B
BBNonec                T   |                      d          D ]}|j        }| |z  }|                                so	 t          j        ||           |                    d| d|j         d           Z# t          $ r*}|                    d|j         d|            Y d}~d}~ww xY wdS )zCopy any .example files to their real names if they don't already exist.

    For example, ``config.yaml.example`` becomes ``config.yaml``.
    Skips files that already exist to avoid overwriting user config on reinstall.
    z	*.examplez[dim]  Created z from [/dim]z)[yellow]Warning:[/yellow] Failed to copy : N)globstemrh   r   copy2printr   OSError)ra   consoleexample_file	real_name	real_pathrq   s         r(   _copy_example_filesr      s    #44   %	*	!! 		\9555PiPP|7HPPP       X@QXXUVXX       		 s   6A00
B$: BB$manifest	list[str]c                H   |                      d          pg }|sg S ddlm g }|D ]n}t          |t                    r|                    d|i           /t          |t                    r*|                     d          r|                    |           ofd|D             S )zLReturn declared ``requires_env`` names that are unset in ``~/.hermes/.env``.requires_envr   )get_env_valuer   c                l    g | ]0}|                     d            |d                    (|d          1S r   )r   .0sr   s     r(   
<listcomp>z/_missing_requires_env_names.<locals>.<listcomp>   sB    [[[!AEE&MM[--PQRXPYBZBZ[AfI[[[r*   )r   hermes_cli.configr   
isinstancer:   appendrb   )r   r   	env_specsentryr   s       @r(   _missing_requires_env_namesr      s    <<//52L 	//////I $ $eS!! 	$fe_----t$$ 	$6):): 	$U###[[[[y[[[[r*   c                   |                      d          pg }|sdS ddlmm} ddlm} g }|D ]n}t          |t                    r|                    d|i           /t          |t                    r*|                     d          r|                    |           ofd|D             }|sdS |                      dd          }|
                    d	| d
           |D ]y}	|	d         }
|	                     dd          }|	                     dd          }|	                     dd          }d|
 }|r|d| z  }|
                    |           |r|
                    d| d           	 |r&t          d|
 d                                          }n%t          d|
 d                                          }n:# t          t          f$ r& |
                    d |             d           Y  dS w xY w|r> ||
|           |t           j        |
<   |
                    d |             d           U|
                    d|
 d |             d           {|
                                 dS )a  Prompt for required environment variables declared in plugin.yaml.

    ``requires_env`` accepts two formats:

    Simple list (backwards-compatible)::

        requires_env:
          - MY_API_KEY

    Rich list with metadata::

        requires_env:
          - name: MY_API_KEY
            description: "API key for Acme service"
            url: "https://acme.com/keys"
            secret: true

    Already-set variables are skipped.  Values are saved to the user's ``.env``.
    r   Nr   )r   save_env_value)display_hermes_homer   c                6    g | ]} |d                    |S r   r1   r   s     r(   r   z+_prompt_plugin_env_vars.<locals>.<listcomp>  s,    DDDQ==6+C+CDqDDDr*   zthis pluginz
[bold]z6[/bold] requires the following environment variables:
descriptionr   rX   secretF      — z  [dim]Get yours at: ru   rv   z,
[dim]  Skipped (you can set these later in z/.env)[/dim]u     [green]✓[/green] Saved to z/.envz  [dim]  Skipped (set z in z/.env later)[/dim])r   r   r   r   hermes_constantsr   r   r:   r   rb   rz   r	   rC   inputEOFErrorKeyboardInterruptr   r   )r   r|   r   r   r   r   r   missingplugin_namespecr   descrX   r   labelvaluer   s                   @r(   _prompt_plugin_env_varsr      s   ( <<//52L ????????444444 I $ $eS!! 	$fe_----t$$ 	$6):): 	$U### EDDD)DDDG ,,v}55KMMa[aaabbb h hF|xxr**hhub!!(E**T 	$^T^^#Ee 	?MM=#===>>>	 5,]$]]];;AACCm4mmm,,2244+, 	 	 	MMmJ]J]J_J_mmmnnnFFF	  	hN4'''$BJtMMW;N;N;P;PWWWXXXXMMf4ff=P=P=R=RfffggggMMOOOOOs   .AF<<2G32G3c                   ddl m} ddlm} ddlm}  |            }| dz  }|                                rl|                    d          } ||          }|                                 |                     ||dd	
                     |                                 dS |                                 |                     |d| d|  ddd	                     |                                 dS )z@Show after-install.md if it exists, otherwise a default message.r   Console)Markdown)Panelafter-install.mdre   rf   greenF)border_styleexpandz![green bold]Plugin installed:[/] z
[dim]Location:[/] u   ✓ Installed)r   titler   N)	rich.consoler   rich.markdownr   
rich.panelr   rh   	read_textrz   )	ra   rK   r   r   r   r|   after_installcontentmds	            r(   _display_after_installr   5  s9   $$$$$$&&&&&&      giiG!33M ))7);;XgeeBWUCCCDDDE2J 2 2%/2 2$%  	
 	
 	
 	r*   c                    ddl m}  |            }|                                 |                    d|  d|            |                                 dS )z*Show confirmation after removing a plugin.r   r   u   [red]✗[/red] Plugin [bold]z[/bold] removed from N)r   r   rz   )r   r;   r   r|   s       r(   _display_removedr   R  s`    $$$$$$giiGMMOOOMMYYYKYYZZZMMOOOOOr*   c                   t          | |d          }|                                sed                    d |                                D                       pd}|                    d|  d| d|            t          j        d	           |S )
zUReturn the plugin path if it exists, or exit with an error listing installed plugins.Tr8   z, c              3  L   K   | ]}|                                 |j        V   d S N)is_dirr   )r   ds     r(   	<genexpr>z,_require_installed_plugin.<locals>.<genexpr>`  s1      RRqxxzzRafRRRRRRr*   z(none)[red]Error:[/red] Plugin 'z' not found in z.
Installed plugins: r
   )rJ   rh   r   iterdirrz   sysexit)r   r;   r|   rH   	installeds        r(   _require_installed_pluginr   \  s    "44HHHF==?? IIRRk.A.A.C.CRRRRR^V^	. . .k . ."+. .	
 	
 	
 	Mr*   forcetuple[Path, dict, str]c                  ddl }	 t          |           }n/# t          $ r"}t          t	          |                    |d}~ww xY wt                      }|                                5 }t          |          dz  }t                      }|st          d          	 t          j
        |ddd|t	          |          gddd	
          }	nD# t          $ r}t          d          |d}~wt          j        $ r}t          d          |d}~ww xY w|	j        dk    r4|	j        p|	j        pd                                }
t          d|
           t#          |          }|                    d          pt'          |          }	 t)          ||          }n/# t          $ r"}t          t	          |                    |d}~ww xY w|                    d          }|x	 t+          |          }n,# t          t,          f$ r t          d| d| d          dw xY w|t.          k    r0ddlm} t          d| d| dt.           d |             d	          d|                                r,|st          d| d| d          t7          j        |           t7          j        t	          |          t	          |                     ddd           n# 1 swxY w Y   |dz                                  p|dz                                  }|s2|dz                                  st<                              d|           ddl m!} tE          | |                       t#          |          }|                    d          p|j#        }|||fS )zClone Git plugin into ``~/.hermes/plugins``.

    Returns ``(target_dir, installed_manifest, canonical_name)``.
    Raises ``PluginOperationError`` on failure.
    r   Nplugin$git is not installed or not in PATH.clonez--depth1T<   )capture_outputtexttimeoutz%Git clone timed out after 60 seconds.r   zGit clone failed:
r   manifest_versionPlugin 'z ' has invalid manifest_version 'z' (expected an integer).)recommended_update_commandz' requires manifest_version z), but this installer only supports up to z. Run z to update Hermes.zD' already exists. Use force reinstall or run `hermes plugins update z`.rd   
plugin.yml__init__.pyz>%s has no plugin.yaml / __init__.py; may not be a valid pluginr   )$tempfilerW   rB   r,   r:   r7   TemporaryDirectoryr   r)   
subprocessrunFileNotFoundErrorTimeoutExpired
returncodestderrstdoutrC   rr   r   r`   rJ   int	TypeError_SUPPORTED_MANIFEST_VERSIONr   r   rh   r   rmtreemoverm   rn   r   r   r   r   )rK   r   r   git_urlrq   r;   tmp
tmp_targetgit_exeresulterrr   r   rH   mvmv_intr   has_yamlr   installed_manifestinstalled_names                        r(   _install_plugin_corer   n  s    OOO2":.. 2 2 2"3q66**12 ..K		$	$	&	& =2##YY)
)++ 	O&'MNNN	^'9c7C
OOL#	  FF ! 	 	 	&6  ( 	 	 	&7 	
 !!=7FM7R>>@@C&'BS'B'BCCC!*--ll6**J.A'.J.J	6*;DDFF 	6 	6 	6&s1vv..A5	6 \\,-->R	*   *5{ 5 55 5 5  
 333HHHHHH*L{ L L L L>YL L5577L L L  	 ==?? 	" *E{ E E5@E E E   M&!!!C
OOS[[111{=2 =2 =2 =2 =2 =2 =2 =2 =2 =2 =2 =2 =2 =2 =2~ &..00TVl5J4R4R4T4TH 
Vm3;;== 
L	
 	
 	

 %$$$$$		***'//'++F33Bv{N%~55s    
A=A'2K+CK
DC  D2DDA5K=FK
F:F55F::KG%$K%)HB-KKKenableOptional[bool]c                   ddl m}  |            }	 t          |           }nC# t          $ r6}|                    d|            t          j        d           Y d}~nd}~ww xY w|                    d          r|                    d           |                    d| d	           	 t          | |
          \  }}}	nC# t          $ r6}|                    d|            t          j        d           Y d}~nd}~ww xY w|dz  
                                sG|dz  
                                s0|dz  
                                s|                    d|	 d           t          ||           t          ||            |}
|
t
          j                                        rtt
          j                                        rV	 t!          d|	 d                                                                          }|dv }
n# t&          t(          f$ r d}
Y nw xY wd}
|
r~t+                      }t-                      }|                    |	           |                    |	           t3          |           t5          |           |                    d|	 d           n|                    d|	 d           |                    d           |                    d           |                                 dS )zInstall a plugin from a Git URL or owner/repo shorthand.

    After install, prompt "Enable now? [y/N]" unless *enable* is provided
    (True = auto-enable without prompting, False = install disabled).
    r   r   [red]Error:[/red] r
   NrM   rN   zs[yellow]Warning:[/yellow] Using insecure/local URL scheme. Consider using https:// or git@ for production installs.z[dim]Cloning 	...[/dim]r   rd   r   r   z[yellow]Warning:[/yellow] zQ doesn't contain plugin.yaml or __init__.py. It may not be a valid Hermes plugin.z
  Enable 'z' now? [y/N]: >   yyesF    [green]✓[/green] Plugin [bold]z[/bold] enabled.zB[dim]Plugin installed but not enabled. Run `hermes plugins enable z` to activate.[/dim]z=[dim]Restart the gateway for the plugin to take effect:[/dim]z#[dim]  hermes gateway restart[/dim])r   r   rW   rB   rz   r   r   rQ   r   r,   rh   r   r   stdinisattyr   r   rC   lowerr   r   _get_enabled_set_get_disabled_setadddiscard_save_enabled_set_save_disabled_set)rK   r   r   r   r|   r   rq   rH   r   r   should_enableanswerenableddisableds                 r(   cmd_installr    s    %$$$$$giiG":..   .1../// 011 
G	
 	
 	

 MM4'4445555I6
 6
 6
2"NN     .1../// ]"**,, 
f|6K5S5S5U5U 
fhh
 	D D D D	
 	
 	

 .8886:...M9 		"#*"3"3"5"5 		"&???? %''%%''  !', 6/0 & & & %& "M 
"$$$&&N###((('"""8$$$O~OOO	
 	
 	
 	
 	O*8O O O	
 	
 	

 MMQRRRMM7888MMOOOOOs>   " 
A",AA")B? ?
C?	,C::C?;G= =HHc                   ddl m}  |            }t                      }	 t          | ||          }nC# t          $ r6}|                    d|            t          j        d           Y d}~nd}~ww xY w|dz                                  s-|                    d|  d           t          j        d           |                    d	|  d
           t          |          \  }}|s,|                    d|            t          j        d           t          ||           |                                }d|v r|                    d|  d           dS |                    d|  d           |                    d| d           dS )zAUpdate an installed plugin by pulling latest from its git remote.r   r   r   r
   NrP   r   z@' was not installed from git (no .git directory). Cannot update.z[dim]Updating r   Already up to dater   z[/bold] is already up to date.z[/bold] updated.z[dim]ru   )r   r   r7   r   rB   rz   r   r   rh   _git_pull_plugin_dirr   rC   )	r   r   r|   r;   rH   rq   okoutputouts	            r(   
cmd_updater    s   $$$$$$giiG..K*4gFF   .1../// VO##%% 3 3 3 3	
 	
 	
 	MM24222333%f--JB 3633444 (((
,,..Cs""StSSS	
 	
 	
 	
 	
 	OOOOPPP)c)))*****   2 
A2,A--A2c                6   ddl m}  |            }t                      }	 t          | ||          }nC# t          $ r6}|                    d|            t          j        d           Y d}~nd}~ww xY wt          j	        |           t          | |           dS )z#Remove an installed plugin by name.r   r   r   r
   N)r   r   r7   r   rB   rz   r   r   r   r   r   )r   r   r|   r;   rH   rq   s         r(   
cmd_remover  F  s    $$$$$$giiG..K*4gFF   .1../// M&T;'''''r  setc                     	 ddl m}   |             }t          |ddg           }t          |t                    rt          |          nt                      S # t          $ r t                      cY S w xY w)zRead the disabled plugins set from config.yaml.

    An explicit deny-list. A plugin name here never loads, even if also
    listed in ``plugins.enabled``.
    r   load_configr3   r  default)r   r  r   r   listr  rl   )r  configr  s      r(   r   r   W  s    11111169j"EEE *8T : :Es8}}}E   uus   AA A21A2r  c                    ddl m}m}  |            }d|vri |d<   t          |           |d         d<    ||           dS )z/Write the disabled plugins list to config.yaml.r   r  save_configr3   r  Nr   r  r  sorted)r  r  r  r  s       r(   r  r  f  sg    ::::::::[]]Fy$*8$4$4F9j!Kr*   c                 b   	 ddl m}   |             }|                    di           }t          |t                    st                      S |                    dg           }t          |t                    rt          |          nt                      S # t          $ r t                      cY S w xY w)zRead the enabled plugins allow-list from config.yaml.

    Plugins are opt-in: only names here are loaded. Returns ``set()`` if
    the key is missing (same behaviour as "nothing enabled yet").
    r   r  r3   r  )r   r  r   r   rb   r  r  rl   )r  r  plugins_cfgr  s       r(   r   r   p  s    	111111jjB//+t,, 	55L//)R00)'488Cs7|||ceeC   uus   AB AB B.-B.r  c                    ddl m}m}  |            }d|vri |d<   t          |           |d         d<    ||           dS )z.Write the enabled plugins list to config.yaml.r   r  r3   r  Nr  )r  r  r  r  s       r(   r   r     se    ::::::::[]]Fy#)'??F9i Kr*   c                   ddl m}  |            }t          |           s-|                    d|  d           t	          j        d           t                      }t                      }| |v r| |vr|                    d|  d           dS |                    |            |	                    |            t          |           t          |           |                    d	|  d
           dS )zEAdd a plugin to the enabled allow-list (and remove it from disabled).r   r   [red]Plugin '$' is not installed or bundled.[/red]r
   [dim]Plugin 'z' is already enabled.[/dim]Nr   z.[/bold] enabled. Takes effect on next session.)r   r   _plugin_existsrz   r   r   r   r   r   r   r   r  r   r   r|   r  r  s        r(   
cmd_enabler'    s   $$$$$$giiG$ PdPPPQQQ  G ""Hw4x//GdGGGHHHKKTgx   MM	(4 	( 	( 	(    r*   c                   ddl m}  |            }t          |           s-|                    d|  d           t	          j        d           t                      }t                      }| |vr| |v r|                    d|  d           dS |                    |            |	                    |            t          |           t          |           |                    d	|  d
           dS )zBRemove a plugin from the enabled allow-list (and add to disabled).r   r   r"  r#  r
   r$  z' is already disabled.[/dim]Nu"   [yellow]⊘[/yellow] Plugin [bold]z/[/bold] disabled. Takes effect on next session.)r   r   r%  rz   r   r   r   r   r   r   r   r  r&  s        r(   cmd_disabler)    s   $$$$$$giiG$ PdPPPQQQ  G ""H7tx//HdHHHIIIOODLLgx   MM	( 	( 	( 	(    r*   c                   t                      }|                                rp|| z                                  rdS |                                D ]B}|                                st          |          }|                    d          | k    r dS Cddlm}  |            }|                                rI|| z  }|                                r0|dz                                  s|dz                                  rdS dS )zCReturn True if a plugin with *name* is installed (user) or bundled.Tr   r   get_bundled_plugins_dirrd   r   F)r7   r   r   rr   r   hermes_cli.pluginsr,  rh   )r   user_dirchildr   r,  repo_plugins	candidates          r(   r%  r%    s,    ~~H tO##%% 	4%%'' 	 	E<<>> %e,,H||F##t++tt , ;:::::**,,L  4'	 	&..00	L(0022	 45r*   r  c                    	 ddl } n# t          $ r d} Y nw xY wi }ddlm}  |            }|dft	                      dffD ]v\  }}|                                st          |                                          D ]8}|                                s|dk    r
|j        dv r(|dz  }|	                                s|dz  }|	                                s[|j        }d	}	d	}
| r	 t          |d
          5 }|                     |          pi }ddd           n# 1 swxY w Y   |                    d|j                  }|                    dd	          }	|                    dd	          }
n# t          $ r Y nw xY w||v r|dk    r|}|dk    r|dz  	                                rd}||	|
||f||<   :xt          |                                          S )u,  Return a list of (name, version, description, source, dir_path) for
    every plugin the loader can see — user + bundled + project.

    Matches the ordering/dedup of ``PluginManager.discover_and_load``:
    bundled first, then user, then project; user overrides bundled on
    name collision.
    r   Nr+  bundleduser>   memorycontext_enginerd   r   r   re   rf   r   versionr   rP   r   )ri   ImportErrorr-  r,  r7   r   r  r   r   rh   rj   rk   r   rl   r  values)ri   seenr,  r0  basesourcer   ro   r   r7  r   rp   r   	src_labels                 r(   _discover_all_pluginsr>    s       D ;:::::**,,L&	2\^^V4LM D Df{{}} 	'' 	D 	DA88:: ""qv1M'M'M-M '')) 1 !L 0 '')) 6DGK mg>>> ;!#'>>!#4#4#:; ; ; ; ; ; ; ; ; ; ; ; ; ; ;#<<77D&ll9b99G"*,,}b"A"AKK    D t||) 3 3IQZ$7$7$9$9!	iCDJJ9	D: sC    $E,5DE,DE, D!A
E,,
E98E9c                    | |v rdS | |v rdS dS )z:Return the user-facing activation state for a plugin name.r  r  znot enabledr1   )r   r  r  s      r(   _plugin_statusr@    s%    xzwy=r*   entriesargsr   c                    | }t          |dd          st          |dd          rd |D             }t          |dd          rfd|D             }|S )z*Apply ``hermes plugins list`` CLI filters.
no_bundledFr4  c                *    g | ]}|d          dk    |S )   r3  r1   )r   r   s     r(   r   z*_filter_plugin_entries.<locals>.<listcomp>  s&    IIIe58y3H3HE3H3H3Hr*   r  c                J    g | ]}t          |d                    dk    | S )r   r  )r@  )r   r   r  r  s     r(   r   z*_filter_plugin_entries.<locals>.<listcomp>  s>     
 
 
eAh::iGG GGGr*   )getattr)rA  rB  r  r  filtereds     `` r(   _filter_plugin_entriesrJ    s    Ht\5)) JWT65-I-I JIIxIIItY&& 

 
 
 
 
'
 
 
 Or*   
Any | Nonec           
     >   ddl m} ddlm}  |            }t	                      }|s,|                    d           |                    d           dS t                      t                      t          ||           }t          | dd          r4fd	|D             }t          t          j        |d
                     dS t          | dd          rH|D ]C\  }}}}	}
t          |          }t          |dd|	ddt          |          dd|            DdS |s|                    d           dS  |dd          }|                    dd           |                    d           |                    dd           |                    d           |                    dd           |D ]S\  }}}}	}
t          |          }|dk    rd}n|dk    rd}nd}|                    ||t          |          ||	           T|                                 |                    |           |                                 |                    d            |                    d!           |                    d"           |                    d#           dS )$z>List all plugins (bundled + user) with enabled/disabled state.r   r   )Tablez [dim]No plugins installed.[/dim]:[dim]Install with:[/dim] hermes plugins install owner/repoNjsonFc                d    g | ],\  }}}}}|t          |          t          |          ||d -S ))r   statusr7  r   r<  )r@  r:   )r   r   r7  r   r<  _dirr  r  s         r(   r   zcmd_list.<locals>.<listcomp>7  s]     	
 	
 	
 9g{FD (wAAw<<*  	
 	
 	
r*   rO   )indentplain12 8z3[dim]No plugins matched the selected filters.[/dim]Plugins)r   
show_linesNamebold)styleStatusVersiondimDescriptionSourcer  z[red]disabled[/red]r  z[green]enabled[/green]z[yellow]not enabled[/yellow]zA[dim]Compact view:[/dim] hermes plugins list --plain --no-bundledz-[dim]Interactive toggle:[/dim] hermes pluginsz?[dim]Enable/disable:[/dim] hermes plugins enable/disable <name>uI   [dim]Plugins are opt-in by default — only 'enabled' plugins load.[/dim])r   r   
rich.tablerM  r>  rz   r   r   rJ  rH  rO  dumpsr@  r:   
add_columnadd_row)rB  r   rM  r|   rA  payloadr   r7  _descriptionr<  rR  rQ  tabler   status_namer  r  s                  @@r(   cmd_listrj  &  s$   $$$$$$      giiG#%%G 8999RSSS  G ""H$WdGXFFGtVU## 	
 	
 	
 	
 	
 =D	
 	
 	
 	dj+++,,,tWe$$ 9@ 	E 	E5D'<#D'8<<FVCCCCCCCLLCCCTCCDDDD KLLLE	e444E	V6***	X	Ye,,,	]###	XU+++4; G G0g{FD$T7H==*$$*FFI%%-FF3FdFCLL+vFFFFMMOOOMM%MMOOOMMUVVVMMABBBMMSTTTMM]^^^^^r*   list[tuple[str, str]]c                 \    	 ddl m}  d  |             D             S # t          $ r g cY S w xY w)zAReturn [(name, description), ...] for available memory providers.r   discover_memory_providersc                    g | ]
\  }}}||fS r1   r1   )r   r   r   _avails       r(   r   z._discover_memory_providers.<locals>.<listcomp>q  s#    SSS!3tVtSSSr*   )plugins.memoryrn  rl   rm  s    r(   _discover_memory_providersrr  m  s[    <<<<<<SS7P7P7R7RSSSS   			s    ++c                    g } t                      }	 ddlm}  |            D ]6\  }}}||vr,|                     ||f           |                    |           7n# t
          $ r Y nw xY w	 ddlm}m}  |              |            }|r6t          |dd          r%|j
        |vr|                     |j
        df           n# t
          $ r Y nw xY w| S )aZ  Return [(name, description), ...] for available context engines.

    Includes repo-shipped engines from ``plugins/context_engine/`` AND
    plugin-registered engines (third-party engines installed as Hermes
    plugins via ``ctx.register_context_engine``). Repo-shipped descriptions
    win when a plugin-registered engine collides on name.
    r   )discover_context_engines)discover_pluginsget_plugin_context_enginer   Nzinstalled plugin)r  plugins.context_enginert  r   r   rl   r-  ru  rv  rH  r   )	enginesr:  rt  r   r   rp  ru  rv  plugin_engines	            r(   _discover_context_enginesrz  v  sH    &(GUUDCCCCCC":":"<"< 	 	D$4d|,,,	    RRRRRRRR1133 	EW]FDAA 	EmFX`dFdFdNNM.0BCDDD    Ns%   AA 
A'&A'+AC   
CCc                 p    	 ddl m}   |             }t          |ddd          pdS # t          $ r Y dS w xY w)zBReturn the current memory.provider from config (empty = built-in).r   r  r5  providerr   r  r   r  r   rl   r  r  s     r(   _get_current_memory_providerr    sb    111111vxR@@@FBF   rr   $' 
55c                 p    	 ddl m}   |             }t          |ddd          pdS # t          $ r Y dS w xY w)z.Return the current context.engine from config.r   r  contextengine
compressorr  r}  r~  s     r(   _get_current_context_enginer    sb    111111vy(LIIIY\Y   ||r  c                h    ddl m}m}  |            }d|vri |d<   | |d         d<    ||           dS )z'Persist memory.provider to config.yaml.r   r  r5  r|  Nr   r  r  r   r  r  r  s       r(   _save_memory_providerr    s_    ::::::::[]]Fvx#'F8Z Kr*   c                h    ddl m}m}  |            }d|vri |d<   | |d         d<    ||           dS )z&Persist context.engine to config.yaml.r   r  r  r  Nr  r  s       r(   _save_context_enginer    s_    ::::::::[]]Fy"&F9hKr*   c                    ddl m}  t                      }t                      }dg}dg}d}|D ]R\  }}|                    |           |r| d| n|}|                    |           ||k    rt          |          dz
  }S|rC||vr?|                    |           |                    | d           t          |          dz
  } | d||	          }	||	         }
|
|k    rt          |
           d
S dS )zDLaunch a radio picker for memory providers. Returns True if changed.r   curses_radiolistzbuilt-in (default)r   r   r
    (not found)zMemory Provider (select one)r   itemsselectedTF)hermes_cli.curses_uir  r  rr  r   rS   r  )r  current	providersr  namesr  r   r   r   choicenew_providers              r(   _configure_memory_providerr    sK   555555*,,G*,,I ""EDEH & &
dT+/94'''''TU7??5zzA~H  "7%''W---...u::>,  F =Lwl+++t5r*   c                    ddl m}  t                      }t                      }dg}dg}d}|D ]R\  }}|                    |           |r| d| n|}|                    |           ||k    rt          |          dz
  }S|dk    rC||vr?|                    |           |                    | d           t          |          dz
  } | d||	          }	||	         }
|
|k    rt          |
           d
S dS )zCLaunch a radio picker for context engines. Returns True if changed.r   r  zcompressor (default)r  r   r
   r  zContext Engine (select one)r  TF)r  r  r  rz  r   rS   r  )r  r  rx  r  r  r  r   r   r   r  
new_engines              r(   _configure_context_enginer    sN   555555)++G'))G $$ENEH & &
dT+/94'''''TU7??5zzA~H ,7%#7#7W---...u::>+  F vJWZ(((t5r*   c            	     v   ddl m}   |             }t                      }t                      }t	                      }g }g }t                      }t          |          D ]h\  }\  }	}
}}}|r|	 d| n|	}|dk    r| d}|                    |	           |                    |           |	|v r|	|vr|                    |           it                      pd}t                      }d|t          fd|t          fg}t          |          }t          |          }|s.|s,|                    d	           |                    d
           dS t          j                                        s|                    d           dS 	 ddl}t'          |||||||           dS # t(          $ r t+          ||||||           Y dS w xY w)uJ   Interactive composite UI — general plugins + provider plugin categories.r   r   r   r3  z
 [bundled]built-inzMemory ProviderzContext EnginezE[dim]No plugins installed and no provider categories available.[/dim]rN  Nz0[dim]Interactive mode requires a terminal.[/dim])r   r   r>  r   r   r  	enumerater   r   r  r  r  r  r<   rz   r   r   r   curses_run_composite_uir8  _run_composite_fallback)r   r|   rA  enabled_setdisabled_setplugin_namesplugin_labelsplugin_selectedir   _versionr   r<  _dr   current_memorycurrent_context
categorieshas_pluginshas_categoriesr  s                        r(   
cmd_toggler    sQ   $$$$$$giiG $%%G"$$K$&&LLMeeO8A'8J8J # #44D(K2=G4.....4Y(((ED!!!U###;4|#;#;""" 233AzN133O	N,FG	?,EFJ
 |$$K*%%N ~ ]^^^RSSS 9 HIIIC&,&
G	= 	= 	= 	= 	= C C Cm_ ,j'	C 	C 	C 	C 	C 	CCs   ;F F87F8c           	          ddl m} t          |          t          |          t                    z   ddd fd}                     |            |             t                      }	t          |          }
t          |          D ]I\  }}|v r+|	                    |           |
                    |           4|
                    |           Jt                      }|	|k    }|
|k    }|s|ret          |	           t          |
           |                    dt          |	           dt          |          t          |	          z
   d           ndk    r|                    d	           d
         r:t                      pd}t                      }|                    d| d| d           dk    sd
         r|                    d           |                                 dS )z<Custom curses screen with checkboxes + category action rows.r   )flush_stdinF)plugins_changedproviders_changedc           	                             d                                           r                                                                                      dj        d                               dj        d                               dj        d                               dj        dk    rdnj	        d           d}d}	 | 
                                 |                                 \  }}	 j        }                                r|                    d          z  }|                     ddd	|dz
  |           |                     ddd
|dz
  j                   n# j        $ r Y nw xY w|dz
  }||k     r|}n|||z   k    r||z
  dz   }d}dk    rF||dz
  k     rf	 j        }                                r|                    d          z  }|                     |dd|dz
  |           n# j        $ r Y nw xY w|dz  }|}	t#          |t%          |d          z             }
t'          |	|
          D ]}||dz
  k    r n|v rdnd}||k    rdnd}d| d| d|          }j        }||k    r3j        }                                r|                    d          z  }	 |                     |d||dz
  |           n# j        $ r Y nw xY w|dz  }||dz
  k     r|dz  }dk    r"||dz
  k     r	 j        }                                r|                    d          z  }|                     |dd|dz
  |           n# j        $ r Y nw xY w|dz  }t+                    D ]\  }\  }}}||dz
  k    r n|z   }||k    rdnd}d| d|dd| }j        }||k    r3j        }                                r|                    d          z  }	 |                     |d||dz
  |           n# j        $ r Y nw xY w|dz  }|                                  |                                 }|j        t3          d          hv r!dk    r|dz
  !z  }nm|j        t3          d          hv r!dk    r|dz   !z  }nE|j        t3          d          hv r/!dk    r't#          !dz
  |t%          d|dz
            z             }n|j        t3          d          hv r,!dk    r$t%          d|t%          d|dz
            z
            }n|j        k    rd}n|j        k    rt%          d!dz
            }n|t3          d          k    r|k     r                    |h           nY|z
  }d|cxk    rk     r~n nB                                  |         \  }}} |            }|r/d d<   ||dk    rtC                      pdntE                      |f|<   #                                } $                                 %                                 | &                    d                                           r                                                                                      dj        d                               dj        d                               dj        d                               dj        dk    rdnj	        d                                d           n|j'        ddhv r|k     rd d<   d S |z
  }d|cxk    rk     r~n n                                  |         \  }}} |            }|r/d d<   ||dk    rtC                      pdntE                      |f|<   #                                } $                                 %                                 | &                    d                                           r                                                                                      dj        d                               dj        d                               dj        d                               dj        dk    rdnj	        d                                d           n|dt3          d           hv rd d<   d S )!Nr   r
   r[   rO   rF        TrX  uV     ↑↓/j/k navigate  PgUp/PgDn page  SPACE toggle  ENTER configure/confirm  ESC donez  General Pluginsu   ✓rV  u   → [z] z  Provider Pluginsz   z<24u    ▸ kjrp      br  r  
      r     q)(curs_set
has_colorsstart_coloruse_default_colors	init_pairCOLOR_GREENCOLOR_YELLOW
COLOR_CYANCOLORSCOLOR_WHITEcleargetmaxyxA_BOLD
color_pairaddnstrA_DIMerrorminmaxrangeA_NORMALr  refreshgetchKEY_UPordKEY_DOWN	KEY_NPAGE	KEY_PPAGEKEY_HOMEKEY_ENDsymmetric_difference_updateendwinr  r  initscrnoechocbreakkeypad	KEY_ENTER)"stdscrcursorscroll_offsetmax_ymax_xhattrvisible_rowsr   sattrplugin_startplugin_stopr  checkarrowlineattrcicat_namecat_current_cat_fncat_idxkey	_cat_name_cat_curcat_fnchangedr  chosenr  n_categories	n_pluginsr  result_holdertotal_itemss"                             r(   _drawz _run_composite_ui.<locals>._drawU  s
    	T   %%'''Q 2B777Q 3R888Q 12666QV]Q%6%6F<NPRSSS~	LLNNN!??,,LE5$$&& 2V..q111Eq!Y	5AAAqlAIv|   
 <    !19L%% &=<777 & 5 9A 1}}uqy== &!,,.. :!V%6%6q%9%99Eq!-@%!)USSSS!<   FA,!)]Sq=Q=Q-QRR|[99  AEAI~~()VHHE()VHHECuCCCCq1ACCD!?DF{{%}!,,.. 9 F$5$5a$8$88Dq!T519dCCCC!<   FAA 519}}Q aA	MM"ME((** 6!2!21!5!55NN1a)=uqy%PPPP|   DQ<Ej<Q<Q  8B8;EAI~~'"nG(/6(9(9HHsELuLLLLL{LLD!?D&((%}!,,.. 9 F$5$5a$8$88Dq!T519dCCCC!<   FAANN,,..Cv}c#hh///??$qjK7F#c((333??$qjK7F)3s88444?? q&3q%!);L;L2LMMF)3s88444?? FSEAI->->$>??F''&&Qa00CI%%66x@@@@  )+BB---------6@n3	8V"(&((" AEM*=> !*PRVWPWPW < > > L*%@%B%B &	.JrN "(!1!1d+++!,,.. d"..000"55777",,Q0BBGGG",,Q0CRHHH",,Q0A2FFF",,QV]Q5F5FFL^`bccc***)2r222I%%7;M"34F  )+BB---------6@n3	8V"(&((" AEM*=> )PRVWPWPW < > > L*%@%B%B &	.JrN "(!1!1d+++!,,.. d"..000"55777",,Q0BBGGG",,Q0CRHHH",,Q0A2FFF",,QV]Q5F5FFL^`bccc***SXX&&37/0}~	s]   A0E2 2
E?>E?4AH 
HH=K
K'&K'AM   
M-,M-4P
PPu%   
[green]✓[/green] General plugins: z
 enabled, z
 disabled.z&
[dim]General plugins unchanged.[/dim]r  r  u*   [green]✓[/green] Memory provider: [bold]z[/bold]  Context engine: [bold]z[/bold]z/[dim]Changes take effect on next session.[/dim]N)r  r  r  rS   wrapperr  r   r   r   r   r  rz   r  r  )r  r  r  r  r  r  r|   r  r  new_enablednew_disabledr  r   prev_enabledenabled_changeddisabled_changed
new_memorynew_contextr  r  r   r  r  s   ` `  `            @@@@@r(   r  r  G  s    100000!!FL!!I z??Ll*K(-EJJMJ J J J J J J J J J J JX NN5KMMM uuKHL\** # #4;;OOD!!!  &&&&T""""#%%L!\1O#x/ A* A+&&&<(((@K8H8H @ @<  3{#3#33@ @ @	
 	
 	
 	
 
Q?@@@() 
133Az
133:J : :%0: : :	
 	
 	

 1}}&9:}GHHHMMOOOOOr*   c           
     T   ddl m}m} t           |d|j                             | rt          |          }t           |d|j                             t           |d|j                             	 t          |          D ]8\  }	}
|	|v r |d|j                  nd}t          d	| d
|	dz   dd|
            9t                       	 t           |d|j                            
                                }|snst          |          dz
  }d|cxk    rt          |           k     rn n|                    |h           n# t          t          t           f$ r Y dS w xY wt                       t                      }t          |          }t          |           D ]I\  }	}|	|v r+|                    |           |                    |           4|                    |           Jt'                      }||k    s||k    rt)          |           t+          |           |rt           |d|j                             t          |          D ]%\  }\  }}}t          d	|dz    d| d| d           &t                       	 t           |d|j                            
                                }|rEt          |          dz
  }d|cxk    rt          |          k     rn n ||         d                      n# t          t          t           f$ r Y nw xY wt                       dS )z1Text-based fallback for the composite plugins UI.r   )Colorscolorz

  Pluginsz
  General Pluginsz&  Toggle by number, Enter to confirm.
Tu   [✓]z[ ]r   rV  r
   z>2z. z"  Toggle # (or Enter to confirm): Nz
  Provider Pluginsr  ]z"  Configure # (or Enter to skip): rO   )hermes_cli.colorsr  r  rz   YELLOWr  DIMr  GREENr   rC   r   rS   r  rB   r   r   r   r   r   r   r  )r  r  r  r  r  r|   r  r  r  r  r   markervalidxr  r  r   r  r  r  r  r  s                         r(   r  r  L  s    0///////	%%v}
-
-...   -_%%ee)6=99:::ee=vzJJKKK	%m44 9 95<=KKz6<888U7677AE777778888GGGEE"F
SSTTZZ\\ #hhl////c,///////66u=== 18<   GGG	  55MM .. 	' 	'GAtF{{%%%$$T****  &&&&')),&&,(*B*Bk***|,,,  ee*FM::;;;3<Z3H3H 	= 	=/B/;;rAv;;;;[;;;<<<<	BFJOOPPVVXXC (XX\,,,,S__,,,,,%JrN1%'''-x8 	 	 	D	 
GGGGGs,   2E  AE E! E!A7K= =LLdict[str, Any]c               l   g }	 t          |           }|                    d          r|                    d           n# t          $ r Y nw xY w	 t	          | |          \  }}}n)# t
          $ r}dt          |          dcY d}~S d}~ww xY wt          |          }	|rdt                      }
t                      }|

                    |           |                    |           t          |
           t          |           d}|dz  }|                                rt          |          }d|||	||d	S )
zPNon-interactive install for the web dashboard. Returns a JSON-serializable dict.r   zEInsecure URL scheme; prefer https:// or git@ for production installs.r   Fr
  r  Nr   T)r
  r   warningsmissing_envafter_install_pathr  )rW   rQ   r   rB   r   r,   r:   r   r   r   r   r   r   r  rh   )rK   r   r   r  r   rH   r   r   excr  endishintaps                 r(   dashboard_install_pluginr"    s    H":..455 	OOW      05I6
 6
 6
2"NN   0 0 0c#hh////////0 ..@AAK  !!
~N###"3D	$	$B	yy{{ 2ww %""  s-   9> 
A
AA% %
B/B BBc                   	 ddl m} n# t          $ r Y dS w xY w	 ddlm}m}  |              |            }|j                                        D ]P\  }}|j        j	        | k    s|| k    r5|j
        D ]+}|                    |          }|r|j        r|j        c c S , nQn# t          $ r Y nw xY w	 ddlm}	  |	            t                      fD ]}
|
                                s|
| z  }|                                rRt!          |          }|                    d          pg D ]+}|                    |          }|r|j        r|j        c c S ,n# t          $ r Y nw xY wdS )u!  Return the toolset key a plugin registers its tools under, or None.

    Queries the live tool registry — the plugin must already be loaded.
    Falls back to reading ``provides_tools`` from plugin.yaml and looking
    up the toolset from the registry for the first tool name found.
    r   )registryN)ru  get_plugin_managerr+  provides_tools)tools.registryr$  rl   r-  ru  r%  _pluginsr  r   r   tools_registered	get_entrytoolsetr,  r7   r   rr   r   )r   r$  ru  r%  manager_keyloaded	tool_namer   r,  r;  r1  r   s                r(   _get_plugin_toolset_keyr0    s(   +++++++   ttKKKKKKKK$$&&#,2244 	 	LD&#t++tt||!'!8 - -I$..y99E - -$},,,,, 0<    >>>>>>,,..? 		- 		-D;;== tI!! -))44!).>!?!?!E2 - -I$..y99E - -$},,,,,		-     4s=   	 
BB" B" "
B/.B/3BE E 
E"!E"c                  t          |           }|sdS ddlm}m}  |            }|                    d          }t          |t                    si }||d<   d}|                                D ]T\  }}	t          |	t                    s|r||	vr|		                    |           d}9||	v r|	
                    |           d}U|r|s
|s|g|d<   d}|r ||           dS dS )zAdd or remove a plugin's toolset from platform_toolsets for all platforms.

    Only acts if the plugin actually provides tools (has a toolset key).
    Nr   r  platform_toolsetsFTcli)r0  r   r  r  r   r   rb   r  r  r   remove)
r   r   toolset_keyr  r  r  r2  r  platformts_lists
             r(   _toggle_plugin_toolsetr8    sS   
 *$//K ::::::::[]]F

#677'.. 8&7"#G.4466 	 	''4(( 	 	')){+++G##NN;'''G  g &7 $/=%  F r*   c               "   t          |           s	dd|  ddS t                      }t                      }|rm| |v r
| |vrd| ddS |                    |            |                    |            t          |           t          |           t          | d           d| ddS | |vr
| |v rd| ddS |                    |            |                    |            t          |           t          |           t          | d           d| ddS )zEnable or disable a plugin in ``config.yaml`` (runtime allow/deny lists).

    For plugins that provide tools (toolsets), also toggles the toolset in
    ``platform_toolsets`` so the agent actually sees the tools in sessions.
    Fr   z' is not installed or bundled.r  T)r
  r   	unchanged)r   )r%  r   r   r   r   r   r  r8  )r   r  r  r  s       r(   "dashboard_set_agent_plugin_enabledr;    sO    $ W&U&U&U&UVVV			B


C >2::$c//4@@@
tD"3tD1111Du===2~~$#++Dt<<<JJtGGDMMMbs4....5999r*   Optional[Path]c                    t                      }	 t          | |d          }n# t          $ r Y dS w xY w|                                r|ndS )z>Resolved path under ``~/.hermes/plugins/<name>`` if it exists.Tr8   N)r7   rJ   rB   r   )r   r;   rH   s      r(   _user_installed_plugin_dirr>  .  s_    ..K&t[tLLL   tt]]__.66$.s   # 
11c                   t          |           }|dd|  dt                       ddS |dz                                  s	dd|  ddS t          |          \  }}|sd|dS d	d
lm} t          | |                       d|v }d| ||dS )z1``git pull`` inside ``~/.hermes/plugins/<name>``.NFr   ' was not found under r?   r  rP   z-' is not a git checkout; cannot pull updates.r   r   r  T)r
  r   r  r:  )r>  r7   rh   r	  r   r   r   )r   rH   r
  msgr   r:  s         r(   dashboard_update_user_pluginrB  8  s    '--F~MMMLNNMMM
 
 	

 VO##%% 
SSSS
 
 	

 #6**GB +c***$$$$$$		***$+I)LLLr*   rH   tuple[bool, str]c           	        t                      }|sdS 	 t          j        |ddgdddt          |                     }n"# t          $ r Y dS t          j        $ r Y dS w xY w|j        dk    r:|j        pd	                                p|j	                                        }d
|pdfS d|j	                                        fS )N)Fr   pullz	--ff-onlyTr   )r   r   r   cwd)Fz$Git pull timed out after 60 seconds.r   r   Fzgit pull failed.)
r)   r   r   r:   r   r   r   r   rC   r   )rH   r   r   r   s       r(   r	  r	  R  s    %''G =<<=fk*F
 
 
  = = =<<<$ = = =<<<= A}"))++Dv}/B/B/D/Dc////$$&&&&s   )> 
AAAc                    t                      }t                      D ]\  }}}}}|| k    r|dk    rdddc S t          |           }|dd|  d| ddS t          j        |           d	| d
S )z7Delete a plugin tree under ``~/.hermes/plugins/`` only.r3  Fz5Bundled plugins cannot be removed from the dashboard.r  Nr   r@  r?   T)r
  r   )r7   r>  r>  r   r   )r   r;   n_verr  src_pathrH   s           r(   dashboard_remove_user_pluginrL  i  s    ..K#8#:#: c c4S%99	))*abbbbb'--F~JJJKJJJ
 
 	

 M&%%%r*   c                v   t          | dd          }|dk    rQd}t          | dd          rd}nt          | dd          rd}t          | j        t          | dd          |	           dS |d
k    rt          | j                   dS |dv rt          | j                   dS |dk    rt          | j                   dS |dk    rt          | j                   dS |dv rt          |            dS |t                       dS ddl
m}  |                                d| d           t          j        d           dS )z$Dispatch hermes plugins subcommands.plugins_actionNinstallr   FT	no_enabler   )r   r   update>   rmr4  	uninstalldisable>   lsr  r   r   z[red]Unknown plugins action: z[/red]r
   )rH  r  rK   r  r   r  r'  r)  rj  r  r   r   rz   r   r   )rB  action
enable_argr   s       r(   plugins_commandrX  {  s   T+T22F
45)) 	JJT;.. 	JO$//	
 	
 	
 	
 	
 	

 
8		49	0	0	049	8		49	9		DI	>	!	!	((((((		FFFFGGGr*   )r   r   )r   r   )r   r:   r;   r   r9   r<   r   r   )rK   r:   r   r:   )rX   r:   r   r:   )ra   r   r   rb   )ra   r   r   rs   )r   rb   r   r   )r   rb   r   rs   )ra   r   rK   r:   r   rs   )r   r:   r;   r   r   rs   )r   r:   r;   r   r   r   )rK   r:   r   r<   r   r   )FN)rK   r:   r   r<   r   r   r   rs   )r   r:   r   rs   )r   r  )r  r  r   rs   )r  r  r   rs   )r   r:   r   r<   )r   r  )r   r:   r  r  r  r  r   r:   )
rA  r  rB  r   r  r  r  r  r   r  r   )rB  rK  r   rs   )r   rk  )r   r:   )r   r<   )r   rs   )rK   r:   r   r<   r   r<   r   r  )r   r:   r   r   )r   r:   r   r<   r   rs   )r   r:   r  r<   r   r  )r   r:   r   r<  )r   r:   r   r  )rH   r   r   rC  )Kr0   
__future__r   	functoolsrO  loggingr   r   r   r   pathlibr   typingr   r   r   r   r   r   hermes_cli.secret_promptr	   	getLoggerr-   rm   	lru_cacher)   rl   r,   r   r7   rJ   rW   r`   rr   r   r   r   r   r   r   r   r  r  r  r   r  r   r   r'  r)  r%  r>  r@  rJ  rj  rr  rz  r  r  r  r  r  r  r  r  r  r"  r0  r8  r;  r>  rB  r	  rL  rX  r1   r*   r(   <module>ra     s1    # " " " " "       				      



                       , , , , , , % % % % % % 9 9 9 9 9 9		8	$	$ Q    DS S S S S9 S S S       	6 6 6 6 6 6r   8         *\ \ \ \$H H H HV   :   
 
 
 
$Z6 Z6 Z6 Z6~ !P P P P Pf%+ %+ %+ %+P( ( ( ("         $      6   4   42 2 2 2j   
 
 
 
?_ ?_ ?_ ?_ ?_N      @            # # # #L# # # #V5C 5C 5C 5CpB B BJ9 9 9x. . . .b+ + + +\# # # #L: : : :B/ / / /M M M M4' ' ' '.& & & &$           r*   