+
    iZj                        R t ^ RIt^ RIt^ RIt^ RIt^ RIt^ RIt^ RIHt ^ RI	H
t
 ^ RIHtHtHt ]P                  ! ]4      t ^ RIHtHtHt RtR R	 lt^ RIt]
! 4       t]R
,          t^@tRtRtRt]P@                  ! R4      t!0 RPmt"R R lt#R R lt$R R lt%R R lt&RQR R llt'RRR R llt(R R lt)R R lt*RSR R  llt+RRR! R" llt,R# R$ lt-RTR% R& llt.R' R( lt/R) R* lt0R+ R, lt1RUR- R. llt2R/R0R1R2R3R4R5R6R7R4R8R9. RVOR1R:/R/R4R8R1R;/R<R4R8R1R=/R>R4R8R1R?/R@R4R8R1RA/RBR4RCR1RD/RER4R8R1RF/RGR4R8R1RH/RIR4R8R1RJ//	RKR7R/.//t3^ RLI4H5t5 ]5Pl                  ! R0R
]3RM RNRO7       R#   ] d    Rt ELi ; i)Wu  
Skill Manager Tool -- Agent-Managed Skill Creation & Editing

Allows the agent to create, update, and delete skills, turning successful
approaches into reusable procedural knowledge. New skills are created in
~/.hermes/skills/. Existing skills (bundled, hub-installed, or user-created)
can be modified or deleted wherever they live.

Skills are the agent's procedural memory: they capture *how to do a specific
type of task* based on proven experience. General memory (MEMORY.md, USER.md) is
broad and declarative. Skills are narrow and actionable.

Actions:
  create     -- Create a new skill (SKILL.md + directory structure)
  edit       -- Replace the SKILL.md content of a user skill (full rewrite)
  patch      -- Targeted find-and-replace within SKILL.md or any supporting file
  delete     -- Remove a user skill entirely
  write_file -- Add/overwrite a supporting file (reference, template, script, asset)
  remove_file-- Remove a supporting file from a user skill

Directory layout for user skills:
    ~/.hermes/skills/
    ├── my-skill/
    │   ├── SKILL.md
    │   ├── references/
    │   ├── templates/
    │   ├── scripts/
    │   └── assets/
    └── category-name/
        └── another-skill/
            └── SKILL.md
N)Path)get_hermes_home)DictAnyOptional)
scan_skillshould_allow_installformat_scan_reportTFc                F    V ^8  d   QhR\         R\        \        ,          /# )   	skill_dirreturn)r   r   str)formats   "5/home/ubuntu/hermes-agent/tools/skill_manager_tool.py__annotate__r   8   s      D Xc]     c                <   \         '       g   R#  \        V RR7      p\        V4      w  r#VRJ d   \        V4      pRV RV 2# Vf$   \        V4      p\        P                  RV4       R#  R#   \         d$   p\        P                  RYR	R
7        Rp?R# Rp?ii ; i)zOScan a skill directory after write. Returns error string if blocked, else None.Nzagent-created)sourceFz"Security scan blocked this skill (z):
z-Agent-created skill has security findings: %szSecurity scan failed for %s: %sTexc_info)_GUARD_AVAILABLEr   r   r	   loggerwarning	Exception)r   resultallowedreasonreportes   &     r   _security_scan_skillr    8   s    WIo>.v6e'/F7xtF8LL?'/FNNJFS    W8)QUVVWs   2A- %A- -B8BBskillsi   i i   z^[a-z0-9][a-z0-9._-]*$c                $    V ^8  d   QhR\         /# )r   r   )bool)r   s   "r   r   r   _   s       r   c                     R# )zBSkill management has no external requirements -- always available.T r%   r   r   check_skill_manage_requirementsr&   _   s    r   c                F    V ^8  d   QhR\         R\        \         ,          /# r   namer   r   r   )r   s   "r   r   r   h   s       # r   c                    V '       g   R# \        V 4      \        8  d   R\         R2# \        P                  V 4      '       g   RV  R2# R# )z>Validate a skill name. Returns error message or None if valid.zSkill name is required.zSkill name exceeds  characters.zInvalid skill name 'ze'. Use lowercase letters, numbers, hyphens, dots, and underscores. Must start with a letter or digit.N)lenMAX_NAME_LENGTHVALID_NAME_REmatch)r)   s   &r   _validate_namer1   h   sR    (
4y?"$_$5\BBt$$"4& )Q R	
 r   c                \    V ^8  d   QhR\         \        ,          R\         \        ,          /# )r   categoryr   )r   r   )r   s   "r   r   r   v   s"      # 8C= r   c                   V f   R# \        V \        4      '       g   R# V P                  4       p V '       g   R# RV 9   g   RV 9   d   RV  R2# \        V 4      \        8  d   R\         R2# \
        P                  V 4      '       g   RV  R2# R# )	zFValidate an optional category name used as a single directory segment.NzCategory must be a string./\zInvalid category 'zn'. Use lowercase letters, numbers, hyphens, dots, and underscores. Categories must be a single directory name.zCategory exceeds r,   )
isinstancer   stripr-   r.   r/   r0   )r3   s   &r   _validate_categoryr9   v   s    h$$+~~H
h$(* 
 +Z Z	
 8}&"?"3<@@x(( 
 +Z Z	
 r   c                F    V ^8  d   QhR\         R\        \         ,          /# )r   contentr   r*   )r   s   "r   r   r      s     $ $3 $8C= $r   c                z   V P                  4       '       g   R# V P                  R4      '       g   R# \        P                  ! RV R,          4      pV'       g   R# V ^VP	                  4       ^,            p \
        P                  ! V4      p\        T\        4      '       g   R	# R
T9  d   R# RT9  d   R# \        \        TR,          4      4      \        8  d   R\         R2# YP                  4       ^,           R P                  4       pT'       g   R# R#   \
        P                   d   pRT 2u Rp?# Rp?ii ; i)zu
Validate that SKILL.md content has proper frontmatter with required fields.
Returns error message or None if valid.
zContent cannot be empty.z---zPSKILL.md must start with YAML frontmatter (---). See existing skills for format.z
\n---\s*\n:   NNzISKILL.md frontmatter is not closed. Ensure you have a closing '---' line.zYAML frontmatter parse error: Nz6Frontmatter must be a YAML mapping (key: value pairs).r)   z&Frontmatter must include 'name' field.descriptionz-Frontmatter must include 'description' field.zDescription exceeds r,   zRSKILL.md must have content after the frontmatter (instructions, procedures, etc.).)r8   
startswithresearchstartyaml	safe_load	YAMLErrorr7   dictr-   r   MAX_DESCRIPTION_LENGTHend)r;   	end_matchyaml_contentparsedr   bodys   &     r   _validate_frontmatterrM      s   
 ==??)e$$a		-5IZ1Y__.23L4- fd##GV7F">
3vm$%&)??%&<%=\JJ==?Q&'(..0Dc# >> 4/s334s   5D D:+D5/D:5D:c                R    V ^8  d   QhR\         R\         R\        \         ,          /# )r   r;   labelr   r*   )r   s   "r   r   r      s%      C  Xc] r   c                b    \        V 4      \        8  d   V R\        V 4      R R\        R R2# R# )z|Check that content doesn't exceed the character limit for agent writes.

Returns an error message or None if within bounds.
z content is ,z characters (limit: za). Consider splitting into a smaller SKILL.md with supporting files in references/ or templates/.N)r-   MAX_SKILL_CONTENT_CHARS)r;   rO   s   &&r   _validate_content_sizerS      sD    
 7|--g\#g,q!1 2.q1 2,-	
 r   c                <    V ^8  d   QhR\         R\         R\        /# )r   r)   r3   r   )r   r   )r   s   "r   r   r      s!      S C 4 r   c                T    V'       d   \         V,          V ,          # \         V ,          # )zFBuild the directory path for a new skill, optionally under a category.)
SKILLS_DIR)r)   r3   s   &&r   _resolve_skill_dirrW      s     H$t++r   c                h    V ^8  d   QhR\         R\        \        \         \        3,          ,          /# r(   )r   r   r   r   )r   s   "r   r   r      s'      c htCH~6 r   c                    ^ RI Hp V! 4        F`  pVP                  4       '       g   K  VP                  R4       F0  pVP                  P
                  V 8X  g   K   RVP                  /u u # 	  Kb  	  R# )z
Find a skill by name across all skill directories.

Searches the local skills dir (~/.hermes/skills/) first, then any
external dirs configured via skills.external_dirs.  Returns
{"path": Path} or None.
)get_all_skills_dirsSKILL.mdpathN)agent.skill_utilsrZ   existsrglobparentr)   )r)   rZ   
skills_dirskill_mds   &   r   _find_skillrc      sa     6)+
  """((4H##t+00 5 , r   c                F    V ^8  d   QhR\         R\        \         ,          /# )r   	file_pathr   r*   )r   s   "r   r   r      s      3 8C= r   c                b   V '       g   R# \        V 4      pRVP                  9   d   R# VP                  '       d   VP                  ^ ,          \        9  d(   RP                  \	        \        4      4      pRV RV  R2# \        VP                  4      ^8  d   RVP                  ^ ,           R	2# R
# )zv
Validate a file path for write_file/remove_file.
Must be under an allowed subdirectory and not escape the skill dir.
zfile_path is required.z..z%Path traversal ('..') is not allowed.z, zFile must be under one of: z. Got: ''z5Provide a file path, not just a directory. Example: 'z/myfile.md'N)r   partsALLOWED_SUBDIRSjoinsortedr-   )re   
normalizedr   s   &  r   _validate_file_pathrm      s    
 'iJ z6 z//2/I))F?34,WIXi[JJ :q FzGWGWXYGZF[[fggr   c                @    V ^8  d   QhR\         R\        R\        RR/# )r   re   r;   encodingr   N)r   r   )r   s   "r   r   r      s)      $   RV r   c                "   V P                   P                  RRR7       \        P                  ! \	        V P                   4      RV P
                   R2RR7      w  r4 \        P                  ! VRVR7      ;_uu_ 4       pVP                  V4       R	R	R	4       \        P                  ! W@4       R	#   + '       g   i     L(; i  \         dC     \        P                  ! T4       h   \         d    \        P                  R
TRR7        h i ; ii ; i)aI  
Atomically write text content to a file.

Uses a temporary file in the same directory and os.replace() to ensure
the target file is never left in a partially-written state if the process
crashes or is interrupted.

Args:
    file_path: Target file path
    content: Content to write
    encoding: Text encoding (default: utf-8)
Tparentsexist_ok.z.tmp. )dirprefixsuffixwro   Nz6Failed to remove temporary file %s during atomic writer   )r`   mkdirtempfilemkstempr   r)   osfdopenwritereplacer   unlinkOSErrorr   error)re   r;   ro   fd	temp_pathfs   &&&   r   _atomic_write_textr      s     4$7$$	  !9>>"%(MB

YYr322aGGG 3


9( 32  	mIIi  	  	mLLQS\gkLl	m	sH   !C <B.C .B>	9C DC$#D$#D
D	D

Dc          
      j    V ^8  d   QhR\         R\         R\         R\        \         \        3,          /# )r   r)   r;   r3   r   r   r   r   )r   s   "r   r   r     s0     6 6 6c 6S 6DcN 6r   c           
        \        V 4      pV'       d   RRRV/# \        V4      pV'       d   RRRV/# \        V4      pV'       d   RRRV/# \        V4      pV'       d   RRRV/# \	        V 4      pV'       d   RRRRV  RVR,           R2/# \        W4      pVP                  RRR	7       VR
,          p\        Wa4       \        V4      pV'       d   \        P                  ! VRR7       RRRV/# RRRRV  R2R\        VP                  \        4      4      R\        V4      /pV'       d   W(R&   RP                  V 4      VR&   V# )z.Create a new user skill with SKILL.md content.successFr   zA skill named 'z' already exists at r\   rt   Trq   r[   )ignore_errorsmessageSkill 'z
' created.rb   r3   zTo add reference files, templates, or scripts, use skill_manage(action='write_file', name='{}', file_path='references/example.md', file_content='...')hint)r1   r9   rM   rS   rc   rW   r{   r   r    shutilrmtreer   relative_torV   r   )	r)   r;   r3   errexistingr   rb   
scan_errorr   s	   &&&      r   _create_skillr     su    
C
5'3//
X
&C
5'3//  
(C
5'3//
 
)C
5'3// 4 Hutf,@&AQ@RRST
 	
 #42IOOD4O0 :%Hx) &i0Jit45':66 	4WTF*-I))*56CM	F %z	nntntuynz 6N Mr   c                ^    V ^8  d   QhR\         R\         R\        \         \        3,          /# )r   r)   r;   r   r   )r   s   "r   r   r   U  s)      c C DcN r   c           	        \        V4      pV'       d   RRRV/# \        V4      pV'       d   RRRV/# \        V 4      pV'       g   RRRRV  R2/# VR,          R,          pVP                  4       '       d   VP	                  RR	7      MR
p\        WA4       \        VR,          4      pV'       d   Ve   \        WE4       RRRV/# RRRRV  R2R\        VR,          4      /# )z:Replace the SKILL.md of any existing skill (full rewrite).r   Fr   r   z7' not found. Use skills_list() to see available skills.r\   r[   utf-8rz   NTr   z
' updated.)rM   rS   rc   r^   	read_textr   r    r   )r)   r;   r   r   rb   original_contentr   s   &&     r   _edit_skillr   U  s    

(C
5'3//
 
)C
5'3//4 H5'WTF:q+rss*,H?G?P?Px))7);VZx) &hv&67J'x:5':66 	4WTF*-HV$% r   c                    V ^8  d   QhR\         R\         R\         R\         R\        R\        \         \        3,          /# )r   r)   
old_string
new_stringre   replace_allr   )r   r#   r   r   )r   s   "r   r   r   v  sT     S S
SS S 	S
 S 
#s(^Sr   c                0   V'       g   RRRR/# Vf   RRRR/# \        V 4      pV'       g   RRRRV  R2/# VR,          pV'       d#   \        V4      pV'       d   RRRV/# Wc,          pM	VR	,          pVP                  4       '       g   RRRR
VP                  V4       2/# TP	                  RR7      p	^ RIHp
 V
! WW$4      w  rpV'       d+   V	R,          \        V	4      R8  d   RMR,           pRRRVRV/# V'       g   R	MTp\        WR7      pV'       d   RRRV/# V'       g   \        V4      pV'       d
   RRRRV 2/# T	p\        W4       \        V4      pV'       d   \        VV4       RRRV/# RRRRV'       g   R	MT RT  RT RV^8  d   RMR R2	/# )zTargeted find-and-replace within a skill file.

Defaults to SKILL.md. Use file_path to patch a supporting file instead.
Requires a unique match unless replace_all is True.
r   Fr   z#old_string is required for 'patch'.zOnew_string is required for 'patch'. Use an empty string to delete matched text.r   ' not found.r\   r[   zFile not found: r   rz   )fuzzy_find_and_replace:Ni  Ni  z...ru   file_previewrO   z&Patch would break SKILL.md structure: Tr   zPatched z in skill 'z' (z replacementsz).)rc   rm   r^   r   r   tools.fuzzy_matchr   r-   rS   rM   r   r    )r)   r   r   re   r   r   r   r   targetr;   r   new_contentmatch_countmatch_errorpreviewtarget_labelr   r   s   &&&&&             r   _patch_skillr   v  s    5'+PQQ5'+|}}4 H5'WTF,+GHH I!),ugs33& Z'==??5'-=f>P>PQZ>[=\+]^^0G 9,BZ-)Kk $-CL3,>5BGu[G
 	
 &/:IL
 
AC
5'3// #K05A#G 
 v+ &i0J6#345':66 	4X	jyIUYTZZ]^i]jjv  J  MN  Nwz  TV  wW  WY  Z r   c                R    V ^8  d   QhR\         R\        \         \        3,          /# r(   r   )r   s   "r   r   r     s"       S#X r   c                F   \        V 4      pV'       g   RRRRV  R2/# VR,          p\        P                  ! V4       VP                  pV\        8w  dF   VP                  4       '       d0   \        VP                  4       4      '       g   VP                  4        RRRRV  R	2/# )
zDelete a skill.r   Fr   r   r   r\   Tr   z
' deleted.)	rc   r   r   r`   rV   r^   anyiterdirrmdir)r)   r   r   r`   s   &   r   _delete_skillr     s    4 H5'WTF,+GHH I
MM) FFNN<L8M8M 	4WTF*- r   c          
      j    V ^8  d   QhR\         R\         R\         R\        \         \        3,          /# )r   r)   re   file_contentr   r   )r   s   "r   r   r     s0     / /c /c / /c3h /r   c                   \        V4      pV'       d   RRRV/# V'       g   VR8w  d   RRRR/# \        VP                  R4      4      pV\        8  d   RRRRVR R	\        R R
2/# \	        W!R7      pV'       d   RRRV/# \        V 4      pV'       g   RRRRV  R2/# VR,          V,          pVP                  P                  RRR7       VP                  4       '       d   VP                  RR7      MRp\        Wb4       \        VR,          4      pV'       d)   Ve   \        Wg4       MVP                  RR7       RRRV/# RRRRV RV  R2R\        V4      /# )z>Add or overwrite a supporting file within any skill directory.r   Fr   ru   zfile_content is required.r   zFile content is rQ   z bytes (limit: z7 bytes / 1 MiB). Consider splitting into smaller files.r   r   z2' not found. Create it first with action='create'.r\   Trq   rz   N)
missing_okr   File 'z' written to skill ''.)rm   r-   encodeMAX_SKILL_FILE_BYTESrS   rc   r`   r{   r^   r   r   r    r   r   )	r)   re   r   r   content_bytesr   r   r   r   s	   &&&      r   _write_filer     s   
i
(C
5'3//LB.5'+FGG ++G45M++u"="3 4/2 39:
 	
 !
?C
5'3//4 H5'WTF:l+mnnf	)F
MMt4=C]]__v'''9RVv, &hv&67J'v8MMTM*5':66 	4VI;&:4&CF r   c                ^    V ^8  d   QhR\         R\         R\        \         \        3,          /# )r   r)   re   r   r   )r   s   "r   r   r     s)     % %s %s %tCH~ %r   c           	        \        V4      pV'       d   RRRV/# \        V 4      pV'       g   RRRRV  R2/# VR,          pWA,          pVP                  4       '       g   . p\         F|  pWG,          pVP                  4       '       g   K#  VP	                  R4       FD  p	V	P                  4       '       g   K  VP                  \        V	P                  V4      4      4       KF  	  K~  	  RRRRV R	V  R
2RV'       d   V/# R/# VP                  4        VP                  p
W8w  dF   V
P                  4       '       d0   \        V
P                  4       4      '       g   V
P                  4        RRRRV RV  R
2/# )z2Remove a supporting file from any skill directory.r   Fr   r   r   r\   *r   z' not found in skill 'r   available_filesNTr   z' removed from skill ')rm   rc   r^   ri   r_   is_fileappendr   r   r   r`   r   r   r   )r)   re   r   r   r   r   	availablesubdirdr   r`   s   &&         r   _remove_filer     s^   
i
(C
5'3//4 H5'WTF,+GHH I"F==??	%F"AxxzzAyy{{!((Q]]9-E)FG & & uvi[(>tfBGIy
 	
 <@
 	
 MMO ]]Fv}}s6>>;K7L7L 	4VI;&<TF"E r   c                    V ^8  d   QhR\         R\         R\         R\         R\         R\         R\         R\         R	\        R
\         /
# )r   actionr)   r;   r3   re   r   r   r   r   r   )r   r#   )r   s   "r   r   r   >  sl     :2 :2:2
:2 :2 	:2
 :2 :2 :2 :2 :2 	:2r   c	                   V R8X  d3   V'       g   \         P                  ! RRRR/RR7      # \        WV4      p	EM=V R8X  d2   V'       g   \         P                  ! RRRR/RR7      # \        W4      p	EMV R	8X  dS   V'       g   \         P                  ! RRRR
/RR7      # Vf   \         P                  ! RRRR/RR7      # \	        WWtV4      p	MV R8X  d   \        V4      p	MV R8X  dR   V'       g   \         P                  ! RRRR/RR7      # Vf   \         P                  ! RRRR/RR7      # \        WV4      p	MAV R8X  d1   V'       g   \         P                  ! RRRR/RR7      # \        W4      p	M
RRRRV  R2/p	V	P                  R4      '       d    ^ RI	H
p
 V
! RR7       \         P                  ! V	RR7      #   \         d     L%i ; i)zn
Manage user-created skills. Dispatches to the appropriate action handler.

Returns JSON string with results.
creater   Fr   zVcontent is required for 'create'. Provide the full SKILL.md text (frontmatter + body).)ensure_asciieditzGcontent is required for 'edit'. Provide the full updated SKILL.md text.patchz=old_string is required for 'patch'. Provide the text to find.zLnew_string is required for 'patch'. Use empty string to delete matched text.delete
write_filezJfile_path is required for 'write_file'. Example: 'references/api-guide.md'z*file_content is required for 'write_file'.remove_filez(file_path is required for 'remove_file'.zUnknown action 'z<'. Use: create, edit, patch, delete, write_file, remove_file) clear_skills_system_prompt_cacheT)clear_snapshot)jsondumpsr   r   r   r   r   r   getagent.prompt_builderr   r   )r   r)   r;   r3   re   r   r   r   r   r   r   s   &&&&&&&&&  r   skill_manager   >  s     ::y%  ;S  T  ch  i  ith7	6	::y%  ;D  E  TY  Z  ZT+	7	::y%:yz  JO  P  P::y%  ;I  J  Y^  _  _d
{S	8	t$	<	::y%  ;G  H  W\  ]  ]::y%:fgv{||Tl;	=	 ::y%:detyzzd. UG/?x  HD  .E  Fzz)	M,DA ::f511  		s   F6 6GGr)   r   r>   u  Manage skills (create, update, delete). Skills are your procedural memory — reusable approaches for recurring task types. New skills go to ~/.hermes/skills/; existing skills can be modified wherever they live.

Actions: create (full SKILL.md + optional category), patch (old_string/new_string — preferred for fixes), edit (full SKILL.md rewrite — major overhauls only), delete, write_file, remove_file.

Create when: complex task succeeded (5+ calls), errors overcome, user-corrected approach worked, non-trivial workflow discovered, or user asks you to remember a procedure.
Update when: instructions stale/wrong, OS-specific failures, missing steps or pitfalls found during use. If you used a skill and hit issues not covered by it, patch it immediately.

After difficult/iterative tasks, offer to save as a skill. Skip for simple one-offs. Confirm with user before creating/deleting.

Good skills: trigger conditions, numbered steps with exact commands, pitfalls section, verification steps. Use skill_view() to see format examples.
parameterstypeobject
propertiesr   stringenumzThe action to perform.zSkill name (lowercase, hyphens/underscores, max 64 chars). Must match an existing skill for patch/edit/delete/write_file/remove_file.r;   zFull SKILL.md content (YAML frontmatter + markdown body). Required for 'create' and 'edit'. For 'edit', read the skill first with skill_view() and provide the complete updated text.r   zText to find in the file (required for 'patch'). Must be unique unless replace_all=true. Include enough surrounding context to ensure uniqueness.r   zXReplacement text (required for 'patch'). Can be empty string to delete the matched text.r   booleanzZFor 'patch': replace all occurrences instead of requiring a unique match (default: false).r3   zOptional category/domain for organizing the skill (e.g., 'devops', 'data-science', 'mlops'). Creates a subdirectory grouping. Only used with 'create'.re   zPath to a supporting file within the skill directory. For 'write_file'/'remove_file': required, must be under references/, templates/, scripts/, or assets/. For 'patch': optional, defaults to SKILL.md if omitted.r   z0Content for the file. Required for 'write_file'.required)registryc                 >   \        V P                  R R4      V P                  RR4      V P                  R4      V P                  R4      V P                  R4      V P                  R4      V P                  R4      V P                  R4      V P                  R	R
4      R7	      # )r   ru   r)   r;   r3   re   r   r   r   r   F)	r   r)   r;   r3   re   r   r   r   r   )r   r   )argskws   &,r   <lambda>r     s{    |xx"%XXfb!#*%((;'XXn-88L)88L)HH]E2	 4r   u   📝)r)   toolsetschemahandleremoji>   assetsscripts	templates
references)r[   )N)r   )NF)NNNNNNF)r   r   r   r   r   r   )7__doc__r   loggingr~   r@   r   r|   pathlibr   hermes_constantsr   typingr   r   r   	getLogger__name__r   tools.skills_guardr   r   r	   r   ImportErrorr    rC   HERMES_HOMErV   r.   rG   rR   r   compiler/   ri   r&   r1   r9   rM   rS   rW   rc   rm   r   r   r   r   r   r   r   r   SKILL_MANAGE_SCHEMAtools.registryr   registerr%   r   r   <module>r      sB  B   	 	    , & &			8	$WW
(  8#
 !    

45 C2$N$4H6rBSl(/d%X:2D N	Y$ Z7
 a U ) 2 	{ / N Qs=
| 	Xv&AA+W v $   		4 Q  s   E 	E+*E+