§
    ‰eîiyu  ã                   ó|  — d 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mZmZmZ  ej        e¦  «        Z	 ddlmZmZmZ dZn# e$ r dZY nw xY wd	efd
„Zded	ee         fd„ZddlZ e
¦   «         Zedz  Z dZ!dZ"ded	efd„Z#dZ$dZ% ej&        d¦  «        Z'h d£Z(ded	ee         fd„Z)dee         d	ee         fd„Z*ded	ee         fd„Z+dLdeded	ee         fd„Z,dMdeded	efd„Z-ded	eeeef                  fd „Z.d!ed	ee         fd"„Z/ded!ed	eee         ee         f         fd#„Z0dNd!eded%ed	dfd&„Z1dMdededed	eeef         fd'„Z2deded	eeef         fd(„Z3	 	 dOded)ed*ed!ed+ed	eeef         fd,„Z4ded	eeef         fd-„Z5ded!ed.ed	eeef         fd/„Z6ded!ed	eeef         fd0„Z7	 	 	 	 	 	 	 dPd1edededed!ed.ed)ed*ed+ed	efd2„Z8d3d4 e¦   «         › d5�d6d7g d8¢d9d:œd7d;d<œd7d=d<œd7d>d<œd7d?d<œd@dAd<œd7dBd<œd7dCd<œd7dDd<œdEœ	d1dgdFœdGœZ9ddHl:m;Z;m<Z<  e;j=        d3de9dI„ dJ¬K¦  «         dS )Qu  
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Údisplay_hermes_home)ÚDictÚAnyÚOptionalÚTuple)Ú
scan_skillÚshould_allow_installÚformat_scan_reportTFÚreturnc                  ó´   — 	 ddl m}   | ¦   «         }t          |                     di ¦  «                             dd¦  «        ¦  «        S # t          $ r Y dS w xY w)a[  Read skills.guard_agent_created from config (default False).

    Off by default because the agent can already execute the same code
    paths via terminal() with no gate, so the scan adds friction without
    meaningful security.  Users who want belt-and-suspenders can turn it
    on via `hermes config set skills.guard_agent_created true`.
    r   )Úload_configÚskillsÚguard_agent_createdF)Úhermes_cli.configr   ÚboolÚgetÚ	Exception)r   Úcfgs     ú:/home/div/.hermes/hermes-agent/tools/skill_manager_tool.pyÚ_guard_agent_created_enabledr   8   ss   € ðØ1Ð1Ð1Ð1Ð1Ð1Øˆk‰mŒmˆÝ�C—G’G˜H bÑ)Ô)×-Ò-Ð.CÀUÑKÔKÑLÔLÐLøÝð ð ð Øˆuˆuðøøøs   ‚AA	 Á	
AÁAÚ	skill_dirc                 óŠ  — t           sdS t          ¦   «         sdS 	 t          | d¬¦  «        }t          |¦  «        \  }}|du rt	          |¦  «        }d|› d|› �S |€2t	          |¦  «        }t
                               d|¦  «         d|› d|› �S n5# t          $ r(}t
                               d| |d	¬
¦  «         Y d}~nd}~ww xY wdS )zšScan a skill directory after write. Returns error string if blocked, else None.

    No-op when skills.guard_agent_created is disabled (the default).
    Nzagent-created)ÚsourceFz"Security scan blocked this skill (z):
z4Agent-created skill blocked (dangerous findings): %szSecurity scan failed for %s: %sT©Úexc_info)Ú_GUARD_AVAILABLEr   r
   r   r   ÚloggerÚwarningr   )r   ÚresultÚallowedÚreasonÚreportÚes         r   Ú_security_scan_skillr&   H   s  € õ
 ð ØˆtÝ'Ñ)Ô)ð ØˆtðWÝ˜I¨oÐ>Ñ>Ô>ˆÝ.¨vÑ6Ô6‰ˆ�Ø�eÐÐÝ'¨Ñ/Ô/ˆFØL¸ÐLÐLÀFÐLÐLÐLØˆ?õ (¨Ñ/Ô/ˆFÝ�NŠNÐQÐSYÑZÔZÐZØL¸ÐLÐLÀFÐLÐLÐLð øõ ð Wð Wð WÝ�ŠÐ8¸)ÀQÐQUˆÑVÔVÐVÐVÐVÐVÐVÐVøøøøðWøøøàˆ4s   ›=B Á3B Â
C ÂB;Â;C r   é@   i   Ú
skill_pathc                 ó¦   — 	 |                       ¦   «                              t                                ¦   «         ¦  «         dS # t          $ r Y dS w xY w)z‰Check if a skill path is within the local SKILLS_DIR.

    Skills found in external_dirs are read-only from the agent's perspective.
    TF)ÚresolveÚrelative_toÚ
SKILLS_DIRÚ
ValueError)r(   s    r   Ú_is_local_skillr.   m   sZ   € ð
Ø×ÒÑÔ×(Ò(­×);Ò);Ñ)=Ô)=Ñ>Ô>Ð>ØˆtøÝð ð ð Øˆuˆuðøøøs   ‚>A Á
AÁAi † i   z^[a-z0-9][a-z0-9._-]*$>   ÚassetsÚscriptsÚ	templatesÚ
referencesÚnamec                 ó”   — | sdS t          | ¦  «        t          k    rdt          › d�S t                               | ¦  «        sd| › d�S dS )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)r3   s    r   Ú_validate_namer:   …   sn   € àð )Ø(Ð(Ý
ˆ4�y„y•?Ò"Ð"ØB¥_ÐBÐBÐBÐBÝ×Ò˜tÑ$Ô$ð 
ðR 4ð Rð Rð Rð	
ð ˆ4ó    Úcategoryc                 ó  — | €dS t          | t          ¦  «        sdS |                      ¦   «         } | sdS d| v sd| v rd| › d�S t          | ¦  «        t          k    rdt          › d�S t
                               | ¦  «        sd| › d�S dS )	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 r5   )Ú
isinstanceÚstrÚstripr6   r7   r8   r9   )r<   s    r   Ú_validate_categoryrC   “   sÓ   € àÐØˆtÝ�h¥Ñ$Ô$ð ,Ø+Ð+à�~Š~ÑÔ€HØð ØˆtØ
ˆh€€˜$ (Ð*Ð*ðZ ð Zð Zð Zð	
õ ˆ8�}„}•Ò&Ð&Ø@¥?Ð@Ð@Ð@Ð@Ý×Ò˜xÑ(Ô(ð 
ðZ ð Zð Zð Zð	
ð ˆ4r;   Úcontentc                 ój  — |                       ¦   «         sdS |                      d¦  «        sdS t          j        d| dd…         ¦  «        }|sdS | d|                     ¦   «         dz   …         }	 t          j        |¦  «        }n!# t
          j        $ r}d|› �cY d}~S d}~ww xY wt          |t          ¦  «        sd	S d
|vrdS d|vrdS t          t          |d         ¦  «        ¦  «        t          k    rdt          › d�S | |                     ¦   «         dz   d…                               ¦   «         }|sdS dS )z�
    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é   NzISKILL.md frontmatter is not closed. Ensure you have a closing '---' line.zYAML frontmatter parse error: z6Frontmatter must be a YAML mapping (key: value pairs).r3   z&Frontmatter must include 'name' field.Údescriptionz-Frontmatter must include 'description' field.zDescription exceeds r5   zRSKILL.md must have content after the frontmatter (instructions, procedures, etc.).)rB   Ú
startswithÚreÚsearchÚstartÚyamlÚ	safe_loadÚ	YAMLErrorr@   Údictr6   rA   ÚMAX_DESCRIPTION_LENGTHÚend)rD   Ú	end_matchÚyaml_contentÚparsedr%   Úbodys         r   Ú_validate_frontmatterrV   ¬   s~  € ð
 �=Š=‰?Œ?ð *Ø)Ð)à×Ò˜eÑ$Ô$ð bØaÐaå”	˜-¨°°°¬Ñ5Ô5€IØð [ØZÐZà˜1˜YŸ_š_Ñ.Ô.°Ñ2Ð2Ô3€Lð4Ý” Ñ-Ô-ˆˆøÝŒ>ð 4ð 4ð 4Ø3°Ð3Ð3Ð3Ð3Ð3Ð3Ð3Ð3øøøøð4øøøõ �f�dÑ#Ô#ð HØGÐGà�VÐÐØ7Ð7Ø˜FÐ"Ð"Ø>Ð>Ý
�3ˆv�mÔ$Ñ%Ô%Ñ&Ô&Õ)?Ò?Ð?ØJÕ&<ÐJÐJÐJÐJà�9—=’=‘?”? QÑ&Ð'Ð'Ô(×.Ò.Ñ0Ô0€DØð dØcÐcàˆ4s   Á/B ÂB"ÂBÂB"ÂB"úSKILL.mdÚlabelc                 ót   — t          | ¦  «        t          k    r|› dt          | ¦  «        d›dt          d›d�S dS )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)r6   ÚMAX_SKILL_CONTENT_CHARS)rD   rX   s     r   Ú_validate_content_sizer\   Ó   sY   € õ
 ˆ7�|„|Õ-Ò-Ð-àð -ð -¥# g¡,¤,Ð>ð -ð -Ý.Ð5ð-ð -ð -ð	
ð ˆ4r;   c                 ó4   — |rt           |z  | z  S t           | z  S )zFBuild the directory path for a new skill, optionally under a category.)r,   )r3   r<   s     r   Ú_resolve_skill_dirr^   â   s%   € àð ,Ý˜HÑ$ tÑ+Ð+Ý˜ÑÐr;   c                 óÀ   — ddl m}  |¦   «         D ]L}|                     ¦   «         sŒ|                     d¦  «        D ]}|j        j        | k    rd|j        ic c S Œ ŒMdS )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.
    r   )Úget_all_skills_dirsrW   ÚpathN)Úagent.skill_utilsr`   ÚexistsÚrglobÚparentr3   )r3   r`   Ú
skills_dirÚskill_mds       r   Ú_find_skillrh   é   sœ   € ð 6Ð5Ð5Ð5Ð5Ð5Ø)Ð)Ñ+Ô+ð 1ð 1ˆ
Ø× Ò Ñ"Ô"ð 	ØØ"×(Ò(¨Ñ4Ô4ð 	1ð 	1ˆHØŒÔ# tÒ+Ð+Ø ¤Ð0Ð0Ð0Ð0Ð0Ð0ð ,ð	1ð ˆ4r;   Ú	file_pathc                 ó:  — ddl m} | sdS t          | ¦  «        } || ¦  «        rdS |j        r|j        d         t          vr0d                     t          t          ¦  «        ¦  «        }d|› d| › d�S t          |j        ¦  «        d	k     rd
|j        d         › d�S dS )z‚
    Validate a file path for write_file/remove_file.
    Must be under an allowed subdirectory and not escape the skill dir.
    r   )Úhas_traversal_componentzfile_path is required.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)Útools.path_securityrk   r   ÚpartsÚALLOWED_SUBDIRSÚjoinÚsortedr6   )ri   rk   Ú
normalizedr"   s       r   Ú_validate_file_pathrt   û   sÓ   € ð
 <Ð;Ð;Ð;Ð;Ð;àð (Ø'Ð'å�i‘”€Jð Ð˜yÑ)Ô)ð 7Ø6Ð6ð Ôð K˜zÔ/°Ô2½/ÐIÐIØ—)’)�F¥?Ñ3Ô3Ñ4Ô4ˆØJ¨WÐJÐJ¸iÐJÐJÐJÐJõ ˆ:ÔÑÔ˜qÒ Ð ØgÀzÔGWÐXYÔGZÐgÐgÐgÐgàˆ4r;   c                 óD   — ddl m} | |z  } ||| ¦  «        }|rd|fS |dfS )zNResolve a supporting-file path and ensure it stays within the skill directory.r   )Úvalidate_within_dirN)rn   rv   )r   ri   rv   ÚtargetÚerrors        r   Ú_resolve_skill_targetry     sL   € à7Ð7Ð7Ð7Ð7Ð7à˜Ñ"€FØÐ ¨	Ñ2Ô2€EØð Ø�Uˆ{ÐØ�4ˆ<Ðr;   úutf-8Úencodingc                 ó   — | j                              dd¬¦  «         t          j        t	          | j         ¦  «        d| j        › d�d¬¦  «        \  }}	 t          j        |d|¬¦  «        5 }|                     |¦  «         d	d	d	¦  «         n# 1 swxY w Y   t          j	        || ¦  «         d	S # t          $ rE 	 t          j        |¦  «         n-# t          $ r  t                               d
|d¬¦  «         Y nw xY w‚ w xY w)au  
    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©r{   Nz6Failed to remove temporary file %s during atomic writer   )re   ÚmkdirÚtempfileÚmkstemprA   r3   ÚosÚfdopenÚwriteÚreplacer   ÚunlinkÚOSErrorr   rx   )ri   rD   r{   ÚfdÚ	temp_pathÚfs         r   Ú_atomic_write_textr“   "  sk  € ð Ô×Ò 4°$ÐÑ7Ô7Ð7ÝÔ$Ý�	Ô Ñ!Ô!Ø(�9”>Ð(Ð(Ð(Øðñ ô �M€Bˆ	ð

ÝŒY�r˜3¨Ð2Ñ2Ô2ð 	°aØ�GŠG�GÑÔÐð	ð 	ð 	ñ 	ô 	ð 	ð 	ð 	ð 	ð 	ð 	øøøð 	ð 	ð 	ð 	å
Œ
�9˜iÑ(Ô(Ð(Ð(Ð(øÝð ð ð ð	mÝŒI�iÑ Ô Ð Ð øÝð 	mð 	mð 	mÝ�LŠLÐQÐS\ÐgkˆLÑlÔlÐlÐlÐlð	møøøàðøøøsT   ÁB. Á*BÂ B. ÂBÂB. ÂBÂB. Â.
C=Â9CÃC=Ã'C8Ã5C=Ã7C8Ã8C=c                 ó„  — t          | ¦  «        }|rd|dœS t          |¦  «        }|rd|dœS t          |¦  «        }|rd|dœS t          |¦  «        }|rd|dœS t	          | ¦  «        }|rdd| › d|d         › d�dœS t          | |¦  «        }|                     dd¬¦  «         |d	z  }t          ||¦  «         t          |¦  «        }|rt          j
        |d¬
¦  «         d|dœS dd| › d�t          |                     t          ¦  «        ¦  «        t          |¦  «        dœ}|r||d<   d                     | ¦  «        |d<   |S )z.Create a new user skill with SKILL.md content.F©Úsuccessrx   zA skill named 'z' already exists at ra   r€   Tr}   rW   )Úignore_errorsúSkill 'z
' created.)r–   Úmessagera   rg   r<   z–To add reference files, templates, or scripts, use skill_manage(action='write_file', name='{}', file_path='references/example.md', file_content='...')Úhint)r:   rC   rV   r\   rh   r^   r‡   r“   r&   ÚshutilÚrmtreerA   r+   r,   Úformat)	r3   rD   r<   ÚerrÚexistingr   rg   Ú
scan_errorr!   s	            r   Ú_create_skillr¡   F  sÍ  € õ ˜Ñ
Ô
€CØ
ð 0Ø ¨3Ð/Ð/Ð/å
˜XÑ
&Ô
&€CØ
ð 0Ø ¨3Ð/Ð/Ð/õ   Ñ
(Ô
(€CØ
ð 0Ø ¨3Ð/Ð/Ð/å
  Ñ
)Ô
)€CØ
ð 0Ø ¨3Ð/Ð/Ð/õ ˜4Ñ Ô €HØð 
àØT tÐTÐTÀÈ&ÔAQÐTÐTÐTð
ð 
ð 	
õ # 4¨Ñ2Ô2€IØ‡O‚O˜D¨4€OÑ0Ô0Ð0ð ˜:Ñ%€HÝ�x Ñ)Ô)Ð)õ & iÑ0Ô0€JØð 7ÝŒ�i¨tÐ4Ñ4Ô4Ð4Ø ¨:Ð6Ð6Ð6ð Ø-˜TÐ-Ð-Ð-Ý�I×)Ò)­*Ñ5Ô5Ñ6Ô6Ý˜‘M”Mð	ð €Fð ð &Ø%ˆˆzÑð	nßntÒntÐuyÑnzÔnzð ˆ6�Nð €Mr;   c                 óî  — t          |¦  «        }|rd|dœS t          |¦  «        }|rd|dœS t          | ¦  «        }|s	dd| › d�dœS t          |d         ¦  «        s	dd| › d�dœS |d         dz  }|                     ¦   «         r|                     d¬	¦  «        nd
}t          ||¦  «         t          |d         ¦  «        }|r|�t          ||¦  «         d|dœS dd| › d�t          |d         ¦  «        dœS )z:Replace the SKILL.md of any existing skill (full rewrite).Fr•   r˜   z7' not found. Use skills_list() to see available skills.ra   úc' is in an external directory and cannot be modified. Copy it to your local skills directory first.rW   rz   r†   NTz
' updated.©r–   r™   ra   )	rV   r\   rh   r.   rc   Ú	read_textr“   r&   rA   )r3   rD   rž   rŸ   rg   Úoriginal_contentr    s          r   Ú_edit_skillr§     s{  € å
 Ñ
(Ô
(€CØ
ð 0Ø ¨3Ð/Ð/Ð/å
  Ñ
)Ô
)€CØ
ð 0Ø ¨3Ð/Ð/Ð/å˜4Ñ Ô €HØð tØ Ð+r°TÐ+rÐ+rÐ+rÐsÐsÐså˜8 FÔ+Ñ,Ô,ð `Ø ð  ,_°Tð  ,_ð  ,_ð  ,_ð  `ð  `ð  	`à˜Ô *Ñ,€Hà?G¿ºÑ?PÔ?PÐZ�x×)Ò)°7Ð)Ñ;Ô;Ð;ÐVZÐÝ�x Ñ)Ô)Ð)õ & h¨vÔ&6Ñ7Ô7€JØð 7ØÐ'Ý˜xÐ)9Ñ:Ô:Ð:Ø ¨:Ð6Ð6Ð6ð Ø-˜TÐ-Ð-Ð-Ý�H˜VÔ$Ñ%Ô%ðð ð r;   Ú
old_stringÚ
new_stringÚreplace_allc           
      ó’  — |sdddœS |€dddœS t          | ¦  «        }|s	dd| › d�dœS t          |d         ¦  «        s	dd| › d	�dœS |d         }|r1t          |¦  «        }|rd|dœS t          ||¦  «        \  }}|rd|dœS n|d
z  }|                     ¦   «         sdd|                     |¦  «        › �dœS |                     d¬¦  «        }	ddlm}
  |
|	|||¦  «        \  }}}}|rS|	dd…         t          |	¦  «        dk    rdndz   }|}	 ddlm
} | |||||	¦  «        z  }n# t          $ r Y nw xY wd||dœS |sd
n|}t          ||¬¦  «        }|rd|dœS |st          |¦  «        }|rdd|› �dœS |	}t          ||¦  «         t          |¦  «        }|rt          ||¦  «         d|dœS dd|sd
n|› d| › d|› d|dk    rdnd› d�	dœS ) z¸Targeted 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.
    Fz#old_string is required for 'patch'.r•   NzOnew_string is required for 'patch'. Use an empty string to delete matched text.r˜   ú' not found.ra   r£   rW   zFile not found: rz   r†   r   )Úfuzzy_find_and_replaceiô  z...r�   )Úformat_no_match_hint)r–   rx   Úfile_preview©rX   z&Patch would break SKILL.md structure: TzPatched z in skill 'z' (z replacementé   Úsz).©r–   r™   )rh   r.   rt   ry   rc   r+   r¥   Útools.fuzzy_matchr­   r6   r®   r   r\   rV   r“   r&   )r3   r¨   r©   ri   rª   rŸ   r   rž   rw   rD   r­   Únew_contentÚmatch_countÚ	_strategyÚmatch_errorÚpreviewÚerr_msgr®   Útarget_labelr¦   r    s                        r   Ú_patch_skillr¼   £  s‹  € ð ð RØ Ð+PÐQÐQÐQØÐØ Ð+|Ð}Ð}Ð}å˜4Ñ Ô €HØð IØ Ð+G°TÐ+GÐ+GÐ+GÐHÐHÐHå˜8 FÔ+Ñ,Ô,ð `Ø ð  ,_°Tð  ,_ð  ,_ð  ,_ð  `ð  `ð  	`à˜Ô €Iàð 
(å! )Ñ,Ô,ˆØð 	4Ø$¨sÐ3Ð3Ð3Ý+¨I°yÑAÔA‰ˆ�Øð 	4Ø$¨sÐ3Ð3Ð3ð	4ð ˜ZÑ'ˆà�=Š=‰?Œ?ð _Ø Ð+]¸f×>PÒ>PÐQZÑ>[Ô>[Ð+]Ð+]Ð^Ð^Ð^à×Ò¨ÐÑ0Ô0€Gð 9Ð8Ð8Ð8Ð8Ð8à7MÐ7MØ�˜Z¨ñ8ô 8Ñ4€K�˜i¨ð ð 
à˜$˜3˜$”-­C°©L¬L¸3Ò,>Ð,> 5 5ÀBÑGˆØˆð	Ø>Ð>Ð>Ð>Ð>Ð>ØÐ+Ð+¨K¸ÀjÐRYÑZÔZÑZˆGˆGøÝð 	ð 	ð 	ØˆDð	øøøð ØØ#ð
ð 
ð 	
ð &/Ð=�:�:°I€LÝ
  °LÐ
AÑ
AÔ
A€CØ
ð 0Ø ¨3Ð/Ð/Ð/ð ð Ý# KÑ0Ô0ˆØð 	à ØGÀ#ÐGÐGðð ð ð
 ÐÝ�v˜{Ñ+Ô+Ð+õ & iÑ0Ô0€JØð 7Ý˜6Ð#3Ñ4Ô4Ð4Ø ¨:Ð6Ð6Ð6ð ð Z°	ÐH˜j˜j¸yð  Zð  ZÐUYð  Zð  ZÐ^ið  Zð  Zð  Jð  MNò  Nð  NÐwzÐwzð  TVð  Zð  Zð  Zðð ð s   ÄD$ Ä$
D1Ä0D1c                 ór  — t          | ¦  «        }|s	dd| › d�dœS t          |d         ¦  «        s	dd| › d�dœS |d         }t          j        |¦  «         |j        }|t
          k    rI|                     ¦   «         r5t          |                     ¦   «         ¦  «        s| 	                    ¦   «          dd| › d�d	œS )
zDelete a skill.Fr˜   r¬   r•   ra   z4' is in an external directory and cannot be deleted.Tz
' deleted.r³   )
rh   r.   r›   rœ   re   r,   rc   ÚanyÚiterdirÚrmdir)r3   rŸ   r   re   s       r   Ú_delete_skillrÁ     sä   € å˜4Ñ Ô €HØð IØ Ð+G°TÐ+GÐ+GÐ+GÐHÐHÐHå˜8 FÔ+Ñ,Ô,ð qØ Ð+o°TÐ+oÐ+oÐ+oÐpÐpÐpà˜Ô €IÝ
„M�)ÑÔÐð Ô€FØ•ÒÐ §¢¡¤Ð½¸F¿NºNÑ<LÔ<LÑ8MÔ8MÐØ�Š‰Œˆð Ø-˜TÐ-Ð-Ð-ðð ð r;   Úfile_contentc                 ó  — t          |¦  «        }|rd|dœS |s|dk    rdddœS t          |                     d¦  «        ¦  «        }|t          k    rdd|d›dt          d›d	�dœS t	          ||¬
¦  «        }|rd|dœS t          | ¦  «        }|s	dd| › d�dœS t          |d         ¦  «        s	dd| › d�dœS t          |d         |¦  «        \  }}|rd|dœS |j         	                    dd¬¦  «         | 
                    ¦   «         r|                     d¬¦  «        nd}t          ||¦  «         t          |d         ¦  «        }|r.|�t          ||¦  «         n|                     d¬¦  «         d|dœS dd|› d| › d�t          |¦  «        dœS )z>Add or overwrite a supporting file within any skill directory.Fr•   r�   zfile_content is required.rz   zFile content is rZ   z bytes (limit: z7 bytes / 1 MiB). Consider splitting into smaller files.r°   r˜   z2' not found. Create it first with action='create'.ra   r£   Tr}   r†   N)Ú
missing_okúFile 'z' written to skill 'ú'.r¤   )rt   r6   ÚencodeÚMAX_SKILL_FILE_BYTESr\   rh   r.   ry   re   r‡   rc   r¥   r“   r&   rŽ   rA   )	r3   ri   rÂ   rž   Úcontent_bytesrŸ   rw   r¦   r    s	            r   Ú_write_filerÊ     sX  € å
˜iÑ
(Ô
(€CØ
ð 0Ø ¨3Ð/Ð/Ð/àð H˜L¨BÒ.Ð.Ø Ð+FÐGÐGÐGõ ˜×+Ò+¨GÑ4Ô4Ñ5Ô5€MØÕ+Ò+Ð+àð: =Ð;ð :ð :Ý/ÐDð:ð :ð :ð
ð 
ð 	
õ ! °YÐ
?Ñ
?Ô
?€CØ
ð 0Ø ¨3Ð/Ð/Ð/å˜4Ñ Ô €HØð oØ Ð+m°TÐ+mÐ+mÐ+mÐnÐnÐnå˜8 FÔ+Ñ,Ô,ð `Ø ð  ,_°Tð  ,_ð  ,_ð  ,_ð  `ð  `ð  	`å'¨°Ô(8¸)ÑDÔD�K€FˆCØ
ð 0Ø ¨3Ð/Ð/Ð/Ø
„M×Ò ¨tÐÑ4Ô4Ð4à=C¿]º]¹_¼_ÐV�v×'Ò'°Ð'Ñ9Ô9Ð9ÐRVÐÝ�v˜|Ñ,Ô,Ð,õ & h¨vÔ&6Ñ7Ô7€JØð 7ØÐ'Ý˜vÐ'7Ñ8Ô8Ð8Ð8à�MŠM TˆMÑ*Ô*Ð*Ø ¨:Ð6Ð6Ð6ð ØC˜IÐCÐC¸4ÐCÐCÐCÝ�F‘”ðð ð r;   c           	      ó$  — t          |¦  «        }|rd|dœS t          | ¦  «        }|s	dd| › d�dœS t          |d         ¦  «        s	dd| › d�dœS |d         }t          ||¦  «        \  }}|rd|dœS |                     ¦   «         s—g }t
          D ]|}||z  }|                     ¦   «         ra|                     d¦  «        D ]K}	|	                     ¦   «         r5|                     t          |	 
                    |¦  «        ¦  «        ¦  «         ŒLŒ}dd|› d	| › d
�|r|nddœS |                     ¦   «          |j        }
|
|k    rI|
                     ¦   «         r5t          |
                     ¦   «         ¦  «        s|
                     ¦   «          dd|› d| › d
�dœS )z2Remove a supporting file from any skill directory.Fr•   r˜   r¬   ra   z5' is in an external directory and cannot be modified.Ú*rÅ   z' not found in skill 'rÆ   N)r–   rx   Úavailable_filesTz' removed from skill 'r³   )rt   rh   r.   ry   rc   rp   rd   Úis_fileÚappendrA   r+   rŽ   re   r¾   r¿   rÀ   )r3   ri   rž   rŸ   r   rw   Ú	availableÚsubdirÚdr’   re   s              r   Ú_remove_filerÓ   R  s  € å
˜iÑ
(Ô
(€CØ
ð 0Ø ¨3Ð/Ð/Ð/å˜4Ñ Ô €HØð IØ Ð+G°TÐ+GÐ+GÐ+GÐHÐHÐHå˜8 FÔ+Ñ,Ô,ð rØ Ð+p°TÐ+pÐ+pÐ+pÐqÐqÐqà˜Ô €Iå'¨	°9Ñ=Ô=�K€FˆCØ
ð 0Ø ¨3Ð/Ð/Ð/Ø�=Š=‰?Œ?ð 
àˆ	Ý%ð 	Hð 	HˆFØ˜FÑ"ˆAØ�xŠx‰zŒzð HØŸš ™œð Hð H�AØ—y’y‘{”{ð HØ!×(Ò(­¨Q¯]ª]¸9Ñ-EÔ-EÑ)FÔ)FÑGÔGÐGøøàØG˜iÐGÐG¸tÐGÐGÐGØ,5Ð?˜y˜y¸4ð
ð 
ð 	
ð ‡M‚M�O„O€Oð Œ]€FØ�ÒÐ˜vŸ}š}™œÐµs¸6¿>º>Ñ;KÔ;KÑ7LÔ7LÐØ�Š‰Œˆð ØE˜IÐEÐE¸TÐEÐEÐEðð ð r;   Úactionc	                 óØ  — | dk    r%|st          dd¬¦  «        S t          |||¦  «        }	nñ| dk    r$|st          dd¬¦  «        S t          ||¦  «        }	nÇ| dk    r:|st          dd¬¦  «        S |€t          d
d¬¦  «        S t          |||||¦  «        }	n‡| dk    rt	          |¦  «        }	nq| dk    r8|st          dd¬¦  «        S |€t          dd¬¦  «        S t          |||¦  «        }	n3| dk    r$|st          dd¬¦  «        S t          ||¦  «        }	n	dd| › d�dœ}	|	                     d¦  «        r$	 ddlm	}
  |
d¬¦  «         n# t          $ r Y nw xY wt          j        |	d¬¦  «        S )zz
    Manage user-created skills. Dispatches to the appropriate action handler.

    Returns JSON string with results.
    ÚcreatezVcontent is required for 'create'. Provide the full SKILL.md text (frontmatter + body).F)r–   ÚeditzGcontent is required for 'edit'. Provide the full updated SKILL.md text.Úpatchz=old_string is required for 'patch'. Provide the text to find.NzLnew_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_filer•   r–   r   )Ú clear_skills_system_prompt_cacheT)Úclear_snapshot)Úensure_ascii)Ú
tool_errorr¡   r§   r¼   rÁ   rÊ   rÓ   r   Úagent.prompt_builderrÜ   r   ÚjsonÚdumps)rÔ   r3   rD   r<   ri   rÂ   r¨   r©   rª   r!   rÜ   s              r   Úskill_managerã   „  s6  € ð  �ÒÐØð 	GÝÐvð  AFð  Gñ  Gô  Gð  GÝ˜t W¨hÑ7Ô7ˆˆà	�6Ò	Ð	Øð 	xÝÐgÐqvÐwÑwÔwÐwÝ˜T 7Ñ+Ô+ˆˆà	�7Ò	Ð	Øð 	nÝÐ]ÐglÐmÑmÔmÐmØÐÝÐlÐv{Ð|Ñ|Ô|Ð|Ý˜d J°
¸IÀ{ÑSÔSˆˆà	�8Ò	Ð	Ý˜tÑ$Ô$ˆˆà	�<Ò	Ð	Øð 	{ÝÐjÐtyÐzÑzÔzÐzØÐÝÐJÐTYÐZÑZÔZÐZÝ˜T 9¨lÑ;Ô;ˆˆà	�=Ò	 Ð	 Øð 	YÝÐHÐRWÐXÑXÔXÐXÝ˜d IÑ.Ô.ˆˆð #ð  .EÀð  .Eð  .Eð  .Eð  Fð  Fˆà‡z‚z�)ÑÔð ð	ØMÐMÐMÐMÐMÐMØ,Ð,¸DÐAÑAÔAÐAÐAøÝð 	ð 	ð 	ØˆDð	øøøõ Œ:�f¨5Ð1Ñ1Ô1Ð1s   Ä3E Å
EÅErã   u�   Manage skills (create, update, delete). Skills are your procedural memory â€” reusable approaches for recurring task types. New skills go to u{  /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.ÚobjectÚstring)rÖ   rØ   r×   rÙ   rÚ   rÛ   zThe action to perform.)ÚtypeÚenumrG   z…Skill name (lowercase, hyphens/underscores, max 64 chars). Must match an existing skill for patch/edit/delete/write_file/remove_file.)ræ   rG   zµFull 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.z‘Text to find in the file (required for 'patch'). Must be unique unless replace_all=true. Include enough surrounding context to ensure uniqueness.zXReplacement text (required for 'patch'). Can be empty string to delete the matched text.ÚbooleanzZFor 'patch': replace all occurrences instead of requiring a unique match (default: false).z–Optional category/domain for organizing the skill (e.g., 'devops', 'data-science', 'mlops'). Creates a subdirectory grouping. Only used with 'create'.zÔPath 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.z0Content for the file. Required for 'write_file'.)	rÔ   r3   rD   r¨   r©   rª   r<   ri   rÂ   )ræ   Ú
propertiesÚrequired)r3   rG   Ú
parameters)Úregistryrß   c                 óŽ  — t          |                      dd¦  «        |                      dd¦  «        |                      d¦  «        |                      d¦  «        |                      d¦  «        |                      d¦  «        |                      d¦  «        |                      d	¦  «        |                      d
d¦  «        ¬¦	  «	        S )NrÔ   r�   r3   rD   r<   ri   rÂ   r¨   r©   rª   F)	rÔ   r3   rD   r<   ri   rÂ   r¨   r©   rª   )rã   r   )ÚargsÚkws     r   ú<lambda>rð   &  s¢   € �|Ø�xŠx˜ "Ñ%Ô%Ø�XŠX�f˜bÑ!Ô!Ø—’˜Ñ#Ô#Ø—’˜*Ñ%Ô%Ø—(’(˜;Ñ'Ô'Ø—X’X˜nÑ-Ô-Ø—8’8˜LÑ)Ô)Ø—8’8˜LÑ)Ô)Ø—H’H˜]¨EÑ2Ô2ð	 4ñ 	 4ô 	 4€ r;   u   ðŸ“�)r3   ÚtoolsetÚschemaÚhandlerÚemoji)rW   )N)rz   )NF)NNNNNNF)>Ú__doc__rá   ÚloggingrŠ   rI   r›   rˆ   Úpathlibr   Úhermes_constantsr   r   Útypingr   r   r   r	   Ú	getLoggerÚ__name__r   Útools.skills_guardr
   r   r   r   ÚImportErrorr   r   rA   r&   rL   ÚHERMES_HOMEr,   r7   rP   r.   r[   rÈ   Úcompiler8   rp   r:   rC   rV   r\   r^   rh   rt   ry   r“   r¡   r§   r¼   rÁ   rÊ   rÓ   rã   ÚSKILL_MANAGE_SCHEMAÚtools.registryrì   rß   Úregister© r;   r   ú<module>r     sÔ  ððð ðB €€€Ø €€€Ø 	€	€	€	Ø 	€	€	€	Ø €€€Ø €€€Ø Ð Ð Ð Ð Ð Ø AÐ AÐ AÐ AÐ AÐ AÐ AÐ AØ -Ð -Ð -Ð -Ð -Ð -Ð -Ð -Ð -Ð -Ð -Ð -à	ˆÔ	˜8Ñ	$Ô	$€ðØWÐWÐWÐWÐWÐWÐWÐWÐWÐWØÐÐøØð ð ð ØÐÐÐðøøøð dð ð ð ð ð  Dð ¨X°c¬]ð ð ð ð ð4 €€€ð ˆoÑÔ€Ø˜8Ñ#€
à€ØÐ ð	 ð 	¨ð 	ð 	ð 	ð 	ð "Ð Ø Ð ð �”
Ð4Ñ5Ô5€ð CÐBÐB€ð˜ð  ¨#¤ð ð ð ð ð ¨#¤ð °8¸C´=ð ð ð ð ð2$ 3ð $¨8°C¬=ð $ð $ð $ð $ðNð  Cð °ð ÀXÈcÄ]ð ð ð ð ðð ˜Sð ¨Cð ¸4ð ð ð ð ð�cð ˜h t¨C°¨H¤~Ô6ð ð ð ð ð$ 3ð ¨8°C¬=ð ð ð ð ð8 Tð °cð ¸eÀHÈTÄNÐT\Ð]`ÔTaÐDaÔ>bð ð ð ð ðð  $ð °ð Àð ÐRVð ð ð ð ðH6ð 6˜ð 6 cð 6°Sð 6ÀDÈÈcÈÄNð 6ð 6ð 6ð 6ðr!�cð ! Cð !¨D°°c°¬Nð !ð !ð !ð !ðP Øð^ð ^Ø
ð^àð^ð ð^ð ð	^ð
 ð^ð 
ˆ#ˆsˆ(„^ð^ð ^ð ^ð ^ðB˜ð   S¨# X¤ð ð ð ð ð.4�cð 4 cð 4¸ð 4ÀÀcÈ3ÀhÄð 4ð 4ð 4ð 4ðn+�sð + sð +¨t°C¸°H¬~ð +ð +ð +ð +ðj ØØØØØØð:2ð :2Øð:2à
ð:2ð ð:2ð ð	:2ð
 ð:2ð ð:2ð ð:2ð ð:2ð ð:2ð 	ð:2ð :2ð :2ð :2ðD ð	Yà/Ð/Ñ1Ô1ð	Yð 	Yð 	Yð& ð !ØZÐZÐZØ7ðð ð !ðaðð ð !ðUðð ð !ð)ðð ð !ð2ðð ð "Ø{ðð ð
 !ð/ðð ð !ðNðð ð !ØQðð ðs=
ð =
ð| ˜vÐ&ðAAð Að+Wð WÐ ðv 0Ð /Ð /Ð /Ð /Ð /Ð /Ð /à €Ô Ø	ØØð	4ð 	4ð ðñ ô ð ð ð s   ÁA ÁAÁA