+
    i                        R t ^ RIt^ RIt^ RIt^ RIt^ RIt^ RIt^ RIt^ RIH	t	H
t
 ^ RIHtHtHt ^ RIHtHt ]P$                  ! R4      t. RJOt. RKOtRR.t. RLOt]! 0 RMm4      t]! 0 RNm4      t]! 0 ROm4      tR R	 ltR
 R ltR R ltR R ltR R lt R R lt!R R lt"R R lt#R R lt$R R lt%R R lt&]	 ! R R4      4       t'R  R! lt(R" R# lt)R$ R% lt*R& R' lt+RPR( R) llt,RQR* R+ llt-RQR, R- llt.R. R/ lt/R0 R1 lt0R2 R3 lt1R4 R5 lt2R6 R7 lt3R8 R9 lt4R: R; lt5R< R= lt6R> R? lt7RRR@ RA llt8RB RC lt9RD RE lt:RF RG lt;RH RI lt<R# )SuW  
Profile management for multiple isolated Hermes instances.

Each profile is a fully independent HERMES_HOME directory with its own
config.yaml, .env, memory, sessions, skills, gateway, cron, and logs.
Profiles live under ``~/.hermes/profiles/<name>/`` by default.

The "default" profile is ``~/.hermes`` itself — backward compatible,
zero migration needed.

Usage::

    hermes profile create coder          # fresh profile + bundled skills
    hermes profile create coder --clone  # also copy config, .env, SOUL.md
    hermes profile create coder --clone-all  # full copy of source profile
    coder chat                           # use via wrapper alias
    hermes -p coder chat                 # or via flag
    hermes profile use coder             # set as sticky default
    hermes profile delete coder          # remove profile + alias + service
N)	dataclassfield)PathPurePosixPathPureWindowsPath)ListOptionalz^[a-z0-9][a-z0-9_-]{0,63}$zmemories/MEMORY.mdzmemories/USER.mdc                $    V ^8  d   QhR\         /#    returnr   )formats   "0/home/ubuntu/hermes-agent/hermes_cli/profiles.py__annotate__r   s   s     0 0D 0    c                 H    \         P                  ! 4       R,          R,          # )u   Return the directory where named profiles are stored.

Always ``~/.hermes/profiles/`` — anchored to the user's home,
NOT to the current HERMES_HOME (which may itself be a profile).
This ensures ``coder profile list`` can see all profiles.
.hermesprofilesr   home r   r   _get_profiles_rootr   s   s     99;"Z//r   c                $    V ^8  d   QhR\         /# r
   r   )r   s   "r   r   r   }   s     # #$ #r   c                 :    \         P                  ! 4       R,          # )z2Return the default (pre-profile) HERMES_HOME path.r   r   r   r   r   _get_default_hermes_homer   }   s    99;""r   c                $    V ^8  d   QhR\         /# r
   r   )r   s   "r   r   r      s     9 9$ 9r   c                 $    \        4       R,          # )z2Return the path to the sticky active_profile file.active_profile)r   r   r   r   _get_active_profile_pathr      s    #%(888r   c                $    V ^8  d   QhR\         /# r
   r   )r   s   "r   r   r      s     * *$ *r   c                 H    \         P                  ! 4       R,          R,          # )z)Return the directory for wrapper scripts.z.localbinr   r   r   r   _get_wrapper_dirr#      s    99;!E))r   c                (    V ^8  d   QhR\         RR/# r   namer   Nstr)r   s   "r   r   r      s     
 
 
 
r   c                n    V R8X  d   R# \         P                  V 4      '       g   \        RV : R24      hR# )zARaise ``ValueError`` if *name* is not a valid profile identifier.defaultNzInvalid profile name z%. Must match [a-z0-9][a-z0-9_-]{0,63})_PROFILE_ID_REmatch
ValueErrorr&   s   &r   validate_profile_namer/      sA    y%%#D8 ,) *
 	
 &r   c                0    V ^8  d   QhR\         R\        /# r   r&   r   r(   r   )r   s   "r   r   r      s     ' '# '$ 'r   c                F    V R8X  d   \        4       # \        4       V ,          # )z4Resolve a profile name to its HERMES_HOME directory.r*   )r   r   r.   s   &r   get_profile_dirr4      s!    y'))$&&r   c                0    V ^8  d   QhR\         R\        /# r1   r(   bool)r   s   "r   r   r      s     * * * *r   c                F    V R8X  d   R# \        V 4      P                  4       # )z)Check whether a profile directory exists.r*   T)r4   is_dirr.   s   &r   profile_existsr:      s!    y4 ''))r   c                F    V ^8  d   QhR\         R\        \         ,          /# r1   )r(   r   )r   s   "r   r   r      s        r   c                   V \         9   d   RV  R2# V \        9   d   RV  R2# \        4       p \        P                  ! RV .RR^R7      pVP
                  ^ 8X  d[   VP                  P                  4       pV\        W,          4      8X  d"    W,          P                  4       pRV9   d   R#  RV  R	V R
2#  R#   \         d     Li ; i  \        \        P                  3 d     R# i ; i)zReturn a human-readable collision message, or None if the name is safe.

Checks: reserved names, hermes subcommands, existing binaries in PATH.
'z' is a reserved namez$' conflicts with a hermes subcommandwhichT)capture_outputtexttimeout	hermes -pNz&' conflicts with an existing command ())_RESERVED_NAMES_HERMES_SUBCOMMANDSr#   
subprocessrun
returncodestdoutstripr(   	read_text	ExceptionFileNotFoundErrorTimeoutExpired)r&   wrapper_dirresultexisting_pathcontents   &    r   check_alias_collisionrS      s   
 4&,--""4&<== #$KdODtQ
 !"MM//1MK$6 77*1<<>G"g-# . tfB=/QRSS "  !  z889 s6   AC	 B8 +	C	 8CC	 CC	 	C('C(c                $    V ^8  d   QhR\         /# r
   )r7   )r   s   "r   r   r      s     G G Gr   c                     \        \        4       4      p V \        P                  P	                  RR4      P                  \        P                  4      9   # )z!Check if ~/.local/bin is in PATH.PATH )r(   r#   osenvirongetsplitpathsep)rO   s    r   _is_wrapper_dir_in_pathr]      s9    &()K"**..4::2::FFFr   c                F    V ^8  d   QhR\         R\        \        ,          /# r1   r(   r   r   )r   s   "r   r   r      s        r   c                   \        4       p VP                  RRR7       Y,          p TP	                  RT  R24       TP                  TP                  4       P                  \        P                  ,          \        P                  ,          \        P                  ,          4       T#   \         d   p\        RT RT 24        Rp?R# Rp?ii ; i  \         d   p\        RT RT 24        Rp?R# Rp?ii ; i)	z|Create a shell wrapper script at ~/.local/bin/<name>.

Returns the path to the created wrapper, or None if creation failed.
Tparentsexist_oku   ⚠ Could not create : Nz#!/bin/sh
exec hermes -p z "$@"
u    ⚠ Could not create wrapper at )r#   mkdirOSErrorprint
write_textchmodstatst_modeS_IEXECS_IXGRPS_IXOTH)r&   rO   ewrapper_paths   &   r   create_wrapper_scriptrq      s    
 #$K$6
 %L"<TF' JK<,,.66ETW[WcWccd  %k]"QC89  0bDEs/   B' A>C 'C2C		CC8C33C8c                0    V ^8  d   QhR\         R\        /# r1   r6   )r   s   "r   r   r      s        r   c                    \        4       V ,          pVP                  4       '       d.    VP                  4       pRV9   d   VP                  4        R#  R# R#   \         d     R# i ; i)zARemove the wrapper script for a profile. Returns True if removed.rB   TF)r#   existsrK   unlinkrL   )r&   rp   rR   s   &  r   remove_wrapper_scriptrv      si    #%,L	",,.Gg%##% &
   		s   'A A&%A&c                   D   a  ] tR t^t o RtRtRtRt^ tRt	V 3R lt
RtV tR# )ProfileInfoz$Summary information about a profile.NFc                   < V ^8  d   Qh/ S[ ;R&   S[;R&   S[;R&   S[;R&   S[S[ ,          ;R&   S[S[ ,          ;R&   S[;R&   S[;R&   S[S[,          ;R	&   # )
r   r&   path
is_defaultgateway_runningmodelproviderhas_envskill_count
alias_path)r(   r   r7   r   int)r   __classdict__s   "r   r   ProfileInfo.__annotate__   s      I  J	 
     C=  sm"      % r   r   )__name__
__module____qualname____firstlineno____doc__r}   r~   r   r   r   __annotate_func____static_attributes____classdictcell__)r   s   @r   rx   rx      s*     .
  E"HGK!%J  r   rx   c                0    V ^8  d   QhR\         R\        /# r   profile_dirr   )r   tuple)r   s   "r   r   r     s      D U r   c                   V R,          pVP                  4       '       g   R#  ^ RIp\        VR4      ;_uu_ 4       pVP                  V4      ;'       g    / pRRR4       XP	                  R/ 4      p\        V\        4      '       d   VR3# \        V\        4      '       d<   VP	                  R4      ;'       g    VP	                  R4      VP	                  R4      3# R#   + '       g   i     L; i  \         d    Ru # i ; i)zLRead model/provider from a profile's config.yaml. Returns (model, provider).config.yamlNrr}   r*   r~   )NN)	rt   yamlopen	safe_loadrZ   
isinstancer(   dictrL   )r   config_pathr   fcfg	model_cfgs   &     r   _read_config_modelr     s    -K+s##q..#))rC $GGGR(	i%%d?"i&&==+EEy}}W/Ey}}U_G``` $#  s:   C1 C3C1 -C1 9"C1 C1 C.	)C1 1D Dc                0    V ^8  d   QhR\         R\        /# r   )r   r7   )r   s   "r   r   r     s        r   c           	        V R,          pVP                  4       '       g   R#  VP                  4       P                  4       pV'       g   R# VP                  R4      '       d   \        P
                  ! V4      MR\        V4      /p\        VR,          4      p\        P                  ! V^ 4       R#   \        P                  \        \        \        \        \        \        3 d     R# i ; i)z<Check if a gateway is running for a given profile directory.gateway.pidF{pidT)rt   rK   rJ   
startswithjsonloadsr   rX   killJSONDecodeErrorKeyErrorr-   	TypeErrorProcessLookupErrorPermissionErrorrf   )r   pid_filerawdatar   s   &    r   _check_gateway_runningr     s    ]*H??
  "((*"%.."5"5tzz#E3s8;L$u+
Q  (J	: s   %B0 B0 "AB0 04C('C(c                0    V ^8  d   QhR\         R\        /# r   )r   r   )r   s   "r   r   r   0  s     	 	t 	 	r   c                    V R,          pVP                  4       '       g   ^ # ^ pVP                  R4       F0  pR\        V4      9  g   K  R\        V4      9  g   K'  V^,          pK2  	  V# )z$Count installed skills in a profile.skillszSKILL.mdz/.hub/z/.git/)r9   rglobr(   )r   
skills_dircountmds   &   r   _count_skillsr   0  s_    x'JEz*3r7"xs2w'>QJE + Lr   c                :    V ^8  d   QhR\         \        ,          /# r
   )r   rx   )r   s   "r   r   r   @  s     + +tK( +r   c                    . p \        4       p\        4       pVP                  4       '       dW   \        V4      w  r4V P	                  \        RVR\        V4      VVVR,          P                  4       \        V4      R7      4       \        4       pVP                  4       '       d   \        VP                  4       4       F  pVP                  4       '       g   K  VP                  p\        P                  V4      '       g   KD  \        V4      w  r4W,          pT P	                  \        TTR\        V4      TTVR,          P                  4       \        V4      VP                  4       '       d   TMRR7	      4       K  	  V # )z4Return info for all profiles, including the default.r*   T.env)r&   rz   r{   r|   r}   r~   r   r   FN)	r&   rz   r{   r|   r}   r~   r   r   r   )r#   r   r9   r   appendrx   r   rt   r   r   sortediterdirr&   r+   r,   )	r   rO   default_homer}   r~   profiles_rootentryr&   r   s	            r   list_profilesr   @  sC   H"$K ,-L,\:2<@!F*224%l3	
 		 '(MM1134E<<>>::D!''--07OE$+JOOK  6u =!//1)%0)3):):)<)<:$
 
 5( Or   c                v    V ^8  d   QhR\         R\        \         ,          R\        R\        R\        R\        /# )r   r&   
clone_from	clone_allclone_configno_aliasr   )r(   r   r7   r   )r   s   "r   r   r   n  sP     Q Q
QQ Q 	Q
 Q 
Qr   c                   \        V 4       V R8X  d   \        R4      h\        V 4      pVP                  4       '       d   \	        RV  RV 24      hRpVf   V'       g	   V'       dZ   Vf   ^ RIHp V! 4       pM\        V4       \        V4      pVP                  4       '       g   \        RT;'       g    R R	V 24      hV'       dF   V'       d>   \        P                  ! We4       \         F  pWX,          P                  R
R7       K  	  V# VP                  R
R
R7       \         F  p	WY,          P                  R
R
R7       K  	  Ve   \         F@  p
Wj,          pVP                  4       '       g   K#  \        P                   ! WV
,          4       KB  	  \"         F^  pWl,          pVP                  4       '       g   K#  W\,          pVP$                  P                  R
R
R7       \        P                   ! W4       K`  	  V# )a  Create a new profile directory.

Parameters
----------
name:
    Profile identifier (lowercase, alphanumeric, hyphens, underscores).
clone_from:
    Source profile to clone from. If ``None`` and clone_config/clone_all
    is True, defaults to the currently active profile.
clone_all:
    If True, do a full copytree of the source (all state).
clone_config:
    If True, copy only config files (config.yaml, .env, SOUL.md).
no_alias:
    If True, skip wrapper script creation.

Returns
-------
Path
    The newly created profile directory.
r*   uS   Cannot create a profile named 'default' — it is the built-in profile (~/.hermes).	Profile '' already exists at Nget_hermes_homezSource profile 'activez' does not exist at T
missing_okra   )r/   r-   r4   rt   FileExistsErrorhermes_constantsr   r9   rM   shutilcopytree_CLONE_ALL_STRIPru   re   _PROFILE_DIRS_CLONE_CONFIG_FILEScopy2_CLONE_SUBDIR_FILESparent)r&   r   r   r   r   r   
source_dirr   stalesubdirfilenamesrcrelpathdsts   &&&&&         r   create_profiler   n  s   8 $ya
 	
 "$'K	$/CK=QRR Jl8(*J!*-(4J  ""#":#9#9"::Nzl[  Z
0%E ((D(9 &. ' 	$6#F!(((E $ !/ +::<<LLH&<= 0 / *::<<%/CJJ$$TD$ALL* / r   c                R    V ^8  d   QhR\         R\        R\        \        ,          /# )r   r   quietr   )r   r7   r   r   )r   s   "r   r   r     s%      T $ 8D> r   c           	     Z   \        \        4      P                  P                  P                  4       p \        P
                  ! \        P                  RR./ \        P                  CR\        V 4      /C\        V4      RR^<R7      pVP                  ^ 8X  dO   VP                  P                  4       '       d/   \        P                  ! VP                  P                  4       4      # V'       gf   \!        RVP                   24       VP"                  P                  4       '       d.   \!        RVP"                  P                  4       R,           24       R	#   \        P$                   d    T'       g   \!        R
4        R	# \&         d"   pT'       g   \!        RT 24        R	p?R	# R	p?ii ; i)zSeed bundled skills into a profile via subprocess.

Uses subprocess because sync_skills() caches HERMES_HOME at module level.
Returns the sync result dict, or None on failure.
z-cziimport json; from tools.skills_sync import sync_skills; r = sync_skills(quiet=True); print(json.dumps(r))HERMES_HOMET)envcwdr?   r@   rA   u%   ⚠ Skill seeding returned exit code z  :N   NNu!   ⚠ Skill seeding timed out (60s)u   ⚠ Skill seeding failed: )r   __file__r   resolverF   rG   sys
executablerX   rY   r(   rH   rI   rJ   r   r   rg   stderrrN   rL   )r   r   project_rootrP   ro   s   &&   r   seed_profile_skillsr     sG    >((//779L^^TAB @2::?}c+.>?L!dB
 !fmm&9&9&;&;::fmm113449&:K:K9LMN}}""$$6==..06789$$ 56 .qc23s=   BE 7-E %E -A%E F*1F*?F*F*	F%%F*c                <    V ^8  d   QhR\         R\        R\        /# )r   r&   yesr   )r(   r7   r   )r   s   "r   r   r     s&     Z Z Z4 ZD Zr   c                   \        V 4       V R8X  d   \        R4      h\        V 4      pVP                  4       '       g   \	        RV  R24      h\        V4      w  r4\        V4      p\        V4      p\        RV  24       \        RV 24       V'       d$   \        RV 2V'       d   RV R	2MR
,           4       V'       d   \        RV 24       R.p^ RI	H
pHp	 \        4       V ,          p
V
P                  4       pV'       d   VP                  RV
 R	24       \        R4       V F  p\        RV 24       K  	  V'       d   \        R4       V'       g<   \        4         \        RV  R24      P!                  4       pY8w  d   \        R4       T# \'        W4       V'       d   \)        V4       V'       d    \+        V 4      '       d   \        RV
 24        \,        P.                  ! V4       \        RV 24        \3        4       pW8X  d   \5        R4       \        R4       \        RT  R24       T#   \"        \$        3 d    \        R4       Tu # i ; i  \0         d   p\        RT RT 24        Rp?L}Rp?ii ; i  \0         d     Lki ; i)zDelete a profile, its wrapper script, and its gateway service.

Stops the gateway if running. Disables systemd/launchd service first
to prevent auto-restart.

Returns the path that was removed.
r*   zZCannot delete the default profile (~/.hermes).
To remove everything, use: hermes uninstallr   ' does not exist.z

Profile: z	Path:    z	Model:   z (rC   rW   z	Skills:  z;All config, API keys, memories, sessions, skills, cron jobs)_profile_suffixget_service_namezCommand alias (z
This will permanently delete:u     • u0     ⚠ Gateway is running — it will be stopped.zType 'z' to confirm: z
Cancelled.z
Cancelled.u   ✓ Removed u   ⚠ Could not remove rd   Nu#   ✓ Active profile reset to defaultz

Profile 'z
' deleted.)r/   r-   r4   r9   rM   r   r   r   rg   hermes_cli.gatewayr   r   r#   rt   r   inputrJ   KeyboardInterruptEOFError_cleanup_gateway_service_stop_gateway_processrv   r   rmtreerL   get_active_profileset_active_profile)r&   r   r   r}   r~   
gw_runningr   itemsr   r   rp   has_wrapperitemconfirmro   r   s   &&              r   delete_profiler    ss    $y:
 	

 "$'K)D61B CDD )5OE'4J,K	Kv
	Ik]
#$	%!r(1%5rJK	+'( 	FE
 E#%,L%%'K|nA67	+-tfo @B 	fTF.9:@@BG ?, T/ k*  &&L/0:k"[M*+
#%>y)78 
KvZ
()I "8, 	.!	.  :%k]"QC899:  s<   H1 $I :&I> 1III; I66I;>JJc                4    V ^8  d   QhR\         R\        RR/# )r   r&   r   r   Nr2   )r   s   "r   r   r   @  s!     -* -*3 -*T -*d -*r   c                   ^ RI p\        P                  P                  R4      p \	        V4      \        P                  R&   ^ RIHpHp VP                  4       R8X  d   V! 4       p\        P                  ! 4       R,          R,          R,          V R2,          pVP                  4       '       dz   \        P                  ! R	R
RV.RR^
R7       \        P                  ! R	R
RV.RR^
R7       VP                  RR7       \        P                  ! . RORR^
R7       \        RV R24       MuVP                  4       R8X  da   V! 4       pVP                  4       '       dD   \        P                  ! RR\	        V4      .RR^
R7       VP                  RR7       \        R4       Ve   V\        P                  R&   R# R\        P                  9   d   \        P                  R R# R#   \          d   p	\        RT	 24        Rp	?	LaRp	?	ii ; i  Te   T\        P                  R&   i R\        P                  9   d   \        P                  R i i ; i)z9Disable and remove systemd/launchd service for a profile.Nr   )r   get_launchd_plist_pathLinuxz.configsystemduserz.service	systemctl--userdisableTF)r?   checkrA   stopr   u   ✓ Service z removedDarwin	launchctlunloadu   ✓ Launchd service removedu   ⚠ Service cleanup: )r
  r  zdaemon-reload)platformrX   rY   rZ   r(   r   r   r  systemr   r   rt   rF   rG   ru   rg   rL   )
r&   r   	_platformold_homer   r  svc_namesvc_file
plist_pathro   s
   &&        r   r   r   @  s     zz~~m,H&*$'$4

=!O(')Hyy{Y.:VC
RZF[[H   (Ix@#'ub  (FH=#'ub 40<#'ub XJh788+/1J  "" (C
O<#'ub !!T!235 (0BJJ}%bjj(

=) )  +%aS)**+ (0BJJ}%bjj(

=) )sE   B	G! /A9G! (H )1G! AG! !H,G?:H ?HH AIc                (    V ^8  d   QhR\         RR/# )r   r   r   Nr   )r   s   "r   r   r   p  s     2 2t 2 2r   c                4   ^ RI p^ RIpV R,          pVP                  4       '       g   R#  VP                  4       P	                  4       pVP                  R4      '       d   \        P                  ! V4      MR\        V4      /p\        VR,          4      p\        P                  ! WaP                  4       \        ^4       F,  pVP                  R4        \        P                  ! V^ 4       K.  	   \        P                  ! WaP                   4       \        RV R24       R#   \         d    \        RT R24         R# i ; i  \         d     L@i ; i  \        \"        3 d    \        R	4        R# \$         d   p\        R
T 24        Rp?R# Rp?ii ; i)z0Stop a running gateway process via its PID file.Nr   r   r   g      ?u   ✓ Gateway stopped (PID rC   u   ✓ Gateway force-stopped (PID u   ✓ Gateway already stoppedu   ⚠ Could not stop gateway: )signaltimert   rK   rJ   r   r   r   r   rX   r   SIGTERMrangesleepr   rg   SIGKILLr   rL   )	r   _signal_timer   r   r   r   _ro   s	   &        r   r   r   p  sJ   ]*H??2  "((*"%.."5"5tzz#E3s8;L$u+
__%rAKKQ 	GGC) 	/uA67 & 1#a89 " 		 0 -+, 2,QC0112sr   4E  A4E D",E 1 E E "E<E  EE EE EE F4F=F>FFc                $    V ^8  d   QhR\         /# r
   r'   )r   s   "r   r   r     s      C r   c                     \        4       p  V P                  4       P                  4       pV'       g   R# V#   \        \        \
        3 d     R# i ; i)zlRead the sticky active profile name.

Returns ``"default"`` if no active_profile file exists or it's empty.
r*   )r   rK   rJ   rM   UnicodeDecodeErrorrf   )rz   r&   s     r   r   r     sK    
 $%D~~%%'17; s   &6 6 AAc                (    V ^8  d   QhR\         RR/# r%   r'   )r   s   "r   r   r     s      S T r   c                f   \        V 4       V R8w  d#   \        V 4      '       g   \        RV  RV  24      h\        4       pVP                  P                  RRR7       V R8X  d   VP                  RR7       R	# VP                  R4      pVP                  V R,           4       VP                  V4       R	# )
zdSet the sticky active profile.

Writes to ``~/.hermes/active_profile``. Use ``"default"`` to clear.
r*   r   8' does not exist. Create it with: hermes profile create Tra   r   .tmp
N)
r/   r:   rM   r   r   re   ru   with_suffixrh   replace)r&   rz   tmps   &  r   r   r     s    
 $y!5!5v 559F<
 	

 $%DKKdT2yt$ v&td{#Dr   c                $    V ^8  d   QhR\         /# r
   r'   )r   s   "r   r   r     s       r   c                    ^ RI Hp  V ! 4       pVP                  4       p\        4       P                  4       pW#8X  d   R# \	        4       P                  4       p VP                  V4      pVP                  p\        V4      ^8X  d,   \        P                  V^ ,          4      '       d
   V^ ,          # R#   \         d     R# i ; i)a  Infer the current profile name from HERMES_HOME.

Returns ``"default"`` if HERMES_HOME is not set or points to ``~/.hermes``.
Returns the profile name if HERMES_HOME points into ``~/.hermes/profiles/<name>``.
Returns ``"custom"`` if HERMES_HOME is set to an unrecognized path.
r   r*   custom)r   r   r   r   r   relative_topartslenr+   r,   r-   )r   hermes_homeresolveddefault_resolvedr   relr3  s          r   get_active_profile_namer9    s     1!#K""$H/199;#&(002M""=1		u:?~33E!H==8O   s   AB1 &B1 1C ?C c                $    V ^8  d   QhR\         /# )r   root_dirr   )r   s   "r   r   r     s      T r   c                   a  R V 3R llpV# )zReturn an *ignore* callable for :func:`shutil.copytree`.

At the root level it excludes everything in ``_DEFAULT_EXPORT_EXCLUDE_ROOT``.
At all levels it excludes ``__pycache__``, sockets, and temp files.
c                <    V ^8  d   QhR\         R\        R\        /# )r   	directorycontentsr   )r(   listset)r   s   "r   r   ,_default_export_ignore.<locals>.__annotate__  s!      3 $ 3 r   c                   < \        4       pV FN  pVR 8X  g   VP                  R4      '       d   VP                  V4       K4  VR9   g   K=  VP                  V4       KP  	  \        V 4      S8X  d   VP	                  R V 4       4       V# )__pycache__c              3   >   "   T F  q\         9   g   K  Vx  K  	  R # 5iN)_DEFAULT_EXPORT_EXCLUDE_ROOT).0cs   & r   	<genexpr>:_default_export_ignore.<locals>._ignore.<locals>.<genexpr>  s     Th7S2S11hs   
)z.sockr*  )zpackage.jsonzpackage-lock.json)rA  endswithaddr   update)r>  r?  ignoredr   r;  s   &&  r   _ignore'_default_export_ignore.<locals>._ignore  sq    uE%8I)J)JE"??E"  	?h&NNThTTr   r   )r;  rP  s   f r   _default_export_ignorerR    s      Nr   c                <    V ^8  d   QhR\         R\         R\        /# )r   r&   output_pathr   r2   )r   s   "r   r   r     s!     ( ( (3 (4 (r   c           	     .  a	 ^ RI p\        V 4       \        V 4      pVP                  4       '       g   \	        RV  R24      h\        V4      p\        V4      P                  R4      P                  R4      pV R8X  d|   VP                  4       ;_uu_ 4       p\        V4      R,          p\        P                  ! VV\        V4      R7       \        P                  ! VRVR4      p\        V4      uuRRR4       # VP                  4       ;_uu_ 4       p\        V4      V ,          pR	R
0o	\        P                  ! VVV	3R lR7       \        P                  ! VRW`4      p\        V4      uuRRR4       #   + '       g   i     L; i  + '       g   i     R# ; i)zEExport a profile to a tar.gz archive.

Returns the output file path.
Nr   r   z.tar.gzz.tgzr*   )ignoregztar	auth.jsonr   c                 (   < S\        V4      ,          # rF  )rA  )dr?  _CREDENTIAL_FILESs   &&r   <lambda> export_profile.<locals>.<lambda>  s    '83x='Hr   )tempfiler/   r4   r9   rM   r   r(   removesuffixTemporaryDirectoryr   r   rR  make_archive)
r&   rT  r^  r   outputbasetmpdirstagedrP   r[  s
   &&       @r   export_profilerf    sL   
 $!$'K)D61B CDD+Fv;##I.;;FCDy ((**f&\I-FOO-k:
 ((w	JF< +* 
	$	$	&	&&f$(&1H	

 $$T7FAF| 
'	& +* 
'	&	&s   AE0AF0F 	F	c                F    V ^8  d   QhR\         R\        \         ,          /# )r   member_namer   )r(   r   )r   s   "r   r   r     s      # $s) r   c                   V P                  RR4      p\        V4      p\        V 4      pV'       d?   VP                  4       '       g)   VP                  4       '       g   VP                  '       d   \        RV  24      hVP                   Uu. uF  qDR9  g   K  VNK  	  ppV'       d;   \        ;QJ d    R V 4       F  '       g   K   RM	  RM! R V 4       4      '       d   \        RV  24      hV# u upi )z4Return safe path parts for a profile archive member.\/zUnsafe archive member path: c              3   *   "   T F	  qR 8H  x  K  	  R# 5i)z..Nr   )rH  parts   & r   rJ  3_normalize_profile_archive_parts.<locals>.<genexpr>.  s     7s   TF)rW   .)r-  r   r   is_absolutedriver-   r3  any)rh  normalized_name
posix_pathwindows_pathrm  r3  s   &     r    _normalize_profile_archive_partsrv    s    !))$4O/J";/L !!####%%7}EFF(..H.di2GTT.EHCC77CCC77777}EFFL Is   C2C2c                4    V ^8  d   QhR\         R\         RR/# )r   archivedestinationr   Nr   )r   s   "r   r   r   3  s!      4 d t r   c                   ^ RI pVP                  V R4      ;_uu_ 4       pVP                  4        EF:  p\        VP                  4      pVP
                  ! V!  pVP                  4       '       d   VP                  RRR7       KT  VP                  4       '       g   \        RVP                   24      hVP                  P                  RRR7       VP                  V4      pVf   \        RVP                   24      hT;_uu_ 4        \        VR4      ;_uu_ 4       p\        P                  ! Wx4       RRR4       RRR4        \        P                  ! WdP                   R,          4       EK=  	  RRR4       R#   + '       g   i     LO; i  + '       g   i     LZ; i  \"         d     EK~  i ; i  + '       g   i     R# ; i)	zAExtract a profile archive without allowing path escapes or links.Nr:gzTra   z!Unsupported archive member type: zCannot read archive member: wbi  )tarfiler   
getmembersrv  r&   joinpathisdirre   isfiler-   r   extractfiler   copyfileobjrX   ri   moderf   )	rx  ry  r}  tfmemberr3  target	extractedr   s	   &&       r   _safe_extract_profile_archiver  3  sE   	gv	&	&"mmoF4V[[AE ))51F||~~TD9==?? 7}E  MMt<v.I  #?}!MNND..#""92 /u!45- & 
'	&& /.
  1 
'	&	&sg   A:F2A,F2FE92F:F2'F*F29F	FFF2F/	*F2.F/	/F22G	c                R    V ^8  d   QhR\         R\        \         ,          R\        /# )r   archive_pathr&   r   r_   )r   s   "r   r   r   S  s%     : : :HSM :T :r   c           	     t   ^ RI p\        V 4      pVP                  4       '       g   \        RV 24      hVP	                  VR4      ;_uu_ 4       pVP                  4        UUu0 uFI  p\        VP                  4      p\        V4      ^8  g   VP                  4       '       g   K@  V^ ,          kKK  	  pppV'       gR   VP                  4        Uu0 uF7  pVP                  4       '       g   K  \        VP                  4      ^ ,          kK9  	  ppRRR4       T;'       g#    \        X4      ^8X  d   VP                  4       MRpV'       g   \        R4      hVR8X  d   \        R4      h\        V4       \        V4      p	V	P                  4       '       d   \        RV RV	 24      h\        4       p
V
P!                  R	R	R
7       \#        W:4       T
X'       d   VP                  4       MT,          pW8w  d(   VP                  4       '       d   VP%                  V	4       V	# u uppi u upi   + '       g   i     EL"; i)zImport a profile from a tar.gz archive.

If *name* is not given, infers it from the archive's top-level directory.
Returns the imported profile directory.
NzArchive not found: r{  zpCannot determine profile name from archive. Specify it explicitly: hermes profile import <archive> --name <name>r*   u   Cannot import as 'default' — that is the built-in root profile (~/.hermes). Specify a different name: hermes profile import <archive> --name <name>r   r   Tra   )r}  r   rt   rM   r   r~  rv  r&   r4  r  popr-   r/   r4   r   r   re   r  rename)r  r&   r}  rx  r  r  r3  top_dirsinferred_namer   r   r  s   &&          r   import_profiler  S  s    < G>>"5gY ?@@ 
gv	&	&" --/
):6;;G5zA~ E!HH) 	 
  !mmo-F<<> A0=a@@-   
' LLs8}/AX\\^tMS
 	
 	!V
 	

 -(!-0K	-8L[MZ[[&(Mt4!'9 8OII$4$4$6$6%Y
 
'	&	&s6   H&"=H
$H
1H&H!+ H!H&H&&H7	c                <    V ^8  d   QhR\         R\         R\        /# )r   old_namenew_namer   r2   )r   s   "r   r   r     s!     / /S /C /D /r   c                   \        V 4       \        V4       V R8X  d   \        R4      hVR8X  d   \        R4      h\        V 4      p\        V4      pVP                  4       '       g   \	        RV  R24      hVP                  4       '       d   \        RV R24      h\        V4      '       d   \        W4       \        V4       VP                  V4       \        RVP                   RVP                   24       \        V 4       \        V4      pV'       g   \        V4       \        R	V 24       M\        R
V RV 24        \!        4       V 8X  d   \#        V4       \        RV 24       V#   \$         d     T# i ; i)zjRename a profile: directory, wrapper script, service, active_profile.

Returns the new profile directory.
r*   z"Cannot rename the default profile.u.   Cannot rename to 'default' — it is reserved.r   r   z' already exists.u   ✓ Renamed u    → u   ✓ Alias updated: u   ⚠ Cannot create alias 'u   ' — u   ✓ Active profile updated: )r/   r-   r4   r9   rM   rt   r   r   r   r   r  rg   r&   rv   rS   rq   r   r   rL   )r  r  old_dirnew_dir	collisions   &&   r   rename_profiler    si   
 (#(#9=>>9IJJh'Gh'G>>)H:5F GHH~~	(3DEFF g&& 3g& NN7	LeGLL>
:; (#%h/Ih'#H:./)(6)EF8+x(0
;< N  Ns   (E, ,E;:E;c                $    V ^8  d   QhR\         /# r
   r'   )r   s   "r   r   r     s     / /# /r   c                     R# )z;Generate a bash completion script for hermes profile names.au  # Hermes Agent profile completion
# Add to ~/.bashrc: eval "$(hermes completion bash)"

_hermes_profiles() {
    local profiles_dir="$HOME/.hermes/profiles"
    local profiles="default"
    if [ -d "$profiles_dir" ]; then
        profiles="$profiles $(ls "$profiles_dir" 2>/dev/null)"
    fi
    echo "$profiles"
}

_hermes_completion() {
    local cur prev
    cur="${COMP_WORDS[COMP_CWORD]}"
    prev="${COMP_WORDS[COMP_CWORD-1]}"

    # Complete profile names after -p / --profile
    if [[ "$prev" == "-p" || "$prev" == "--profile" ]]; then
        COMPREPLY=($(compgen -W "$(_hermes_profiles)" -- "$cur"))
        return
    fi

    # Complete profile subcommands
    if [[ "${COMP_WORDS[1]}" == "profile" ]]; then
        case "$prev" in
            profile)
                COMPREPLY=($(compgen -W "list use create delete show alias rename export import" -- "$cur"))
                return
                ;;
            use|delete|show|alias|rename|export)
                COMPREPLY=($(compgen -W "$(_hermes_profiles)" -- "$cur"))
                return
                ;;
        esac
    fi

    # Top-level subcommands
    if [[ "$COMP_CWORD" == 1 ]]; then
        local commands="chat model gateway setup status cron doctor config skills tools mcp sessions profile update version"
        COMPREPLY=($(compgen -W "$commands" -- "$cur"))
    fi
}

complete -F _hermes_completion hermes
r   r   r   r   generate_bash_completionr    s    -r   c                $    V ^8  d   QhR\         /# r
   r'   )r   s   "r   r   r     s       r   c                     R# )z:Generate a zsh completion script for hermes profile names.a  #compdef hermes
# Hermes Agent profile completion
# Add to ~/.zshrc: eval "$(hermes completion zsh)"

_hermes() {
    local -a profiles
    profiles=(default)
    if [[ -d "$HOME/.hermes/profiles" ]]; then
        profiles+=("${(@f)$(ls $HOME/.hermes/profiles 2>/dev/null)}")
    fi

    _arguments \
        '-p[Profile name]:profile:($profiles)' \
        '--profile[Profile name]:profile:($profiles)' \
        '1:command:(chat model gateway setup status cron doctor config skills tools mcp sessions profile update version)' \
        '*::arg:->args'

    case $words[1] in
        profile)
            _arguments '1:action:(list use create delete show alias rename export import)' \
                        '2:profile:($profiles)'
            ;;
    esac
}

_hermes "$@"
r   r   r   r   generate_zsh_completionr    s    r   c                0    V ^8  d   QhR\         R\         /# )r   profile_namer   r'   )r   s   "r   r   r     s      c c r   c                    \        V 4       \        V 4      pV R8w  d(   VP                  4       '       g   \        RV  RV  24      h\	        V4      # )zResolve a profile name to a HERMES_HOME path string.

Called early in the CLI entry point, before any hermes modules
are imported, to set the HERMES_HOME environment variable.
r*   r   r)  )r/   r4   r9   rM   r(   )r  r   s   & r   resolve_profile_envr    s]     ,'!,/Ky ););)=)=~ &55AND
 	

 {r   )memoriessessionsr   skinslogsplans	workspacecron)r   r   zSOUL.md)r   gateway_state.jsonprocesses.json>   r"   r  r   	sandboxesaudio_cachecheckpointsimage_cachenode_modulesr   document_cachebrowser_screenshotsr   state.dbrX  	auth.lock
.worktrees
errors.logr   hermes-agentstate.db-shmstate.db-wal.update_checkr  .hermes_historyhermes_state.dbresponse_store.dbr  response_store.db-shmresponse_store.db-wal>   r.  rootsudotesthermesr*   >   acpmcpchatr  loginr}   setuptoolsconfigdoctorhonchologoutr   statusrN  gatewaypairingpluginsprofileversioninsightsr  whatsapp	uninstall)NFFF)FrF  )=r   r   rX   rer   rj   rF   r   dataclassesr   r   pathlibr   r   r   typingr   r   compiler+   r   r   r   r   	frozensetrG  rD   rE   r   r   r   r#   r/   r4   r:   rS   r]   rq   rv   rx   r   r   r   r   r   r   r  r   r   r   r   r9  rR  rf  rv  r  r  r  r  r  r  r   r   r   <module>r     sa  *  	 	    
 ( 8 8 !9:	      ) *   2   
   !  0#
9
*
'*BG,& 
& 
& 
&&$	 +\QhBZz-*`2L0>0(V(@:B/l/dFr   