+
    iZ                        R t ^ RIt^ RIt^ RIH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HtHtHt ^ RIt^ RIHt ]P,                  ! ]4      t]! 4       t]R,          t^@tRtR	R
RRRR/t]P<                  ! R4      t] ! R4      t!] ! 0 Rm4      t"Rs#R R lt$ ! R R]%]	4      t&R R lt'R R lt(R R lt)R R lt*R R lt+RR R llt,R R  lt-R! R" lt.R# R$ lt/RR% R& llt0R'R/R( R) llt1R* R+ lt2RR, R- llt3R. R/ lt4R0 R1 lt5R2 R3 lt6R4 R5 lt7R6 R7 lt8R8 R9 lt9RR: R; llt:R<R=/R> R? llt;R@ RA lt<RRB RC llt=RRD RE llt>RRF RG llt?RHt@]RI8X  EdF    ]A! RJ4       ]A! R4       ]A! RK4       ]P                  ! ]>! 4       4      tC]CRL,          '       d   ]A! RM]CRN,           RO]D! ]CP                  RP. 4      4       RQ24       ]A! RR]CP                  RP. 4       24       ]A! RS4       ]CR,          RT,           FO  tF]FP                  RU4      '       d   RV]FRU,           RW2MRXtG]A! RY]G ]FRZ,           R[]FR\,          R],           R^24       KQ  	  M]A! R_]CR`,           24       ]A! Ra4       ]P                  ! ]?! Rb4      4      tC]CRL,          '       dy   ]A! Rc]CRZ,           24       ]A! Rd]CP                  R\Re4      Rf,           R^24       ]A! Rg]D! ]CRh,          4       Ri24       ]CP                  Rj4      '       d   ]A! Rk]CRj,           24       M]A! R_]CR`,           24       ]A! Rl4       ]P                  ! ]?! RbRm4      4      tC]CRL,          '       dG   ]A! Rn]CRo,           24       ]A! Rg]D! ]CRh,          4       Ri24       ]A! Rp]CRh,          Rq,           R^24       M]A! R_]CR`,           24       RZRrR\RsRtRuRvRwRURuRxR\Ry//Rz. //tHRZR{R\R|RtRuRvRwRZRuRxR\R}/R~RuRxR\R//RzRZ.//tI]P                  ! RrR]HR ]4RR7       ]P                  ! R{R]IR ]4RR7       R# )u  
Skills Tool Module

This module provides tools for listing and viewing skill documents.
Skills are organized as directories containing a SKILL.md file (the main instructions)
and optional supporting files like references, templates, and examples.

Inspired by Anthropic's Claude Skills system with progressive disclosure architecture:
- Metadata (name ≤64 chars, description ≤1024 chars) - shown in skills_list
- Full Instructions - loaded via skill_view when needed
- Linked Files (references, templates) - loaded on demand

Directory Structure:
    skills/
    ├── my-skill/
    │   ├── SKILL.md           # Main instructions (required)
    │   ├── references/        # Supporting documentation
    │   │   ├── api.md
    │   │   └── examples.md
    │   ├── templates/         # Templates for output
    │   │   └── template.md
    │   └── assets/            # Supplementary files (agentskills.io standard)
    └── category/              # Category folder for organization
        └── another-skill/
            └── SKILL.md

SKILL.md Format (YAML Frontmatter, agentskills.io compatible):
    ---
    name: skill-name              # Required, max 64 chars
    description: Brief description # Required, max 1024 chars
    version: 1.0.0                # Optional
    license: MIT                  # Optional (agentskills.io)
    platforms: [macos]            # Optional — restrict to specific OS platforms
                                  #   Valid: macos, linux, windows
                                  #   Omit to load on all platforms (default)
    prerequisites:                # Optional — legacy runtime requirements
      env_vars: [API_KEY]         #   Legacy env var names are normalized into
                                  #   required_environment_variables on load.
      commands: [curl, jq]        #   Command checks remain advisory only.
    compatibility: Requires X     # Optional (agentskills.io)
    metadata:                     # Optional, arbitrary key-value (agentskills.io)
      hermes:
        tags: [fine-tuning, llm]
        related_skills: [peft, lora]
    ---

    # Skill Title

    Full instructions and content here...

Available tools:
- skills_list: List skills with metadata (progressive disclosure tier 1)
- skill_view: Load full skill content (progressive disclosure tier 2-3)

Usage:
    from tools.skills_tool import skills_list, skill_view, check_skills_requirements

    # List all skills (returns metadata only - token efficient)
    result = skills_list()

    # View a skill's main content (loads full instructions)
    content = skill_view("axolotl")

    # View a reference file within a skill (loads linked file)
    content = skill_view("axolotl", "references/dataset-formats.md")
N)get_hermes_home)Enum)Path)DictAnyListOptionalSetTuple)registryskillsi   macosdarwinlinuxwindowswin32z^[A-Za-z_][A-Za-z0-9_]*$c                F    V ^8  d   QhR\         \        \        3,          /#    return)r   str)formats   "./home/ubuntu/hermes-agent/tools/skills_tool.py__annotate__r   m   s      $sCx.     c                    \        4       R,          p / pV P                  4       '       g   V# V P                  4       ;_uu_ 4       pV F  pVP                  4       pV'       g   K  VP	                  R4      '       d   K6  RV9   g   K?  VP                  R4      w  rEpVP                  4       P                  R4      WP                  4       &   K  	  RRR4       V#   + '       g   i     T# ; i)z@Load profile-scoped environment variables from HERMES_HOME/.env.z.env#="'N)r   existsopenstrip
startswith	partition)env_pathenv_varsflinekey_values          r   load_envr+   m   s     6)H!H??	AD::<DtDOOC00SD[ $s 3(-(;(;E(B%	  
 O 
 Os   C$C=CACC(	c                   "    ] tR t^}tRtRtRtRtR# )SkillReadinessStatus	availablesetup_neededunsupported N)__name__
__module____qualname____firstlineno__	AVAILABLESETUP_NEEDEDUNSUPPORTED__static_attributes__r1   r   r   r-   r-   }   s    I!LKr   r-   c                    V ^8  d   QhRR/# )r   r   Nr1   )r   s   "r   r   r      s     ( (T (r   c                 
    V s R # N)_secret_capture_callback)callbacks   &r   set_secret_capture_callbackr?      s    'r   c                R    V ^8  d   QhR\         \        \        3,          R\        /# r   frontmatterr   )r   r   r   bool)r   s   "r   r   r      s"      S#X 4 r   c                    ^ RI Hp V! V 4      # )u   Check if a skill is compatible with the current OS platform.

Delegates to ``agent.skill_utils.skill_matches_platform`` — kept here
as a public re-export so existing callers don't need updating.
)skill_matches_platform)agent.skill_utilsrE   )rB   _impls   & r   rE   rE      s     Br   c                F    V ^8  d   QhR\         R\        \        ,          /# )r   r*   r   )r   r   r   )r   s   "r   r   r      s     > ># >$s) >r   c                     V '       g   . # \        V \        4      '       d   V .p V  Uu. uF/  p\        V4      P                  4       '       g   K$  \        V4      NK1  	  up# u upi r<   )
isinstancer   r!   )r*   items   & r   _normalize_prerequisite_valuesrL      sI    	%"'=%$3t9??+<ICI%===s   !A A c                    V ^8  d   QhR\         \        \        3,          R\        \        \        ,          \        \        ,          3,          /# rA   )r   r   r   r
   r   )r   s   "r   r   r      s6     	 	c3h	
49d3i 	r   c                     V P                  R 4      pV'       d   \        V\        4      '       g   . . 3# \        VP                  R4      4      \        VP                  R4      4      3# )prerequisitesr%   commands)getrJ   dictrL   )rB   prereqss   & r   _collect_prerequisite_valuesrT      sV     ooo.G*Wd332v&w{{:'>?&w{{:'>? r   c                t    V ^8  d   QhR\         \        \        3,          R\         \        \        3,          /# rA   r   r   r   )r   s   "r   r   r      s*     * *4S> *d38n *r   c                    V P                  R 4      p\        V\        4      '       g   RRR. /# VP                  R4      p\        V\        4      '       d0   VP	                  4       '       d   \        V4      P	                  4       MRpVP                  R4      p\        V\        4      '       d   V.p\        V\
        4      '       g   . p. pV EF  p\        V\        4      '       g   K  \        VP                  R4      ;'       g    R4      P	                  4       pV'       g   KX  \        VP                  R4      ;'       g    RV 24      P	                  4       p\        VP                  R4      ;'       g    VP                  R	4      ;'       g    R4      P	                  4       p	RVRVR
\        VP                  R
R4      4      /p
V	'       d   WR&   VP                  V
4       EK  	  RVRV/# )setuphelpNcollect_secretsenv_var promptEnter value for provider_urlurlsecretT)rQ   rJ   rR   r   r!   listrC   append)rB   rX   	help_textnormalized_helpcollect_secrets_rawrZ   rK   r[   r]   r_   entrys   &          r   _normalize_setup_metadatarh      s   OOG$EeT""/44		&!I i%%)//*;*; 	I   ))$56%t,,23)400 ,.O#$%%dhhy)//R0668TXXh'GG-=gY+GHNNP488N3LLtxxLL"MSSU wfd488Hd34!

 $0.!u%% $* 	? r   c          	          V ^8  d   QhR\         \        \        3,          R\        \        ,          R,          R\        \         \        \        3,          ,          /# )r   rB   legacy_env_varsNr   )r   r   r   r   )r   s   "r   r   r      sD     ? ?c3h?#Y%? 
$sCx.?r   c                 z  aaa	 \        V 4      o	V P                  R 4      p\        V\        4      '       d   V.p\        V\        4      '       g   . p. o\        4       oR VVV	3R llpV FE  p\        V\        4      '       d   V! RV/4       K%  \        V\        4      '       g   K=  V! V4       KG  	  S	R,           FW  pT! RVP                  R4      RVP                  R4      RVP                  R4      ;'       g    S	P                  R4      /4       KY  	  Vf   \        V 4      w  rV F  pV! RV/4       K  	  S# )	required_environment_variablesc                J    V ^8  d   QhR\         \        \        3,          RR/# )r   rg   r   NrV   )r   s   "r   r   9_get_required_environment_variables.<locals>.__annotate__   s"     $ $S#X $4 $r   c                   < \        V P                  R 4      ;'       g    V P                  R4      ;'       g    R4      P                  4       pV'       d   VS9   d   R# \        P	                  V4      '       g   R# R TR\        V P                  R4      ;'       g    RV 24      P                  4       /pV P                  R4      ;'       gD    V P                  R4      ;'       g+    V P                  R4      ;'       g    SP                  R4      p\        V\         4      '       d*   VP                  4       '       d   VP                  4       VR&   V P                  R	4      p\        V\         4      '       d*   VP                  4       '       d   VP                  4       VR	&   SP                  V4       SP                  V4       R# )
namer[   r\   Nr]   r^   rY   r_   r`   required_for)r   rQ   r!   _ENV_VAR_NAME_REmatchrJ   addrc   )rg   env_name
normalizedrd   rq   requiredseenrX   s   &    r   _append_required=_get_required_environment_variables.<locals>._append_required   sj   uyy(FFEIIi,@FFBGMMO8t+%%h// Hc%))H-NN3CH:1NOUUW&

 IIf ! !yy(! !yy! ! yy 	 	 i%%)//*;*;!*!2Jvyy0lC((\-?-?-A-A)5););)=J~&
#r   rp   rZ   r[   r]   rY   r_   )rh   rQ   rJ   rR   rb   setr   rT   )
rB   rj   required_rawry   rK   r)   r[   rw   rx   rX   s
   &&     @@@r   #_get_required_environment_variablesr}      s'    &k2E??#CDL,%%$~lD))%'HUD$ $8 dC  fd^,dD!!T"  '((+$((8,0EEEIIf4E	
 ) 9+F"&'*+ # Or   c                    V ^8  d   QhR\         R\        \        \         \        3,          ,          R\        \         \        3,          /# )r   
skill_namemissing_entriesr   )r   r   r   r   )r   s   "r   r   r     s@     E EE$sCx.)E 
#s(^Er   c           
      V   V'       g	   R . RRRR/# V Uu. uF  q"R,          NK  	  pp\        4       '       d   R VRRR\        4       /# \        f	   R VRRRR/# Rp. pV F  pRV /pVP                  R4      '       d   VR,          VR&   VP                  R4      '       d   VR,          VR&    \        VR,          VR	,          V4      p\        V\        4      ;'       d    \        VP                  R4      4      p\        V\        4      ;'       d    \        VP                  R4      4      p	V'       d   V	'       g   K  RpVP                  VR,          4       K  	  R VRVRR/# u upi   \         d6    \
        P                  R
TR,           2RR7       RRRTR,          RRRR/p Li ; i)missing_namessetup_skippedFgateway_setup_hintNrp   r   rY   rq   r]   z#Secret capture callback failed for Texc_infosuccess	stored_as	validatedskipped)_is_gateway_surface_gateway_setup_hintr=   rQ   	ExceptionloggerwarningrJ   rR   rC   rc   )
r   r   rg   r   r   remaining_namesmetadatacallback_resultr   r   s
   &&        r   '_capture_required_environment_variablesr     s    RU $
 	
 1@@u6]]M@]U "5"7
 	
  ']U $
 	
 M!#O  *-99V$V}HV99^$$',^'<H^$	6fhO  _d3 
 
	*9
 _d3 
 
	*9
 7uV}-E !J 	d m A>  		NN5eFm_EPT   5U6]U4	O			s   E#,E((=F('F(c                $    V ^8  d   QhR\         /# r   rC   )r   s   "r   r   r   ]  s     6 6T 6r   c                  |    \         P                  ! R 4      '       d   R# \        \         P                  ! R4      4      # )HERMES_GATEWAY_SESSIONTHERMES_SESSION_PLATFORM)osgetenvrC   r1   r   r   r   r   ]  s*    	yy)**		3455r   c                $    V ^8  d   QhR\         /# r   r   )r   s   "r   r   r   c  s     N NC Nr   c                      \        \        P                  ! R R4      4      P                  4       P	                  4       ;'       g    R# )TERMINAL_ENVlocal)r   r   r   r!   lowerr1   r   r   _get_terminal_backend_namer   c  s2    ryy1288:@@BMMgMr   c                l    V ^8  d   QhR\         R\        \         \         3,          R,          R\        /# )r   var_nameenv_snapshotNr   )r   r   rC   )r   s   "r   r   r   g  s1     % %%!%c3h$!6%	%r   c                     Vf   \        4       pW9   d   \        VP                  V 4      4      # \        \        P                  ! V 4      4      # r<   )r+   rC   rQ   r   r   )r   r   s   &&r   _is_env_var_persistedr   g  sA     zL$$X.//		(#$$r   r   c          	          V ^8  d   QhR\         \        \        \        3,          ,          R\        \        \        3,          R\        \        \        3,          R,          R\         \        ,          /# )r   required_env_varscapture_resultr   Nr   )r   r   r   r   )r   s   "r   r   r   q  sV      DcN+cN sCx.4'	
 
#Yr   c                    \        VR ,          4      pVf   \        4       p. pV  F6  pVR,          pWc9   g   \        Wb4      '       d   K%  VP                  V4       K8  	  V# )r   rp   )r{   r+   r   rc   )r   r   r   r   	remainingrg   rp   s   &&$    r   %_remaining_required_environment_namesr   q  s_     78MzI"V} (=d(Q(QT" # r   c                $    V ^8  d   QhR\         /# r   r   )r   s   "r   r   r     s     S SS Sr   c                  8     ^ RI Hp  V #   \         d     R# i ; i)    *GATEWAY_SECRET_CAPTURE_UNSUPPORTED_MESSAGEzSecure secret entry is not available. Load this skill in the local CLI to be prompted, or add the key to ~/.hermes/.env manually.)gateway.platforms.baser   r   r   s    r   r   r     s(    SU99 S SSs   
 c          	      z    V ^8  d   QhR\         R\        \        ,          R\        R,          R\        R,          /# )r   readiness_statusmissing
setup_helpNr   )r-   r   r   )r   s   "r   r   r     s<      *#Y d
 	4Z	r   c                     V \         P                  8X  d3   V'       d   R P                  V4      MRpRV R2pV'       d   V RV 2# V# R# )z, zrequired prerequisitesz.Setup needed before using this skill: missing . N)r-   r7   join)r   r   r   missing_strnotes   &&&  r   _build_setup_noter     sP    
 /<<<,3dii(9Q?}ANV1ZL))r   c                $    V ^8  d   QhR\         /# r   r   )r   s   "r   r   r     s      4 r   c                     R# )zOSkills are always available -- the directory is created on first use if needed.Tr1   r1   r   r   check_skills_requirementsr     s    r   c                t    V ^8  d   QhR\         R\        \        \         \        3,          \         3,          /# r   contentr   )r   r
   r   r   )r   s   "r   r   r     s,     & & &d38nc.A(B &r   c                    ^ RI Hp V! V 4      # )u   Parse YAML frontmatter from markdown content.

Delegates to ``agent.skill_utils.parse_frontmatter`` — kept here
as a public re-export so existing callers don't need updating.
)parse_frontmatter)rF   r   )r   r   s   & r   _parse_frontmatterr     s     4W%%r   c                F    V ^8  d   QhR\         R\        \        ,          /# )r   
skill_pathr   r   r   r   )r   s   "r   r   r     s       # r   c                   \         .p ^ RIHp VP                  V! 4       4       V F<  p V P                  V4      pVP                  p\        V4      ^8  d   V^ ,          u # K>  	  R#   \         d     LQi ; i  \         d     Ka  i ; i)z
Extract category from skill path based on directory structure.

For paths like: ~/.hermes/skills/mlops/axolotl/SKILL.md -> "mlops"
Also works for external skill dirs configured via skills.external_dirs.
get_external_skills_dirsN)	
SKILLS_DIRrF   r   extendr   relative_topartslen
ValueError)r   dirs_to_checkr   
skills_dirrel_pathr   s   &     r   _get_category_from_pathr     s      LM>578 $
	!--j9HNNE5zQQx 	 $     		s"   A) 5A:)A76A7:B	B	c                0    V ^8  d   QhR\         R\        /# r   )r   int)r   s   "r   r   r     s     
 
c 
c 
r   c                &    \        V 4      ^,          # )zx
Rough token estimate (4 chars per token average).

Args:
    content: Text content

Returns:
    Estimated token count
)r   )r   s   &r   _estimate_tokensr     s     w<1r   c                :    V ^8  d   QhR\         \        ,          /# r   )r   r   )r   s   "r   r   r     s     P PtCy Pr   c                   V '       g   . # \        V \        4      '       d3   V  Uu. uF%  q'       g   K  \        V4      P                  4       NK'  	  up# \        V 4      P                  4       p V P	                  R4      '       d   V P                  R4      '       d   V ^R p V P                  R4       Uu. uF9  qP                  4       '       g   K  VP                  4       P                  R4      NK;  	  up# u upi u upi )u  
Parse tags from frontmatter value.

Handles:
- Already-parsed list (from yaml.safe_load): [tag1, tag2]
- String with brackets: "[tag1, tag2]"
- Comma-separated string: "tag1, tag2"

Args:
    tags_value: Raw tags value — may be a list or string

Returns:
    List of tag strings
[],r   )rJ   rb   r   r!   r"   endswithsplit)
tags_valuets   & r   _parse_tagsr     s     	 *d##(28
1aA
88 Z&&(JS!!j&9&9#&>&>"%
,6,<,<S,AO,AqWWY"AGGIOOE",AOO 9 Ps   	C4C42C9#C9c                :    V ^8  d   QhR\         \        ,          /# r   )r	   r   )r   s   "r   r   r     s     & &3s8 &r   c                     ^ RI Hp  V ! 4       # )u   Load disabled skill names from config.

Delegates to ``agent.skill_utils.get_disabled_skill_names`` — kept here
as a public re-export so existing callers don't need updating.
get_disabled_skill_names)rF   r   r   s    r   _get_disabled_skill_namesr     s     ;#%%r   c                <    V ^8  d   QhR\         R\         R\        /# )r   rp   platformr   )r   rC   )r   s   "r   r   r     s!      S C 4 r   c                0   ^ RI p ^ RIHp V! 4       pVP                  R/ 4      pT;'       g    VP                  ! R4      pV'       d*   VP                  R/ 4      P                  V4      pVe   W9   # WP                  R. 4      9   #   \
         d     R# i ; i)z'Check if a skill is disabled in config.N)load_configr   HERMES_PLATFORMplatform_disableddisabledF)r   hermes_cli.configr   rQ   r   r   )rp   r   r   r   config
skills_cfgresolved_platformr   s   &&      r   _is_skill_disabledr     s    1ZZ"-
$DD		2C(D */BB G K KL] ^ ,00~~j"555 s"   'B B 	(B 2B BBskip_disabledFc                h    V ^8  d   QhR\         R\        \        \        \        3,          ,          /# )r   r   r   )rC   r   r   r   r   )r   s   "r   r   r   
  s+     J Jt JT#s(^8L Jr   c           
     <   ^ RI Hp . p\        4       pV '       d   \        4       M	\        4       p. p\        P                  4       '       d   VP                  \        4       VP                  V! 4       4       V EF  pVP                  R4       EF  p\        ;QJ d&    R VP                   4       F  '       g   K   RM	  RM! R VP                   4       4      '       d   KT  VP                  p VP                  RR7      R,          p	\        V	4      w  r\        V
4      '       g   K  V
P                  R	VP                   4      R
\"         pW9   d   K  W9   d   K  V
P                  RR4      pV'       g\   VP%                  4       P'                  R4       F8  pVP%                  4       pV'       g   K  VP)                  R4      '       d   K6  Tp M	  \+        V4      \,        8  d   VR
\,        ^,
           R,           p\/        V4      pVP1                  V4       VP                  R	VRVRV/4       EK  	  EK  	  V#   \2        \4        3 d$   p\6        P9                  RTT4        R
p?EK  R
p?i\:         d&   p\6        P9                  RTTRR7        R
p?EK	  R
p?ii ; i)aB  Recursively find all skills in ~/.hermes/skills/ and external dirs.

Args:
    skip_disabled: If True, return ALL skills regardless of disabled
        state (used by ``hermes skills`` config UI). Default False
        filters out disabled skills.

Returns:
    List of skill metadata dicts (name, description, category).
r   SKILL.mdc              3   2   "   T F  q\         9   x  K  	  R # 5ir<   _EXCLUDED_SKILL_DIRS.0parts   & r   	<genexpr>#_find_all_skills.<locals>.<genexpr>%  s     KND//N   TFutf-8encodingNi  Nrp   Ndescriptionr\   
r   ...categoryz Failed to read skill file %s: %sz)Skipping skill at %s: failed to parse: %sr   )rF   r   r{   r   r   r   rc   r   rglobanyr   parent	read_textr   rE   rQ   rp   MAX_NAME_LENGTHr!   r   r"   r   MAX_DESCRIPTION_LENGTHr   rt   UnicodeDecodeErrorPermissionErrorr   debugr   )r   r   r   
seen_namesr   dirs_to_scanscan_dirskill_md	skill_dirr   rB   bodyrp   r  r'   r  es   $                r   _find_all_skillsr  
  s!    ;FeJ &su+D+FH LJ'023  z2HsKHNNKsssKHNNKKK I(",,g,>uE$6w$?!-k::"vy~~>?OP%#)oomR@" $

 2 24 8#zz|4(<(<*.K!	 !9 {#&<<"-.I/E/I"JU"RK28<t$D!; C 3 !b M '8 ?1M ?1W[   	sO   .7H9')H9H9H947H90H9	A$H99J
I((J5J6JJc                F    V ^8  d   QhR\         R\        \        ,          /# )r   category_dirr   r   )r   s   "r   r   r   W  s     ( (T (hsm (r   c                   V R,          pVP                  4       '       g   R#  VP                  RR7      p\        V4      w  r4VP                  RR4      pV'       g\   VP	                  4       P                  R4       F8  pVP	                  4       pV'       g   K  VP                  R4      '       d   K6  Tp M	  \        V4      \        8  d   VR\        ^,
           R	,           pV'       d   V# R#   \        \        3 d"   p\        P                  R
Y4        Rp?R# Rp?i\         d$   p\        P                  RYRR7        Rp?R# Rp?ii ; i)z
Load category description from DESCRIPTION.md if it exists.

Args:
    category_dir: Path to the category directory

Returns:
    Description string or None if not found
zDESCRIPTION.mdNr  r  r  r\   r	  r   r
  z*Failed to read category description %s: %sz)Error parsing category description %s: %sTr   )r   r  r   rQ   r!   r   r"   r   r  r  r  r   r  r   r   )r  	desc_filer   rB   r  r  r'   r  s   &       r   _load_category_descriptionr!  W  s    //I%%w%7.w7 "oomR8

**40zz|4 4 4"&K	 1 {44%&B(>(BCeKK){3t30 A9P 7PT 	 	
 	sB   A0C. C. 18C. *C. ,C. .E?DE(E)EEc                <    V ^8  d   QhR\         R\        R\        /# )r   verbosetask_idr   )rC   r   )r   s   "r   r   r     s+     LS LSt LSc LSS LSr   c           	         \         P                  4       '       d   \         .M. p ^ RIHp VP	                  R V! 4        4       4       V'       g   \        P                  ! RRR. RR/RR	7      # / p/ pV F  pVP                  R
4       F  p\        ;QJ d&    R VP                   4       F  '       g   K   RM	  RM! R VP                   4       4      '       d   KS   \        VP                  RR7      R,          4      w  r\        V4      '       g   K  \        V4      p
V
'       g   K  VP                  V
^ 4      ^,           WZ&   W9  g   K  VP                   P                   WJ&   K  	  K  	  . p\#        VP%                  4       4       F?  pWL,          p\'        V4      pRVRW\,          /pV'       d   WR&   VP)                  V4       KA  	  \        P                  ! RRRVRR/RR	7      #   \
         d     ELi ; i  \
         d    / p EL	i ; i  \
         d0   p\        P                  ! RRR\+        T4      /RR	7      u Rp?# Rp?ii ; i)a9  
List available skill categories with descriptions (progressive disclosure tier 0).

Returns category names and descriptions for efficient discovery before drilling down.
Categories can have a DESCRIPTION.md file with a description frontmatter field
or first paragraph to explain what skills are in that category.

Args:
    verbose: If True, include skill counts per category (default: False, but currently always included)
    task_id: Optional task identifier used to probe the active backend

Returns:
    JSON string with list of categories and their descriptions
r   c              3   T   "   T F  qP                  4       '       g   K  Vx  K   	  R # 5ir<   )r   r   ds   & r   r  $skills_categories.<locals>.<genexpr>  s     P'A!XXZAA'As   (
(r   T
categoriesmessagezNo skills directory found.Fensure_asciir   c              3   2   "   T F  q\         9   x  K  	  R # 5ir<   r   r   s   & r   r  r)    s     O33r  r  r  r  rp   skill_countr  hintzbIf a category is relevant to your task, use skills_list with that category to see available skillserrorN)r   r   rF   r   r   r   jsondumpsr  r  r   r   r  rE   r   rQ   r  sortedkeysr!  rc   r   )r#  r$  all_dirsr   category_dirscategory_countsr  r  rB   r)   r  r*  rp   r  r  	cat_entryr  s   &&               r   skills_categoriesr:    s   =S#-#4#4#6#6J<B	BOOP'?'APP ::t ";
 #  *, H$NN:63OO333OOOO%%7 **G*<UC&NK .k::28<80?0C0CHa0PST0TO-42://2H2H/% 7 !* 
=--/0D(.L4\BK}o6KLI+6-(i( 1 zz4j|
 
 	
[  		. ! %"$K%>  Szz9eWc!f=ERRSs   H 	H #G( 	H H /AH 5$H H $G:#H )H BH (G73H 6G77H :HH 
HH I$I=IIc                <    V ^8  d   QhR\         R\         R\         /# )r   r  r$  r   r   )r   s   "r   r   r     s+     AS AS# ASs ASc ASr   c                    \         P                  4       '       g8   \         P                  RRR7       \        P                  ! RRR. R. RR/RR	7      # \        4       pV'       g!   \        P                  ! RRR. R. RR
/RR	7      # V '       d)   V Uu. uF  q3P                  R4      V 8X  g   K  VNK  	  ppVP                  R R7       \        \        R V 4       4      4      p\        P                  ! RRRVRVR\        V4      RR/RR	7      # u upi   \         d0   p\        P                  ! RRR\        T4      /RR	7      u Rp?# Rp?ii ; i)a  
List all available skills (progressive disclosure tier 1 - minimal metadata).

Returns only name + description to minimize token usage. Use skill_view() to
load full content, tags, related files, etc.

Args:
    category: Optional category filter (e.g., "mlops")
    task_id: Optional task identifier used to probe the active backend

Returns:
    JSON string with minimal skill info: name, description, category
T)parentsexist_okr   r   r*  r+  z>No skills found. Skills directory created at ~/.hermes/skills/Fr,  z%No skills found in skills/ directory.r  c                 J    V P                  R 4      ;'       g    RV R,          3# )r  r\   rp   rQ   )ss   &r   <lambda>skills_list.<locals>.<lambda>  s    quuZ'8'>'>B&	&Jr   )r(   c              3   t   "   T F.  qP                  R 4      '       g   K  VP                  R 4      x  K0  	  R# 5i)r  Nr@  )r   rA  s   & r   r  skills_list.<locals>.<genexpr>  s(     K:az9J!j!!:s   88countr0  z@Use skill_view(name) to see full content, tags, and linked filesr1  N)r   r   mkdirr2  r3  r  rQ   sortr4  r{   r   r   r   )r  r$  
all_skillsrA  r*  r  s   &&    r   skills_listrJ    s^   3S  ""TD9::tb "_	 #  &'
::tb "F	 #  %/QZ553D3P!!ZJQ 	JK K:KK

 zz4*jZZ 	
 		
 R*  Szz9eWc!f=ERRSsM   D 6D 1D D D D-D3AD D E$EEEc                H    V ^8  d   QhR\         R\         R\         R\         /# )r   rp   	file_pathr$  r   r   )r   s   "r   r   r     s4     WS WSS WSS WS# WS WSr   c                \  aF  ^ RI Hp . p\        P                  4       '       d   VP	                  \        4       VP                  V! 4       4       V'       g   \        P                  ! RRRR/RR7      # RpRpV F  pWp,          pVP                  4       '       d+   VR,          P                  4       '       d   TpVR,          p M<VP                  R	4      P                  4       '       g   Kr  VP                  R	4      p M	  V'       gW   V FP  pVP                  R4       F.  p	V	P                  P                  V 8X  g   K   V	P                  pT	p M	  V'       g   KP   M	  V'       gD   V F=  pVP                  V  R	24       F  p
V
P                  R8w  g   K  T
p M	  V'       g   K=   M	  V'       d   VP                  4       '       gK   \        4       R
,           Uu. uF  qR,          NK  	  pp\        P                  ! RRRRV  R2RVRR/RR7      #  VP                  RR7      pRp\        P!                  4       .p TP                  R TR,           4       4       T F%  p TP!                  4       P#                  T4       Rp M	  . R_OpTP'                  4       oF\(        ;QJ d    TF3R lT 4       F  '       g   K   RM	  RM! TF3R lT 4       4      pT'       g	   T'       dq   . pT'       d   TP	                  RT 24       T'       d   TP	                  R4       ^ RIpTP-                  \.        4      P1                  RT RP3                  T4      4       / p \5        T4      w  pp\7        T4      '       g;   \        P                  ! RRRRT  R2R\8        P:                  P<                  /RR7      # TP?                  RTP                  P                  4      p\A        T4      '       d!   \        P                  ! RRRRT R2/RR7      # T'       Ed   T'       Ed   \C        T4      pR TPD                  9   d   \        P                  ! RRRR!RR"/RR7      # YQ,          p TP!                  4       pTP!                  4       pTPG                  T4      '       g   \        P                  ! RRRR#RR"/RR7      #  TP                  4       '       Eg   R'. R(. R). R*. R+. /pTP                  R,4       EF:  pTPK                  4       '       g   K  TP                  R8w  g   K/  \M        TP#                  T4      4      pTPO                  R-4      '       d   TR',          P	                  T4       Kz  TPO                  R.4      '       d   TR(,          P	                  T4       K  TPO                  R/4      '       d   TR),          P	                  T4       K  TPO                  R04      '       d   TR*,          P	                  T4       EK  TPP                  R`9   g   EK"  TR+,          P	                  T4       EK=  	  TPS                  4        U U!u/ uF  w  p p!T!'       g   K  T T!bK  	  pp p!\        P                  ! RRRR1T R2T  R32R4TRR5/RR7      #  TP                  RR7      p\        P                  ! RRRT R6TR7TR<TPP                  /RR7      # Tp". p#. p$. p%. p&T'       Ed   TR',          p'T'P                  4       '       d9   T'P[                  R=4       Uu. uF  p\M        TP#                  T4      4      NK  	  p#pTR(,          p(T(P                  4       '       dR   Ra FK  p)T$P                  T(P                  T)4       Uu. uF  p\M        TP#                  T4      4      NK  	  up4       KM  	  TR),          p*T*P                  4       '       dZ   T*P                  R,4       FD  pTPK                  4       '       g   K  T%P	                  \M        TP#                  T4      4      4       KF  	  TR*,          p+T+P                  4       '       dR   Rb FK  p)T&P                  T+P[                  T)4       Uu. uF  p\M        TP#                  T4      4      NK  	  up4       KM  	  / p,T"P?                  R>4      p-\]        T-\^        4      '       d   T-P?                  R?/ 4      ;'       g    / p,\a        T,P?                  R@4      ;'       g    T"P?                  R@RA4      4      p.\a        T,P?                  RB4      ;'       g    T"P?                  RBRA4      4      p// p0T#'       d   T#T0R'&   T$'       d   T$T0R(&   T%'       d   T%T0R)&   T&'       d   T&T0R*&    \M        TP#                  \        4      4      p1T"P?                  RT'       g   TPb                  MTP                  4      p2\e        T"4      w  p3p\g        T"T34      p4\i        4       p5\k        4       p6T4 Uu. uF   p\m        TR,          T64      '       d   K  TNK"  	  p7p\o        T2T74      p8T7'       d   \k        4       p6\q        T4T8T6RC7      p9\s        T94      p:T4 Uu. uF  pTR,          T99  g   K  TR,          NK  	  p;pT;'       d    ^ RDI:H;p< T<! T;4       T"P?                  RG. 4      p=\]        T=\|        4      '       g   . p=. p>T='       d    ^ RHI?H@p? T?! T=4      p>T>'       d   Rp:/ RRbRT2bRJT"P?                  RJRA4      bR@T.bRBT/bR7TbRKT1bRLT0'       d   T0MRbRMT0'       d   RNMRbROT4bRP. bRQT9bRRT>bRS. bRTT:bRUT8RU,          bRT:'       d   \8        P                  P<                  M\8        P                  P<                  bp@\        RV T4 4       R4      pATA'       d   XAX@RW&   T8RX,          '       d   T8RX,          X@RX&   T:'       d   T9 UBu. uF  pBRYTB 2NK
  	  upBT> UCu. uF  pCRZTC 2NK
  	  upC,           pD\        \8        P                  TDXA4      pET5\        9   d   XE'       d   XE R[T5P                  4        R\2pEXE'       d   XEX@R]&   T"P?                  R^4      '       d   T"R^,          X@R^&   \]        T-\^        4      '       d   T-X@R>&   \        P                  ! X@RR7      # u upi   \         d-   p\        P                  ! RRRRT  RT 2/RR7      u Rp?# Rp?ii ; i  \         d     E
Lpi ; i  \$         d     E
K  i ; i  \         d    / p E	Li ; i  \H        \$        3 d&    \        P                  ! RRRR$T R%2RR&/RR7      u # i ; iu up!p i   \T         dO    \        P                  ! RRRT R6TR7R8TP                   R9TPW                  4       PX                   R:2R;R/RR7      u # i ; iu upi u upi u upi   \$         d[    TP                  P                  '       d/   \M        TP#                  TP                  P                  4      4      MTP                  p1 ELi ; iu upi u upi   \         d    \x        P{                  RET2RRF7        ELi ; i  \         d    \x        P{                  RIT2RRF7        ELi ; iu upBi u upCi   \         d0   p\        P                  ! RRR\M        T4      /RR7      u Rp?# Rp?ii ; i)ca  
View the content of a skill or a specific file within a skill directory.

Args:
    name: Name or path of the skill (e.g., "axolotl" or "03-fine-tuning/axolotl")
    file_path: Optional path to a specific file within the skill (e.g., "references/api.md")
    task_id: Optional task identifier used to probe the active backend

Returns:
    JSON string with skill content or error message
r   r   Fr1  zISkills directory does not exist yet. It will be created on first install.r,  Nr   .md:N   Nrp   zSkill 'z' not found.available_skillsr0  z+Use skills_list to see all available skillsr  r  zFailed to read skill 'z': Tc              3   @   "   T F  qP                  4       x  K  	  R # 5ir<   )resolver'  s   & r   r  skill_view.<locals>.<genexpr>t  s      Clls   :   NNc              3   ,   <"   T F	  qS9   x  K  	  R # 5ir<   r1   )r   p_content_lowers   & r   r  rS    s     !S?R!~"5?Rs   zHskill file is outside the trusted skills directory (~/.hermes/skills/): zBskill content contains patterns that may indicate prompt injectionz#Skill security warning for '%s': %sz; z$' is not supported on this platform.r   zT' is disabled. Enable it with `hermes skills` or inspect the files directly on disk.z..z%Path traversal ('..') is not allowed.z.Use a relative path within the skill directoryz&Path escapes skill directory boundary.zInvalid file path: ''z4Use a valid relative path within the skill directory
references	templatesassetsscriptsother*zreferences/z
templates/zassets/zscripts/zFile 'z' not found in skill 'z'.available_filesz0Use one of the available file paths listed abovefiler   z[Binary file: z, size: z bytes]	is_binary	file_type*.mdr   hermestagsr\   related_skills)r   )register_env_passthroughz/Could not register env passthrough for skill %sr   required_credential_files)register_credential_filesz0Could not register credential files for skill %sr  pathlinked_files
usage_hintzzTo view linked files, call skill_view(name, file_path) where file_path is e.g. 'references/api.md' or 'assets/config.yaml'rl   required_commands&missing_required_environment_variablesmissing_credential_filesmissing_required_commandsr/   r   c              3   d   "   T F&  qP                  R 4      '       g   K  VR ,          x  K(  	  R# 5i)rY   Nr@  )r   r  s   & r   r  rS    s"     Q.?55=91V99.?s   00r   r   zenv $zfile r   zW-backed skills need these requirements available inside the remote environment as well.
setup_notecompatibility)	zignore previous instructionszignore all previouszyou are nowzdisregard yourzforget your instructionsznew instructions:zsystem prompt:z<system>z]]>)rN  z.pyz.yamlz.ymlz.jsonz.texz.sh)rc  *.pyz*.yamlz*.ymlz*.jsonz*.tex*.sh)rt  ru  z*.bashz*.jsz*.tsz*.rb)GrF   r   r   r   rc   r   r2  r3  is_dirwith_suffixr  r  rp   r  r  r   rR  r   r   r   r  logging	getLoggerr2   r   r   r   rE   r-   r8   r*   rQ   r   r   r   is_relative_toOSErroris_filer   r"   suffixitemsr  statst_sizeglobrJ   rR   r   stemrT   r}   r   r+   r   r   r   rC   tools.env_passthroughrg  r   r  rb   tools.credential_filesri  r7   r6   nextr   _REMOTE_ENV_BACKENDSupper)Grp   rL  r$  r   r6  r  r  
search_dirdirect_pathfound_skill_mdfound_mdrA  r.   r   r  _outside_skills_dir_trusted_dirs_td_INJECTION_PATTERNS_injection_detected	_warnings_loggingparsed_frontmatterr)   resolved_namenormalized_pathtarget_fileresolvedskill_dir_resolvedr_  r&   relkvrB   reference_filestemplate_filesasset_filesscript_filesreferences_dirtemplates_dirext
assets_dirscripts_dirhermes_metar   re  rf  rk  r   r   rj   r   backendr   missing_required_env_varsr   remaining_missing_required_envsr/   available_env_namesrg  required_cred_files_rawmissing_cred_filesri  resultr   ru   rj  missing_itemsrr  rW  sG   &&&                                                                   @r   
skill_viewr    s   KS> OOJ'023::uh #  	 #J$+K!!##z)A(I(I(K(K'	&3((/6688&2259 # &
&0&6&6z&BN%,,11T9$2$9$9	#1	 'C
 8 ' &
 * 0 0D6 >H}}
2#+ !? 8 ' x00,<,>s,CD,Cq6,CID::uwtfL9&	I	 # 		(('(:G ##++-.	   Chrl CC !C  "..s3&+#	 !

 !!c!S?R!Sccc!S?R!SS"5I"  #kltku!vw"  !ef&x(001VX\^b^g^ghq^rs-/	$$6w$?! &&899::uwtf,PQ&(<(H(H(N(N
 #  +..vx7K7KLm,,::u!- 1` ` #	 	 9"9oO,,,zz!5!H P
 "'  $/K&..0%.%6%6%8"../ABB::%u#%M"$T
 &+  C$ %%'' !"brR# #-Ayy{{qvv';!!--	":;>>-88+L9@@E ^^L99+K8??D ^^I66+H5<<SA ^^J77+I6==cBXX *  ,G4;;C@) .. 5D4I4I4K"Q4KDAqq41a44K"Qzz!56)4J4&PR!S)? R	 "' %///A ::tDIw!3!3 #	 	 ) 9&5N$$&&;I;N;Nv;V#;VaCi01;V   # &3M##%%C #)) &3%8%8%=%=  i 89%=" #X-J  ""#))#.Ayy{{#**3q}}Y/G+HI / $i/K!!##MC ''@K@P@PQT@UV@U1Q]]956@UV N ??:.h%%",,x4::K;??62QQkoofb6QR$OO,-VVAQSU1V

 )8L&(6L%%0L"&2L#	v8//
;<H !__HMM	

 :+F?
 -.z '%
&(6LA A& 	" %

 A%
 %#:L*O%+
'
 ;< '
&y ?? AfII& 	 

 	J()<= #.//2Mr"R1488&(##%"L%>?V%W"%#'L
t
J
 ;??="=
 D	

 n
 w
 H
 LLd
  W
 -.?
  
 56U
 '(:
  (!
" L#
$ ^O<%
&  !5 A A G G%//55+
0 Q.?QSWX
#-F< .//+9:N+OF'(3R3Rx%z"3R ,>+=4%v+=M
 +$11J
 ..: *|1W]]_,=  >U  V
'1|$ ???++&1/&BF?#h%%!)F:zz&u55c E  	::u5dV3qcB # 	  		  <  	$!#	$p Z( zz!5#7	{!!D V
 "' V #R & zz!4	!^K4D4D3EXkN^N^N`NhNhMiip#q#T "'	 	H# " W8  	vLTOOLbLbLbs8//0F0FGHhphuhuH	v%
*
  E!  *  F!  N*  Szz9eWc!f=ERRSsE  !y1 2y1 y1 4Ay1 8/y1 ,y1 	1y1 ?y1 y1 '*y1 y1 &y1 2y1 y1 q?,%y1 r %y1 =r> y1 "!s7y1 =y1 y1 %	y1 /y1 Ay1 s# &A
y1 1Ay1 y1 y1 9y1 y1 As7 2y1 
4y1 y1 A!y1 80y1 )0y1 )y1 	0y1 9t0t0)y1 =t6 +y1 ;y1 y1 -y1  #v# y1 #y1 '#v

)y1 4'y1  Ay1 ,#y1 #v
2Ay1 ?y1 3y1  y1 4y1 y1 y1 y1 !v! ?y1 Ay1 !x	x	=y1 xx&
y1 1x ?3y1 4x= 
x= .y1 ;y1 (y1 1A#y1 y1 )y1 -y';y1 y,6y1 y1 $y1  >y1 ?y1 r;!r60r;1y1 6r;;y1 >s	y1 sy1 s y1 s  y1 #s40y1 3s44y1 73t-*y1 ,t--	y1 6Avy1 vy1 !&x:xy1 xy1 #x:6y1 9x::y1 =#y$ y1 #y$$y1 1z+<$z& z+&z+a  Access skill documents providing specialized instructions, guidelines, and executable knowledge.

Progressive disclosure workflow:
1. skills_list() - Returns metadata (name, description, tags, linked_file_count) for all skills
2. skill_view(name) - Loads full SKILL.md content + shows available linked_files
3. skill_view(name, file_path) - Loads specific linked file (e.g., 'references/api.md', 'scripts/train.py')

Skills may include:
- references/: Additional documentation, API specs, examples
- templates/: Output formats, config files, boilerplate code
- assets/: Supplementary files (agentskills.io standard)
- scripts/: Executable helpers (Python, shell scripts)__main__u   🎯 Skills Tool Testu   
📋 Listing all skills:r   zFound rF  z skills in r*  z categorieszCategories: z
First 10 skills::N
   Nr  r   z] r\   u     • rp   z: r  :N<   Nr
  zError: r1  u   
📖 Viewing skill 'axolotl':axolotlzName: zDescription: zN/A:Nd   NzContent length: r   z charsrk  zLinked files: uE   
📄 Viewing reference file 'axolotl/references/dataset-formats.md':zreferences/dataset-formats.mdzFile: r`  z	Preview: :N   NrJ  zVList available skills (name + description). Use skill_view(name) to load full content.
parameterstypeobject
propertiesstringz*Optional category filter to narrow resultsrw   r  ah  Skills allow for loading information about specific tasks and workflows, as well as scripts and templates. Load a skill's full content or access its linked files (references, templates, scripts). First call returns SKILL.md content plus a 'linked_files' dict showing available references/templates/scripts. To access those, call again with file_path parameter.z8The skill name (use skills_list to see available skills)rL  zOPTIONAL: Path to a linked file within the skill (e.g., 'references/api.md', 'templates/config.yaml', 'scripts/validate.py'). Omit to get the main SKILL.md content.c                 X    \        V P                  R 4      VP                  R4      R7      # )r  r$  )r  r$  )rJ  rQ   argskws   &,r   rB  rB  S  s     {*%rvvi/@ r   u   📚)rp   toolsetschemahandlercheck_fnemojic                 z    \        V P                  R R4      V P                  R4      VP                  R4      R7      # )rp   r\   rL  r$  )rL  r$  )r  rQ   r  s   &,r   rB  rB  ]  s-    z(=rvviGX r   )z.gitz.githubz.hub>   sshmodaldockerdaytonasingularityr<   )FN)NNz<============================================================)K__doc__r2  rx  hermes_constantsr   r   resysenumr   pathlibr   typingr   r   r   r   r	   r
   yamltools.registryr   ry  r2   r   HERMES_HOMEr   r  r  _PLATFORM_MAPcompilerr   	frozensetr   r  r=   r+   r   r-   r?   rE   rL   rT   rh   r}   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r  r!  r:  rJ  r  SKILLS_TOOL_DESCRIPTIONprintloadsr  r   rQ   skillcatSKILLS_LIST_SCHEMASKILL_VIEW_SCHEMAregisterr1   r   r   <module>r     s  AF   , 	 	 
   8 8  #			8	$ 8#
  
 XWw
 ::9:  !<=  !UV    3  (
>	*Z?DEP6N% +/	$S
&4
P>&"Je JZ(VLS^ASHWSv:  z	
!"	(O 

&'ZZ&FiVG_%[VZZb5Q1R0SS^_	
 	VZZb9:;<"#H%c**E/4yy/D/DAeJ'(+"CF3%fb}1Ec1J0K3OP + 	w()* 

+,ZZ
9-.Fivf~&'(fjj>tDESIJ VI%6!7 8?@::n%%N6.#9":;<w()* 

RSZZ
9.MNOFivf~&'( VI%6!7 8?@	&+D12#67w()* MkK
 	B	   L  ~Y    F	
 	VH & 	  	 '
	 	  	 '
	r   