+
    Ӄi;5                     ~  a  R t0 t R t^ RIt^ RIt^ RIt^ RIHt ^ RIHt ^ RIH	t	H
t
Ht ]P                  ! ]4      t/ s] ^ k ]P                   ! R4      t]P                   ! R4      t]P                   ! R4      tRRR/R	 R
 llltRR R lltR R ltRR R lltR R ltR R ltR R ltRR R lltRR R lltR# ) zShared slash command helpers for skills and built-in prompt-style modes.

Shared between CLI (cli.py) and gateway (gateway/run.py) so both surfaces
can invoke skills via /skill-name commands and prompt-only built-ins like
/plan.
N)datetime)Path)AnyDictOptionalz
[^a-z0-9]+z
[^a-z0-9-]z-{2,}nowc                J    V ^8  d   QhR\         R\        R,          R\        /# )   user_instructionr   Nreturn)strr   r   )formats   "1/home/ubuntu/hermes-agent/agent/skill_commands.py__annotate__r      s1     @ @@ 
D@ 
	@    c               $   V '       d0   T ;'       g    RP                  4       P                  4       ^ ,          MRp\        P                  RVP	                  4       4      P                  R4      pV'       dE   RP                  R VP                  R4      R,           4       4      R,          P                  R4      pT;'       g    RpT;'       g    \        P                  ! 4       P                  R4      p\        R4      R	,          V RV R
2,          # )an  Return the default workspace-relative markdown path for a /plan invocation.

Relative paths are intentional: file tools are task/backend-aware and resolve
them against the active working directory for local, docker, ssh, modal,
daytona, and similar terminal backends. That keeps the plan with the active
workspace instead of the Hermes host's global home directory.
 -c              3   8   "   T F  q'       g   K  Vx  K  	  R # 5iN .0parts   & r   	<genexpr>"build_plan_path.<locals>.<genexpr>'   s     E)<)<s   	
:N   N:N0   Nzconversation-planz%Y-%m-%d_%H%M%Sz.hermesplansz.md)strip
splitlines_PLAN_SLUG_REsublowerjoinsplitr   r   strftimer   )r
   r   slug_sourceslug	timestamps   &$   r   build_plan_pathr*      s     GW#))r002==?B\^KS+"3"3"56<<SADxxEC)<EEcJPPQTU&&&D&&001BCI	?W$)AdV3'???r   c          	          V ^8  d   QhR\         R\         R,          R\        \        \         \        3,          \        R,          \         3,          R,          /# )r	   skill_identifiertask_idNr   )r   tupledictr   r   )r   s   "r   r   r   -   sL     "/ "/# "/d
 "/eTXY\^aYaTbdhkodoqtTtNux|N| "/r   c                   T ;'       g    RP                  4       pV'       g   R#  ^ RIHpHp \	        V4      P                  4       pVP                  4       '       d9    \        VP                  4       P                  VP                  4       4      4      pMVP                  R4      p\        P                  ! V! WaR7      4      pTP                  R4      '       g   R# \        TP                  R4      ;'       g    T4      p\        TP                  R4      ;'       g    R4      p	Rp
T	'       d    T\	        T	4      P                  ,          p
YzT3#   \         d    Tp Li ; i  \         d     R# i ; i  \         d    Rp
 L8i ; i)	zOLoad a skill by name/path and return (loaded_payload, skill_dir, display_name).r   N)
SKILLS_DIR
skill_view/r-   successnamepath)r   tools.skills_toolr1   r2   r   
expanduseris_absoluter   resolverelative_to	Exceptionlstripjsonloadsgetparent)r,   r-   raw_identifierr1   r2   identifier_path
normalizedloaded_skill
skill_name
skill_path	skill_dirs   &&         r   _load_skill_payloadrJ   -   sV   &,,"335N<~.99;&&((, !8!8!:!F!FzGYGYG[!\]
 (..s3Jzz*Z"IJ I&&\%%f-;;<J\%%f-334JI	"T*%5%<%<<I J..+  ,+
,    	I	sG   7E" 6E /E" /E4 EE" EE" "E10E14FFc                l    V ^8  d   QhR\         \        \        3,          R\        \        ,          RR/# )r	   rF   partsr   N)r/   r   r   list)r   s   "r   r   r   R   s-     $ $tCH~ $d3i $D $r   c                     ^ RI HpHpHp \	        V P                  R4      ;'       g    V P                  R4      ;'       g    R4      pV'       g   R# V! V4      w  rgV! V4      pV'       g   R# V! V4      p	V	'       g   R# RR.p
V	P                  4        F1  w  rV'       d   \	        V4      MRpV
P                  RV R	V 24       K3  	  V
P                  R
4       VP                  V
4       R#   \         d     R# i ; i)aQ  Resolve and inject skill-declared config values into the message parts.

If the loaded skill's frontmatter declares ``metadata.hermes.config``
entries, their current values (from config.yaml or defaults) are appended
as a ``[Skill config: ...]`` block so the agent knows the configured values
without needing to read config.yaml itself.
)extract_skill_config_varsparse_frontmatterresolve_skill_config_valuesraw_contentcontentr   Nz+[Skill config (from ~/.hermes/config.yaml):z	(not set)z  z = ])
agent.skill_utilsrO   rP   rQ   r   rA   itemsappendextendr=   )rF   rL   rO   rP   rQ   rR   frontmatter_config_varsresolvedlineskeyvaluedisplay_vals   &&            r   _inject_skill_configra   R   s    	
 	
 ,**=9^^\=M=Mi=X^^\^_*;7/<.{;BC"..*JC(-#e*;KLL2cU#k]34 + 	SU s/   &C. C. C. C. /C. A+C. .C=<C=c                    V ^8  d   QhR\         \        \        3,          R\        R,          R\        R\        R\        R\        /# )r	   rF   rI   Nactivation_noter
   runtime_noter   )r/   r   r   r   )r   s   "r   r   r   y   sX     L LsCx.Ld{L L 	L
 L 	Lr   c                   ^ RI Hp \        V P                  R4      ;'       g    R4      pVRVP	                  4       .p\        W4       V P                  R4      '       d   VP                  RR.4       MV P                  R4      '       d    VP                  RRV R,           R2.4       MLV P                  R	4      '       d6   V P                  R
4      '       d   VP                  RRV R
,           R2.4       . pV P                  R4      ;'       g    / p	V	P                  4        F,  p
\        V
\        4      '       g   K  VP                  V
4       K.  	  V'       g   V'       d   R F  pW,          pVP                  4       '       g   K#  \        VP                  R4      4       FF  pVP                  4       '       g   K  \        VP                  V4      4      pVP                  V4       KH  	  K  	  V'       dx   V'       dp    \        VP                  V4      4      pVP                  R4       VP                  R4       V F  pVP                  RV 24       K  	  VP                  RV R24       V'       d&   VP                  R4       VP                  RV 24       V'       d'   VP                  R4       VP                  RV R24       RP%                  V4      #   \          d    TP"                  p Li ; i)z9Format a loaded skill into a user/system message payload.)r1   rS   r   setup_skippedz[Skill setup note: Required environment setup was skipped. Continue loading the skill and explain any reduced functionality if it matters.]gateway_setup_hintz[Skill setup note: rT   setup_needed
setup_notelinked_files*zH[This skill has supporting files you can load with the skill_view tool:]z- z-
To view any of these, use: skill_view(name="z", file_path="<path>")zPThe user has provided the following instruction alongside the skill invocation: z[Runtime note: 
)
references	templatesscriptsassets)r8   r1   r   rA   r   ra   rX   values
isinstancerM   existssortedrglobis_filer<   rW   
ValueErrorr6   r$   )rF   rI   rc   r
   rd   r1   rS   rL   
supportingrj   entriessubdirsubdir_pathfrelskill_view_targetsfs   &&&&&            r   _build_skill_messager   y   s    -,""9-334Gb'--/2E -(( ^	
 
		.	/	/%l3G&H%IK	
 
		.	)	)l.>.>|.L.L%l<&@%AC	
 J##N399rL&&(gt$$g& ) )FF#,K!!## 1 1# 67Ayy{{!!--	":;"))#. 8 G i	/ #I$9$9*$E F 	R_`BLL2bT# <=N<OOef	
 Rghxgyz{R|nA6799U'  	/ )	/s   K K54K5c                h    V ^8  d   QhR\         \        \         \        \        3,          3,          /# r	   r   r   r   r   )r   s   "r   r   r      s%     > >T#tCH~"56 >r   c                 \   / s  ^ RIHp HpHpHp ^ RIHp V! 4       p\        4       p. pV P                  4       '       d   VP                  V 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                  RR7      p
V! V
4      w  rV! V4      '       g   K  VP!                  R	V	P"                  P$                  4      pW9   d   K  W9   d   K  VP!                  R
R4      pV'       gc   VP'                  4       P)                  R4       F?  pVP'                  4       pV'       g   K  VP+                  R4      '       d   K6  VR,          p M	  VP-                  V4       VP/                  4       P1                  RR4      P1                  RR4      p\2        P5                  RV4      p\6        P5                  RV4      P'                  R4      pV'       g   EK  R	TR
T;'       g    RV R2R\9        V	4      R\9        V	P"                  4      /\         RV 2&   EK  	  EK  	  \         #   \:         d     EK  i ; i  \:         d	     \         # i ; i)zScan ~/.hermes/skills/ and return a mapping of /command -> skill info.

Returns:
    Dict mapping "/skill-name" to {name, description, skill_md_path, skill_dir}.
)r1   _parse_frontmatterskill_matches_platform_get_disabled_skill_names)get_external_skills_dirszSKILL.mdc              3   *   "   T F	  qR9   x  K  	  R# 5i).gitN)r   z.githubz.hubr   r   s   & r   r   &scan_skill_commands.<locals>.<genexpr>   s     V~t::~s   TFzutf-8)encodingr6   descriptionr   rl   #:NP   N r   rZ   zInvoke the z skillskill_md_pathrI   r3   )_skill_commandsr8   r1   r   r   r   rU   r   setrs   rW   rX   ru   anyrL   	read_textrA   rB   r6   r   r%   
startswithaddr#   replace_SKILL_INVALID_CHARSr"   _SKILL_MULTI_HYPHENr   r=   )r1   r   r   r   r   disabled
seen_namesdirs_to_scanscan_dirskill_mdrS   rY   bodyr6   r   linecmd_names                    r   scan_skill_commandsr      s>    O5ww>,.%
 
+467$H$NN:63Vx~~V333Vx~~VVV#&00'0BG(:7(C%K1+>> &??68??3G3GHD) ' "-//-"DK&$(JJL$6$6t$<D#'::<D#tDOOC,@,@.23i %	 %=
 NN4(  $zz|33C=EEc3OH377HEH266sHEKKCPH# %{'P'PD66P'X#S%9	7OazN3? 7 %T 	 !  s   B#J *$J J *J<J >,J*J ,J2J 4J7J
J#BJ4J 7J2J5
J JJ JJ J+*J+c                h    V ^8  d   QhR\         \        \         \        \        3,          3,          /# r   r   )r   s   "r   r   r   	  s%      Dd38n!45 r   c                 :    \         '       g   \        4        \         # )z@Return the current skill commands mapping (scan first if empty).)r   r   r   r   r   get_skill_commandsr   	  s    ?r   c                F    V ^8  d   QhR\         R\        \         ,          /# )r	   commandr   r   r   )r   s   "r   r   r     s"     @ @s @x} @r   c                f    V '       g   R# RV P                  RR4       2pV\        4       9   d   V# R# )u2  Resolve a user-typed /command to its canonical skill_cmds key.

Skills are always stored with hyphens — ``scan_skill_commands`` normalizes
spaces and underscores to hyphens when building the key. Hyphens and
underscores are treated interchangeably in user input: this matches
``_check_unavailable_skill`` and accommodates Telegram bot-command names
(which disallow hyphens, so ``/claude-code`` is registered as
``/claude_code`` and comes back in the underscored form).

Returns the matching ``/slug`` key from ``get_skill_commands()`` or
``None`` if no match.
Nr3   rZ   r   )r   r   )r   cmd_keys   & r   resolve_skill_command_keyr     s8     '//#s+,-G!3!557?4?r   c                x    V ^8  d   QhR\         R\         R\         R,          R\         R\        \         ,          /# )r	   r   r
   r-   Nrd   r   r   )r   s   "r   r   r   #  sB     # ### 4Z# 	#
 c]#r   c                    \        4       pVP                  V 4      pV'       g   R# \        VR,          VR7      pV'       g   RVR,           R2# Vw  rxp	RV	 R2p
\        VVV
VVR	7      # )
a-  Build the user message content for a skill slash command invocation.

Args:
    cmd_key: The command key including leading slash (e.g., "/gif-search").
    user_instruction: Optional text the user typed after the command.

Returns:
    The formatted message string, or None if the skill wasn't found.
NrI   r4   z[Failed to load skill: r6   rT   z#[SYSTEM: The user has invoked the "zf" skill, indicating they want you to follow its instructions. The full skill content is loaded below.])r
   rd   )r   rA   rJ   r   )r   r
   r-   rd   commands
skill_infoloadedrF   rI   rG   rc   s   &&&&       r   build_skill_invocation_messager   #  s     "#Hg&J K!8'JF(F);(<A>>*0'LZ
-j\ :S 	S   )! r   c          
          V ^8  d   QhR\         \        ,          R\        R,          R\        \        \         \        ,          \         \        ,          3,          /# )r	   skill_identifiersr-   Nr   )rM   r   r.   )r   s   "r   r   r   I  sB     '< '<Cy'<4Z'< 3S	49$%'<r   c                   . p. p. p\        4       pV  F  pT;'       g    RP                  4       pV'       d   Wu9   d   K-  VP                  V4       \        WqR7      pV'       g   VP	                  V4       Ke  Vw  rpRV R2pVP	                  \        V	V
V4      4       VP	                  V4       K  	  RP                  V4      W43# )zzLoad one or more skills for session-wide CLI preloading.

Returns (prompt_text, loaded_skill_names, missing_identifiers).
r   r4   z6[SYSTEM: The user launched this CLI session with the "z~" skill preloaded. Treat its instructions as active guidance for the duration of this session unless the user overrides them.]z

)r   r   r   rJ   rW   r   r$   )r   r-   prompt_partsloaded_namesmissingseenrC   
identifierr   rF   rI   rG   rc   s   &&           r   build_preloaded_skills_promptr   I  s     !L LGUD+$**113
Z/$ZANN:&.4+DZL Q7 7 	
 	 	
 	J'1 ,4 ;;|$l;;r   c                    V ^8  d   Qh/ ^ \         9   d,   \        \        \        \        \        3,          3,          ;R&   # )r	   r   )__conditional_annotations__r   r   r   )r   s   "r   r   r      s0        0 /c4S>)* /!r   )r   r   )r   r   )r   Nr   )r   __doc__r?   loggingrer   pathlibr   typingr   r   r   	getLogger__name__loggerr   compiler!   r   r   r*   rJ   ra   r   r   r   r   r   r   r   )r   s   @r   <module>r      s      	   & &			8	$-/ /

=)zz-0 jj* @  @ @*"/J$NL^>B@&#L'< '<r   