
    Ki۾                     
   d Z ddlZddlZddlmZ ddlZddlZddlZddlm	Z	 ddl
mZ ddlmZmZmZmZmZmZ ddlZddlmZ  ej        e          Z e            Zedz  Zd	Zd
ZddddZ ej        d          Z e d          Z! e h d          Z"da#dee$e$f         fdZ% G d de$e	          Z&ddZ'dee$ef         de(fdZ)dedee$         fdZ*dee$ef         deee$         ee$         f         fdZ+dee$ef         dee$ef         fdZ,	 ddee$ef         dee$         dz  deee$ef                  fdZ-de$d eee$ef                  dee$ef         fd!Z.de(fd"Z/de$fd#Z0	 dd$e$d%ee$e$f         dz  de(fd&Z1dd'd(eee$ef                  d)ee$ef         d%ee$e$f         dz  dee$         fd*Z2de$fd+Z3	 dd,e&d-ee$         d.e$dz  de$dz  fd/Z4de(fd0Z5d1e$deee$ef         e$f         fd2Z6d3edee$         fd4Z7d1e$de8fd5Z9dee$         fd6Z:dee$         fd7Z;dd8e$d9e$de(fd:Z<d;d<d=e(deee$ef                  fd>Z=d?edee$         fd@Z>ddAe(dBe$de$fdCZ?ddDe$dBe$de$fdEZ@dd8e$dFe$dBe$de$fdGZAdHZBedIk    ro	  eCdJ            eCdK            eCdL            ejD         e@                      ZEeEdM         r eCdNeEdO          dP eFeEG                    dQg                      dR            eCdSeEG                    dQg                        eCdT           eEd         ddU         D ]MZHeHG                    dD          rdVeHdD          dWndXZI eCdYeI eHd8          dZeHd[         dd\          d]           Nn eCd^eEd_                      eCd`            ejD         eAda                    ZEeEdM         r eCdbeEd8                      eCdceEG                    d[dd          dde          d]            eCdf eFeEd1                    dg           eEG                    dh          r eCdieEdh                     n eCd^eEd_                      eCdj            ejD         eAdadk                    ZEeEdM         rP eCdleEdm                      eCdf eFeEd1                    dg            eCdneEd1         ddo          d]           n eCd^eEd_                     dpdqdrdDdsdtduig dvdwZJdxdydrdsdzdudsd{dud|d8gdvdwZK ejL        dpdeJd} e5d~            ejL        dxdeKd e5d~           dS )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skills@   i   darwinlinuxwin32)macosr   windowsz^[A-Za-z_][A-Za-z0-9_]*$)z.gitz.githubz.hub>   sshmodaldockerdaytonasingularityreturnc                     t                      dz  } i }|                                 s|S |                                 5 }|D ]}|                                }|rn|                    d          sYd|v rU|                    d          \  }}}|                                                    d          ||                                <   	 ddd           n# 1 swxY w Y   |S )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          ./home/ubuntu/hermes-agent/tools/skills_tool.pyload_envr+   m   s.     6)H!H?? 	 CA 	C 	CD::<<D CDOOC00 CSD[[ $s 3 3Q(-(;(;E(B(B%		CC C C C C C C C C C C C C C C Os   B
CCCc                       e Zd ZdZdZdZdS )SkillReadinessStatus	availablesetup_neededunsupportedN)__name__
__module____qualname__	AVAILABLESETUP_NEEDEDUNSUPPORTED     r*   r-   r-   }   s        I!LKKKr8   r-   c                 
    | a d S N)_secret_capture_callback)callbacks    r*   set_secret_capture_callbackr=      s    'r8   frontmatterc                 $    ddl m}  ||           S )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.
    r   )skill_matches_platform)agent.skill_utilsr@   )r>   _impls     r*   r@   r@      s'     BAAAAA5r8   r)   c                 R    | sg S t          | t                    r| g} d | D             S )Nc                 n    g | ]2}t          |                                          #t          |          3S r7   strr    ).0items     r*   
<listcomp>z2_normalize_prerequisite_values.<locals>.<listcomp>   s3    ===$3t99??+<+<=CII===r8   )
isinstancerF   )r)   s    r*   _normalize_prerequisite_valuesrK      s<     	% ==%====r8   c                     |                      d          }|rt          |t                    sg g fS t          |                     d                    t          |                     d                    fS )Nprerequisitesr$   commands)getrJ   dictrK   )r>   prereqss     r*   _collect_prerequisite_valuesrR      so     ooo..G *Wd33 2v&w{{:'>'>??&w{{:'>'>?? r8   c           	         |                      d          }t          |t                    sd g dS |                     d          }t          |t                    r5|                                r!t          |                                          nd }|                     d          }t          |t                    r|g}t          |t
                    sg }g }|D ]}t          |t                    st          |                     d          pd                                          }|sRt          |                     d          pd|                                           }t          |                     d	          p|                     d
          pd                                          }	||t          |                     dd                    d}
|	r|	|
d	<   |                    |
           ||dS )Nsetup)helpcollect_secretsrU   rV   env_var promptEnter value for provider_urlurlsecretT)rW   rY   r]   )rO   rJ   rP   rF   r    listboolappend)r>   rT   	help_textnormalized_helpcollect_secrets_rawrV   rH   rW   rY   r[   entrys              r*   _normalize_setup_metadatare      s   OOG$$EeT"" 5444		&!!I i%%	*3//*;*;	I   ))$566%t,, 423)400 ! ,.O# & &$%% 	dhhy))/R006688 	TXXh''G+Gg+G+GHHNNPP488N33LtxxL"MMSSUU 488Hd3344!
 !

  	1$0E.!u%%%%  *  r8   legacy_env_varsc                   	 t          |           	|                     d          }t          |t                    r|g}t          |t                    sg }g t                      dt          t          t          f         dd f	fd}|D ]E}t          |t                    r |d|i           %t          |t                    r ||           F	d         D ]_} ||                    d          |                    d          |                    d	          p	                    d
          d           `|t          |           \  }}|D ]} |d|i           S )Nrequired_environment_variablesrd   r   c                    t          |                     d          p|                     d          pd                                          }|r|v rd S t                              |          sd S |t          |                     d          pd|                                           d}|                     d          p>|                     d          p)|                     d	          p                    d          }t          |t                     r+|                                r|                                |d<   |                     d
          }t          |t                     r+|                                r|                                |d
<                       |                               |           d S )NnamerW   rX   rY   rZ   )rj   rY   rU   r[   r\   required_for)rF   rO   r    _ENV_VAR_NAME_REmatchrJ   addr`   )rd   env_name
normalizedra   rk   requiredseenrT   s        r*   _append_requiredz=_get_required_environment_variables.<locals>._append_required   s   uyy((FEIIi,@,@FBGGMMOO 	8t++F%%h// 	F %))H--N1NH1N1NOOUUWW&
 &

 IIf !yy((!yy! yy  	 	 i%% 	3)//*;*; 	3!*!2!2Jvyy00lC(( 	>\-?-?-A-A 	>)5););)=)=J~&
#####r8   rj   rV   rW   rY   r[   rU   )rj   rY   rU   )
re   rO   rJ   rP   r^   setr   rF   r   rR   )
r>   rf   required_rawrs   rH   r(   rW   rq   rr   rT   s
          @@@r*   #_get_required_environment_variablesrv      s    &k22E??#CDDL,%% &$~lD)) %'HUUD$S#X $4 $ $ $ $ $ $ $ $8  # #dC   	fd^,,,dD!! 	#T"""'( 
 
++((8,,00EEIIf4E4E 	
 	
 	
 	
 9+FF" , ,&'*++++Or8   
skill_namemissing_entriesc                    |sg dd dS d |D             }t                      r|dt                      dS t          |dd dS d}g }|D ]9}d| i}|                    d          r|d         |d<   |                    d          r|d         |d<   	 t          |d         |d         |          }nB# t          $ r5 t
                              d	|d          d
           d|d         dd
d}Y nw xY wt          |t                    o!t          |                    d                    }t          |t                    o!t          |                    d                    }	|r|	sd
}|
                    |d                    ;||d dS )NF)missing_namessetup_skippedgateway_setup_hintc                     g | ]
}|d          S rj   r7   )rG   rd   s     r*   rI   z;_capture_required_environment_variables.<locals>.<listcomp>   s    @@@uU6]@@@r8   rw   rU   rk   rj   rY   z#Secret capture callback failed for Texc_info)success	stored_as	validatedskippedr   r   )_is_gateway_surface_gateway_setup_hintr;   rO   	ExceptionloggerwarningrJ   rP   r_   r`   )
rw   rx   rz   r{   remaining_namesrd   metadatacallback_resultr   r   s
             r*   '_capture_required_environment_variablesr     s7     
""&
 
 	
 A@@@@M 
*""5"7"7
 
 	
  '*""&
 
 	
 M!#O  ". ". *-99V 	-$V}HV99^$$ 	=',^'<H^$	6fh OO
  		 		 		NNEeFmEEPT     !"6]"	 OOO			 _d33 
	**9
 9
 _d33 
	**9
 9
  	7 	uV}---- )&"  s   B..<C-,C-c                  p    t          j        d          rdS t          t          j        d                    S )NHERMES_GATEWAY_SESSIONTHERMES_SESSION_PLATFORM)osgetenvr_   r7   r8   r*   r   r   ]  s3    	y)** t	344555r8   c                      t          t          j        dd                                                                                    pdS )NTERMINAL_ENVlocal)rF   r   r   r    lowerr7   r8   r*   _get_terminal_backend_namer   c  s9    ry112288::@@BBMgMr8   var_nameenv_snapshotc                     |t                      }| |v r"t          |                    |                     S t          t          j        |                     S r:   )r+   r_   rO   r   r   )r   r   s     r*   _is_env_var_persistedr   g  sR     zz<L$$X..///	(##$$$r8   r   required_env_varscapture_resultc                    t          |d                   }|t                      }g }| D ]3}|d         }||v st          ||          s|                    |           4|S )Nrz   rj   )rt   r+   r   r`   )r   r   r   rz   	remainingrd   rj   s          r*   %_remaining_required_environment_namesr   q  sx     788MzzI" # #V}=  (=dL(Q(Q T"""r8   c                  6    	 ddl m}  | S # t          $ r Y dS w xY w)Nr   *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     sQ    SUUUUUU99 S S S S  S  SSs   
 
readiness_statusmissing
setup_helpc                 z    | t           j        k    r*|rd                    |          nd}d| d}|r| d| S |S d S )Nz, zrequired prerequisitesz.Setup needed before using this skill: missing . )r-   r5   join)r   r   r   missing_strnotes        r*   _build_setup_noter     se    
 /<<<,3Qdii(((9QNNNN 	*))Z)))4r8   c                      dS )zOSkills are always available -- the directory is created on first use if needed.Tr7   r7   r8   r*   check_skills_requirementsr     s    4r8   contentc                 $    ddl m}  ||           S )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.
    r   )parse_frontmatter)rA   r   )r   r   s     r*   _parse_frontmatterr     s'     433333W%%%r8   
skill_pathc                     	 |                      t                    }|j        }t          |          dk    r|d         S dS # t          $ r Y dS w xY w)z
    Extract category from skill path based on directory structure.

    For paths like: ~/.hermes/skills/mlops/axolotl/SKILL.md -> "mlops"
       r   N)relative_to
SKILLS_DIRpartslen
ValueError)r   rel_pathr   s      r*   _get_category_from_pathr     s`    ))*55u::??8Ot   tts   ;A   
AAc                 &    t          |           dz  S )z
    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r8   c                 4   | sg S t          | t                    rd | D             S t          |                                           } |                     d          r|                     d          r
| dd         } d |                     d          D             S )uB  
    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
    c                 T    g | ]%}|t          |                                          &S r7   rE   rG   ts     r*   rI   z_parse_tags.<locals>.<listcomp>  s+    8881a8A888r8   []   c                     g | ]=}|                                 |                                                      d           >S )r   )r    r   s     r*   rI   z_parse_tags.<locals>.<listcomp>  s9    OOOqQWWYYOAGGIIOOE""OOOr8   ,)rJ   r^   rF   r    r!   endswithsplit)
tags_values    r*   _parse_tagsr     s      	 *d## 988
8888 Z&&((JS!! &j&9&9#&>&> &"%
OOJ,<,<S,A,AOOOOr8   c                  "    ddl m}   |             S )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.
    r   get_disabled_skill_names)rA   r   r   s    r*   _get_disabled_skill_namesr     s%     ;:::::##%%%r8   rj   platformc                 0   ddl }	 ddlm}  |            }|                    di           }|p |j        d          }|r/|                    di                               |          }|| |v S | |                    dg           v S # t
          $ r Y dS w xY w)	z'Check if a skill is disabled in config.r   N)load_configr   HERMES_PLATFORMplatform_disableddisabledF)r   hermes_cli.configr   rO   r   r   )rj   r   r   r   config
skills_cfgresolved_platformr   s           r*   _is_skill_disabledr     s    III111111ZZ"--
$D		2C(D(D 	1 */BB G G K KL] ^ ^ ,000z~~j"5555   uus   A(B /B 
BBF)skip_disabledr   c           	         ddl m} g }t                      }| rt                      nt                      }g }t                                          r|                    t                     |                     |                       |D ]}|                    d          D ]}t          d |j
        D                       r"|j        }	 |                    d          dd         }	t          |	          \  }
}t          |
          sj|
                    d	|j                  dt"                   }||v r||v r|
                    d
d          }|sY|                                                    d          D ]1}|                                }|r|                    d          s|} n2t+          |          t,          k    r|dt,          dz
           dz   }t/          |          }|                    |           |                    |||d           y# t2          t4          f$ r'}t6                              d||           Y d}~d}~wt:          $ r)}t6                              d||d           Y d}~d}~ww xY w|S )a^  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   get_external_skills_dirsSKILL.mdc              3   (   K   | ]}|t           v V  d S r:   _EXCLUDED_SKILL_DIRSrG   parts     r*   	<genexpr>z#_find_all_skills.<locals>.<genexpr>  (      KKD4//KKKKKKr8   utf-8encodingN  rj   descriptionrX   
r   r   ...)rj   r   categoryz Failed to read skill file %s: %sz)Skipping skill at %s: failed to parse: %sTr   )rA   r   rt   r   r   r   r`   extendrglobanyr   parent	read_textr   r@   rO   rj   MAX_NAME_LENGTHr    r   r!   r   MAX_DESCRIPTION_LENGTHr   rn   UnicodeDecodeErrorPermissionErrorr   debugr   )r   r   r   
seen_namesr   dirs_to_scanscan_dirskill_md	skill_dirr   r>   bodyrj   r   r&   r   es                    r*   _find_all_skillsr     s    ;:::::FeeJ &Fsuuu+D+F+FH L (J'''0022333  / / z22 .	 .	HKKHNKKKKK  I(",,g,>>uuE$6w$?$?!T-k:: "vy~>>?O?OP:%%8##)oomR@@" " $

 2 24 8 8 " "#zz|| "(<(< "*.K!E{##&<<<"-.I/E/I.I"JU"RK28<<t$$$ #. (      '8   ?1MMM   ?1W[     	U.	` Ms7   ?H,H8H=CHJ+IJI>>Jcategory_dirc                    | dz  }|                                 sdS 	 |                    d          }t          |          \  }}|                    dd          }|sY|                                                    d          D ]1}|                                }|r|                    d          s|} n2t          |          t          k    r|dt          d	z
           d
z   }|r|ndS # t          t          f$ r'}t                              d||           Y d}~dS d}~wt          $ r)}t                              d||d           Y d}~dS d}~ww xY w)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   rX   r   r   r   r   z*Failed to read category description %s: %sz)Error parsing category description %s: %sTr   )r   r   r   rO   r    r   r!   r   r   r   r   r   r   r   r   )r  	desc_filer   r>   r  r   r&   r  s           r*   _load_category_descriptionr	  M  s    //I t%%w%77.w77T "oomR88 	

**400  zz||  4 4 "&KE {444%&B(>(B&BCeKK)3{{t30   A9aPPPttttt   7APT 	 	
 	
 	
 ttttt	s$   CC) )E:DE)EEverbosetask_idc                    	 t                                           st          j        dg ddd          S i }i }t                               d          D ]}t          d |j        D                       r!	 t          |                    d	          d
d                   \  }}n# t          $ r i }Y nw xY wt          |          sst          |          }|r-|                    |d          dz   ||<   ||vrt           |z  ||<   g }t          |                                          D ]@}	||	         }
t          |
          }|	||	         d}|r||d<   |                    |           At          j        d|ddd          S # t          $ r0}t          j        dt#          |          dd          cY d
}~S d
}~ww xY w)aa  
    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
    TzNo skills directory found.)r   
categoriesmessageFensure_asciir   c              3   (   K   | ]}|t           v V  d S r:   r   r   s     r*   r   z$skills_categories.<locals>.<genexpr>  r   r8   r   r   Nr   r   r   )rj   skill_countr   zbIf a category is relevant to your task, use skills_list with that category to see available skills)r   r  hintr   error)r   r   jsondumpsr   r   r   r   r   r   r@   r   rO   sortedkeysr	  r`   rF   )r
  r  category_dirscategory_countsr  r>   r(   r   r  rj   r  r   	cat_entryr  s                 r*   skills_categoriesr  x  s`   5S  "" 	:#"$; 
 #    *,"((44 	D 	DHKKHNKKKKK !!3&&&88$?" "QQ  ! ! ! ! *+66 .x88H D,;,?,?!,L,Lq,P)=00.88.CM(+
=--//00 	) 	)D(.L4\BBK!%od6KLLI 7+6	-(i((((z(| 
 
 
 
 	
  S S Szec!ff==ERRRRRRRRRSsG   2F ?F 5.B$#F $B30F 2B33CF 
F=%F82F=8F=r   c                 b    	 t                                           s7t                               dd           t          j        dg g ddd          S t                      }|st          j        dg g ddd          S  r fd|D             }|                    d	 
           t          t          d |D                                 }t          j        d||t          |          ddd          S # t          $ r0}t          j        dt          |          dd          cY d}~S d}~ww xY w)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_okz>No skills found. Skills directory created at ~/.hermes/skills/)r   r   r  r  Fr  z%No skills found in skills/ directory.c                 F    g | ]}|                     d           k    |S )r   rO   )rG   sr   s     r*   rI   zskills_list.<locals>.<listcomp>  s/    QQQ1553D3D3P3P!3P3P3Pr8   c                 @    |                      d          pd| d         fS )Nr   rX   rj   r"  )r#  s    r*   <lambda>zskills_list.<locals>.<lambda>  s     quuZ'8'8'>B&	&J r8   )r'   c              3   j   K   | ].}|                     d           |                     d           V  /dS )r   Nr"  rG   r#  s     r*   r   zskills_list.<locals>.<genexpr>  s?      KKaz9J9JKj!!KKKKKKr8   z@Use skill_view(name) to see full content, tags, and linked files)r   r   r  countr  r  N)r   r   mkdirr  r  r  sortr  rt   r   r   rF   )r   r  
all_skillsr  r  s   `    r*   skills_listr,    s   3S  "" 
	TD999:# "$_	  #    &''
 		:# "$F	  #     	RQQQQZQQQJ 	JJKKK KK:KKKKK
 

 z$(ZZ  	
 	
 	
 		
  S S Szec!ff==ERRRRRRRRRSs+   AC4 *C4 >A5C4 4
D.>%D)#D.)D.	file_pathc                 v  >?@A 	 ddl m} g }t                                          r|                    t                     |                     |                       |st          j        dddd          S dAd}|D ]y}|| z  }|                                r |dz                                  r	|A|dz  } n?|	                    d	                                          r|	                    d	          } nz|s<|D ]9}|
                    d          D ]}|j        j        | k    r|j        A|} n|r n:|s3|D ]0}|
                    |  d	          D ]}	|	j        dk    r|	} n|r n1|r|                                s?d
 t                      dd         D             }
t          j        dd|  d|
ddd          S 	 |                    d          }n6# t          $ r)}t          j        dd|  d| dd          cY d}~S d}~ww xY wd}t                                          g}	 |                    d |dd         D                        n# t          $ r Y nw xY w|D ]=}	 |                                                    |           d} n# t$          $ r Y :w xY wg d}|                                >t)          >fd|D                       }|s|ryg }|r|                    d|            |r|                    d           ddl}|                    t.                                        d| d                    |                     i }	 t5          |          \  }}n# t          $ r i }Y nw xY wt7          |          s-t          j        dd|  dt8          j        j        dd          S |                    d|j        j                  }tA          |          rt          j        dd| d dd          S |rArtC          |          }d!|j"        v rt          j        dd"d#d$d          S A|z  }	 |                                }A                                }|#                    |          st          j        dd%d#d$d          S n5# tH          t$          f$ r! t          j        dd&| d'd(d$d          cY S w xY w|                                sg g g g g d)}A
                    d*          D ]/}|%                                r|j        dk    rtM          |                    A                    }|'                    d+          r|d,                             |           w|'                    d-          r|d.                             |           |'                    d/          r|d0                             |           |'                    d1          r|d2                             |           |j(        d3v r|d4                             |           1d5 |)                                D             }t          j        dd6| d7|  d8|d9d:d          S 	 |                    d          }nO# tT          $ rB t          j        d| |d;|j         d<|+                                j,         d=dd>d          cY S w xY wt          j        d| |||j(        d?d          S |}g }g } g }!g }"ArXAd,z  }#|#                                r!Afd@|#-                    dA          D             }Ad.z  }$|$                                r9dBD ]6}%|                     AfdC|$
                    |%          D                        7Ad0z  }&|&                                ra|&
                    d*          D ]K}|%                                r5|!                    tM          |                    A                               LAd2z  }'|'                                r9dDD ]6}%|"                    AfdE|'-                    |%          D                        7i }(|                    dF          })t]          |)t^                    r|)                    dGi           pi }(ta          |(                    dH          p|                    dHdI                    }*ta          |(                    dJ          p|                    dJdI                    }+i },|r||,d,<   | r| |,d.<   |!r|!|,d0<   |"r|"|,d2<   	 tM          |                    t                              }-nO# t$          $ rB |j        j        r,tM          |                    |j        j                            n|j        }-Y nw xY w|                    dAs|j1        nAj                  }.te          |          \  }/}tg          ||/          }0ti                      }1tk                      ??fdK|0D             }2tm          |.|2          }3|2rtk                      ?to          |0|3?L          @tq          @          }4@fdM|0D             }5|5r@	 ddNl9m:}6  |6|5           n-# t          $ r  tv          <                    dO|.dP           Y nw xY w|                    dQg           }7t]          |7tz                    sg }7g }8|7rD	 ddRl>m?}9  |9|7          }8|8rd}4n-# t          $ r  tv          <                    dS|.dP           Y nw xY wi dTdd|.dU|                    dUdI          dH|*dJ|+dV|dW|-dX|,r|,nddY|,rdZndd[|0d\g d]@d^|8d_g d`|4da|3da         db|4rt8          j@        j        nt8          jA        j        }:t          dc |0D             d          };|;r|;|:dd<   |3de         r|3de         |:de<   |4r`df @D             dg |8D             z   }<t          t8          j@        |<|;          }=|1t          v r|=r|= dh|1E                                 di}=|=r|=|:dj<   |                    dk          r|dk         |:dk<   t]          |)t^                    r|)|:dF<   t          j        |:d          S # t          $ r0}t          j        dtM          |          dd          cY d}~S d}~ww xY w)la  
    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   FzISkills directory does not exist yet. It will be created on first install.r  r  Nr   .mdc                     g | ]
}|d          S r~   r7   r'  s     r*   rI   zskill_view.<locals>.<listcomp>F  s    DDDq6DDDr8      zSkill 'z' not found.z+Use skills_list to see all available skills)r   r  available_skillsr  r   r   zFailed to read skill 'z': Tc              3   >   K   | ]}|                                 V  d S r:   )resolve)rG   ds     r*   r   zskill_view.<locals>.<genexpr>b  s*       C C C C C C C Cr8   r   )	zignore previous instructionszignore all previouszyou are nowzdisregard yourzforget your instructionsznew instructions:zsystem prompt:z<system>z]]>c              3       K   | ]}|v V  	d S r:   r7   )rG   p_content_lowers     r*   r   zskill_view.<locals>.<genexpr>z  s(      !S!S!!~"5!S!S!S!S!S!Sr8   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   r  r   rj   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 directory)r   r  r  z&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/r:  z
templates/r;  zassets/r<  zscripts/r=  )r/  z.pyz.yamlz.ymlz.jsonz.texz.shr>  c                     i | ]
\  }}|||S r7   r7   )rG   kvs      r*   
<dictcomp>zskill_view.<locals>.<dictcomp>  s#    "Q"Q"QDAqq"Q1a"Q"Q"Qr8   zFile 'z' not found in skill 'z'.z0Use one of the available file paths listed above)r   r  available_filesr  z[Binary file: z, size: z bytes])r   rj   filer   	is_binary)r   rj   rE  r   	file_typec                 T    g | ]$}t          |                                        %S r7   rF   r   rG   r%   r  s     r*   rI   zskill_view.<locals>.<listcomp>  s:     # # #67Ci0011# # #r8   *.md)rK  *.pyz*.yamlz*.ymlz*.jsonz*.tex*.shc                 T    g | ]$}t          |                                        %S r7   rI  rJ  s     r*   rI   zskill_view.<locals>.<listcomp>.  s=        !  i 8 899  r8   )rL  rM  z*.bashz*.jsz*.tsz*.rbc                 T    g | ]$}t          |                                        %S r7   rI  rJ  s     r*   rI   zskill_view.<locals>.<listcomp>?  s-    VVV1Q]]95566VVVr8   r   hermestagsrX   related_skillsc                 @    g | ]}t          |d                    |S r~   )r   )rG   r  r   s     r*   rI   zskill_view.<locals>.<listcomp>g  s=     %
 %
 %
(6LAA%
%
 %
 %
r8   r   c                 4    g | ]}|d          v|d          S r~   r7   )rG   r  remaining_missing_required_envss     r*   rI   zskill_view.<locals>.<listcomp>|  s7     
 
 
y ??? fI???r8   )register_env_passthroughz/Could not register env passthrough for skill %sr   required_credential_files)register_credential_filesz0Could not register credential files for skill %sr   r   r   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'rh   required_commands&missing_required_environment_variablesmissing_credential_filesmissing_required_commandsr/   r{   r   c              3   P   K   | ]!}|                     d           |d          V  "dS )rU   Nr"  )rG   r  s     r*   r   zskill_view.<locals>.<genexpr>  s5      QQ155==Q1V9QQQQQQr8   r   r|   c                     g | ]}d | S )zenv $r7   )rG   ro   s     r*   rI   zskill_view.<locals>.<listcomp>  s.       '/"""  r8   c                     g | ]}d | S )zfile r7   )rG   rY  s     r*   rI   zskill_view.<locals>.<listcomp>  s+       #'  r8   r   zW-backed skills need these requirements available inside the remote environment as well.
setup_notecompatibility)FrA   r   r   r   r`   r   r  r  is_dirwith_suffixr   r   rj   r  r   r   r4  r   r   r   r   logging	getLoggerr1   r   r   r   r@   r-   r6   r)   rO   r   r   r   is_relative_toOSErroris_filerF   r!   suffixitemsr   statst_sizeglobrJ   rP   r   stemrR   rv   r   r+   r   r   r_   tools.env_passthroughrV  r   r   r^   tools.credential_filesrX  r5   r4   nextr   _REMOTE_ENV_BACKENDSupper)Brj   r-  r  r   all_dirsr  
search_dirdirect_pathfound_skill_mdfound_mdr.   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_resolvedrD  r%   relr>   reference_filestemplate_filesasset_filesscript_filesreferences_dirtemplates_dirext
assets_dirscripts_dirhermes_metar   rQ  rR  rZ  r   rw   rf   r   backendmissing_required_env_varsr   r/   available_env_namesrV  required_cred_files_rawmissing_cred_filesrX  resultr   missing_itemsrc  r8  r   rU  r  sB                                                                 @@@@r*   
skill_viewr    sj   KS>>>>>>  	(OOJ'''0022333 	:$h  #    	 # 		 		J$t+K!!## z)A(I(I(K(K '	&3((//6688 &22599
  	&  
&0&6&6z&B&B  N%,1T99$2$9	#1 :  E  	&  
 * 0 0D > >  H}
22#+ 3  E  
	x00 
	DD,<,>,>ss,CDDDI:$9t999(1I	  #   		(('(::GG 	 	 	:$BdBBqBB  #        	 ##++--.	   C Chqrrl C C CCCCC 	 	 	D	  	 	C  ""..s333&+#   

 

 

 !!!S!S!S!S?R!S!S!SSS 	t"5 	tI" x  !vlt!v!vwww" g  !efff&&&&x((001VX\^b^g^ghq^r^rsss-/	$$6w$?$?! 	$ 	$ 	$!#	$ &&899 	:$QtQQQ(<(H(N 
 #    +..vx7KLLm,, 
	:$`- ` ` `  #	 	 	 	  l	 l	"9ooO,,,z#(!H P 
 "'    $i/K&..00%.%6%6%8%8"../ABB :',%M$T 
 &+    Z(   z#(!D	!D!D!D V 
 "'      %%'' , #%!# !# # #-- A AAyy{{ Aqv';';!!--	":":;;>>-88 A+L9@@EEEE ^^L99 A+K8??DDDD ^^I66 A+H5<<SAAAA ^^J77 A+I6==cBBBBX *   ,G4;;C@@@ #R"QO4I4I4K4K"Q"Q"Qz#(!S)!S!S4!S!S!S+: R	  "'   %///AA%   z#' $ )#qK4D#q#qkN^N^N`N`Nh#q#q#q%)  "'	 	 	 	 	 	 :# %&!,!3  #	 	 	 	 )  %	&5N$$&& # # # #;I;N;Nv;V;V# # # &3M##%%   C #))   %2%8%8%=%=      #X-J  "" J#))#.. J JAyy{{ J#**3q}}Y/G/G+H+HIII#i/K!!## M  C ''VVVV@P@PQT@U@UVVV    ??:..h%% 	;",,x44:K;??622Qkoofb6Q6QRR$OO,--VAQSU1V1V
 

  	9)8L& 	7(6L% 	1%0L" 	3&2L#	v8//
;;<<HH 	v 	v 	vLTOLbus8//0FGGHHHhphuHHH	v !__FHMM	
 

 :+FF?
 
 -..zz%
 %
 %
 %
&%
 %
 %
!
 A%
 
 % 	&#::L*O%+
 +
 +
'
 ;<<

 
 
 
&
 
 

  
		JJJJJJ(()<====   E!       #.//2Mr"R"R1488 	)&(##%" 	LLLLLL%>%>?V%W%W"% (#'L   F!      
t
J
 ;??="==
 D	

 n
 w
 H
 LBLLd
   W  W
 -.?
  
 56U
 '(:
  (!
" L#
$ ^O<%
& !6 4 A G G%/5+
0 QQ.?QQQSWXX
 	.#-F< ./ 	P+9:N+OF'( 	2 3R   +=  M
 +$1 J
 ...:. *  V  VW]]__  V  V  V
 2'1|$ ???++ 	C&1/&BF?#h%% 	*!)F:z&u5555 S S Szec!ff==ERRRRRRRRRSs  A2q> 9Eq> G q> 
H#HHq> Hq> ,'I q> 
I!q>  I!!q> ))Jq> 
J!q>  J!!B5q> M* )q> *M96q> 8M99>q> 8Aq> 7q> <q> AR q> /S	q> SF%q> 3Z
 	q> 
A	[q> [#q> :H7q> 2'e q> A	f&#q> %f&&Cq> +i= <q> ='j'$q> &j''4q> k2 1q> 2'lq> lE!q> >
r8%r3-r83r8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 Testz<============================================================u   
📋 Listing all skills:r   zFound r(  z skills in r  z categorieszCategories: z
First 10 skills:
   r   z] rX   u     • z: r   <   r   zError: r  u   
📖 Viewing skill 'axolotl':axolotlzName: zDescription: zN/Ad   zContent length: z charsrZ  zLinked files: uE   
📄 Viewing reference file 'axolotl/references/dataset-formats.md':zreferences/dataset-formats.mdzFile: rE  z	Preview:    r,  zVList available skills (name + description). Use skill_view(name) to load full content.objectstringz*Optional category filter to narrow results)typer   )r  
propertiesrq   )rj   r   
parametersr  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)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.)rj   r-  c                 p    t          |                     d          |                    d                    S )Nr   r  )r   r  )r,  rO   argskws     r*   r%  r%  A  s2    {*%%rvvi/@/@      r8   u   📚)rj   toolsetschemahandlercheck_fnemojic                     t          |                     dd          |                     d          |                    d                    S )Nrj   rX   r-  r  )r-  r  )r  rO   r  s     r*   r%  r%  K  sB    z(=(=rvviGXGX      r8   )r   Nr:   )FN)NN)M__doc__r  rg  hermes_constantsr   r   resysenumr   pathlibr   typingr   r   r   r	   r
   r   yamltools.registryr   rh  r1   r   HERMES_HOMEr   r   r   _PLATFORM_MAPcompilerl   	frozensetr   ru  r;   rF   r+   r-   r=   r_   r@   rK   rR   re   rv   r   r   r   r   r   r   r   r   r   r   intr   r   r   r   r  r	  r  r,  r  SKILLS_TOOL_DESCRIPTIONprintloadsr  r   rO   skillcatSKILLS_LIST_SCHEMASKILL_VIEW_SCHEMAregisterr7   r8   r*   <module>r     s8  A AF   , , , , , , 				 				 



             8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8  # # # # # #		8	$	$ o8#
  
  
 2:9::  y!<==  y!U!U!UVV  $sCx.              3      ( ( ( (
S#X 4    ># >$s) > > > >	c3h	
49d3i 	 	 	 	*4S> *d38n * * * *^ )-? ?c3h?#Y%? 
$sCx.? ? ? ?DEE$sCx.)E 
#s(^E E E EP6T 6 6 6 6NC N N N N
 :>% %%!%c3h$!6%	% % % % +/	  DcN+cN sCx.4'	
 
#Y   $SS S S S S " *#Y d
 	4Z	   4    
& &d38nc.A(B & & & & #     
c 
c 
 
 
 
PtCy P P P P>&3s8 & & & & S C 4    " /4 J J Jt JT#s(^8L J J J JZ(T (hsm ( ( ( (VDS DSt DSc DSS DS DS DS DSNAS AS# ASs ASc AS AS AS ASHWS WSS WSS WS# WS WS WS WS WSv:  z	E
!"""	E(OOO 
E
&'''TZ&&Fi 
+_VG___VZZb5Q5Q1R1R___	
 	
 	
 	;VZZb99;;<<<"###H%crc* 	Q 	QE/4yy/D/DL+eJ'++++"CEO3OfOO}1Ecrc1JOOOPPPP	Q 	)w))*** 
E
+,,,TZ

9--..Fi +'vf~''(((Ifjj>>ttDIIIJJJ?VI%6!7!7???@@@::n%% 	=E;6.#9;;<<<)w))*** 
E
RSSSTZ

9.MNNOOFi +'vf~''(((?VI%6!7!7???@@@6&+DSD16667777)w))*** k K 
 	 	     ~ !Y 
 !  F 	
 	
 H   &  	  '
	 	 	 	  	  '
	 	 	 	 	 	r8   