+
    jHàj¸V  ã                  óx  a € 0 t $ R t^ RIHt ^ RIt^ RIt^ RIHtHtH	t	 ^ RI
Ht ^ RIHt ^ RIHtHtHtHt ]P&                  ! R4      t^ t]P,                  ! R4      t]P,                  ! R	4      tR
 R ltR R ltR R lt]P,                  ! R4      tR R ltR R ltR R ltRR/R R llt ^<t!^dt"RR9RR:RR;/t#R]$R&   R<t%R  R! lt&R" R# 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. R/ lt-^2t.^ t/]P,                  ! R04      t0]1! 0 R?m4      t2]1! 0 R@m4      t3R1 R2 lt4R3 R4 lt5RAR5 R6 llt6R7 R8 lt7R# )Bz]Gateway platform command derivations (Telegram / Discord / Slack) from ``COMMAND_REGISTRY``.
)ÚannotationsN)ÚCallableÚMappingÚSequence)ÚAny)Út)ÚCOMMAND_REGISTRYÚ_is_gateway_availableÚ_iter_plugin_command_entriesÚ_resolve_config_gateszhermes_cli.commandsz
[^a-z0-9_]z_{2,}c               ó   € V ^8„  d   QhRR/# )é   ÚreturnÚlist© )Úformats   "ÚB/home/ubuntu/.hermes/hermes-agent/hermes_cli/commands_platforms.pyÚ__annotate__r      s   € ÷ Vñ V Tñ Vó    c                 ór   € \        4       p \         Uu. uF  p\        W4      '       g   K  VNK  	  up# u upi )zFRegistry entries visible on gateway surfaces (config gates read once).)r   r   r	   )Ú	overridesÚcmds     r   Ú_gateway_available_commandsr      s.   € ä%Ó'€IÝ+ÓUÑ+�CÔ/DÀS×/T�CˆCÑ+ÑUÐUùÒUs   “4«4c               ó    € V ^8„  d   QhRRRR/# )r   Ú	args_hintÚstrr   Úboolr   )r   s   "r   r   r      s   € ÷ -ñ - #ð -¨$ñ -r   c                ó@   € V P                  4       P                  R4      # )z?True when selecting a command without text would be incomplete.Ú<)ÚstripÚ
startswith)r   s   &r   Ú_requires_argumentr!      s   € à�?‰?Ó×'Ñ'¨Ó,Ð,r   c               ó    € V ^8„  d   QhRRRR/# ©r   Úrawr   r   r   )r   s   "r   r   r   #   s   € ÷ 	:ñ 	: ð 	:¨ñ 	:r   c                ó|  € V P                  4       P                  RR4      p\        P                  RV4      p\        ;QJ d/    R \        P                  V4       4       F  '       g   K   RM$	  RM ! R \        P                  V4       4       4      '       d   R# \        P                  RV4      P                  R4      # )u  Telegram allows only ``[a-z0-9_]``: lowercase, hyphens -> ``_``, collapse/strip ``_``.
A name that would lose letters (``ä¸­æ–‡helper`` -> ``helper``) is omitted (``""``): the menu
entry could not resolve back to the registered ``/ä¸­æ–‡helper`` and would answer
"Unknown command".Ú-Ú_Ú c              3  ó@   "  € T F  qP                  4       x € K  	  R # 5i©N)Úisalnum)Ú.0Úchs   & r   Ú	<genexpr>Ú*_sanitize_telegram_name.<locals>.<genexpr>*   s   é € Ð
EÑ"D˜B�:‰:�<ˆ<Ó"Dùs   ‚TF)ÚlowerÚreplaceÚ_TG_INVALID_CHARSÚsubÚanyÚfindallÚ_TG_MULTI_UNDERSCOREr   )r$   ÚloweredÚnames   &  r   Ú_sanitize_telegram_namer9   #   sˆ   € ð
 �i‰i‹k×!Ñ! # sÓ+€GÜ× Ñ   WÓ-€Dß
ƒsÑ
EÔ"3×";Ñ";¸GÔ"DÓ
E‡s‡s‚sÑ
EÔ"3×";Ñ";¸GÔ"DÓ
E×EÒEÙÜ×#Ñ# C¨Ó.×4Ñ4°SÓ9Ð9r   u   [â€’â€“â€”â€•âˆ’]c               ó    € V ^8„  d   QhRRRR/# )r   Údescr   r   r   )r   s   "r   r   r   2   s   € ÷ %ñ % 3ð %¨3ñ %r   c                ó.   € \         P                  RV 4      # )z�Fold Unicode dashes (em/en/figure/horizontal-bar/minus) to ASCII ``-``.
BotFather rejects setMyCommands descriptions containing them (#2925).r&   )Ú
_TG_DASHESr3   )r;   s   &r   Ú_normalize_telegram_descr>   2   s   € ô �>‰>˜#˜tÓ$Ð$r   c               ó$   € V ^8„  d   QhRRRRRR/# )r   r;   r   ÚlimitÚintr   r   )r   s   "r   r   r   8   s&   € ÷ Dñ D˜ð D Sð D¨Sñ Dr   c                óL   € \        V 4      V8:  d   V # V RV^,
           R,           # )z>Clamp a menu description to *limit* chars with a ``...`` tail.Nz...)Úlen)r;   r@   s   &&r   Ú_truncate_descrD   8   s(   € ä�t“9 Ô%ˆ4ÐC¨4°
°¸µÐ+;¸eÕ+CÐCr   c               ó$   € V ^8„  d   QhRRRRRR/# )r   ÚentrieszSequence[tuple[str, ...]]Úreservedúset[str]r   zlist[tuple[str, ...]]r   )r   s   "r   r   r   =   s$   € ÷ ñ Ø&ðØ2:ðØ?Tñr   c                ó@  € \        V4      p. pV  FŠ  vrEp\        V4      \        8”  dD   VR\         pWr9   d3   VR\        ^,
           p\        ^
4       F  p	V V	 2pWr9  g   K   M	  KZ  TpWB9   d   Kd  VP	                  V4       VP                  WE.VO54       KŒ  	  V# )a  Enforce the 32-char Telegram/Discord name limit: over-long names are truncated; on a
collision with *reserved* or an earlier entry a 31-char prefix + digit ``0``-``9`` is tried,
then the entry is silently dropped. Duplicates are dropped; extra tuple elements pass through.
N)ÚsetrC   Ú_CMD_NAME_LIMITÚrangeÚaddÚappend)
rF   rG   ÚusedÚresultr8   r;   ÚextraÚ	candidateÚprefixÚdigits
   &&        r   Ú_clamp_command_namesrU   =   s¯   € ô ˜“]€DØ€FÛ%Ðˆ�UÜˆt‹9”Ô&ØÐ-œoÐ.ˆIØÔ ØÐ2œ°Õ2Ð3�Ü" 2žY�EØ#) (¨5¨'Ð 2�IØ Ö,Ùñ 'ñ
 ØˆDØŒ<ÙØ�‰�ŒØ�‰�tÐ* EÑ*Ö+ñ &ð  €Mr   Úinclude_pluginsTc               ó    € V ^8„  d   QhRRRR/# )r   rV   r   r   zlist[tuple[str, str]]r   )r   s   "r   r   r   Z   s   € ÷ sñ s¨dð sÐ>Sñ sr   c           	     ó~  € \        4        Uu. uF  qP                  VP                  4       3NK   	  ppV '       d=   T\        4        UUUu. uF  w  r4p\	        V4      '       d   K  W43NK  	  uppp,          pV UUu. uF'  w  rg\        V4      ;p'       g   K  V\        V4      3NK)  	  upp# u upi u upppi u uppi )a  (command_name, description) pairs for Telegram setMyCommands: sanitized canonical names
only (no aliases). Built-ins needing arguments are included (their handlers show usage when
selected bare); plugin commands needing arguments are excluded (may lack a no-arg fallback).)r   r8   Údescriber
   r!   r9   r>   )	rV   r   ÚpairsÚnÚdÚhintr8   r;   Útgs	   $        r   Útelegram_bot_commandsr_   Z   sª   € ô 4OÔ3PÓQÑ3P¨C�h‰h˜Ÿ™›Ó'Ñ3P€EÐQßØÔ+GÔ+Iõ 3Ñ+I™Z˜Q 4Ü+¨D×1ô �1“&Ñ+Ió 3õ 	3ˆáCHÔrÁ5±Z°TÔSjÐkoÓSpÐMpÈRÓMpÔ0ˆRÔ)¨$Ó/Ó0Á5ÒrÐrùò	 Rùô3ùãrs   �$B-Á
B2
Á%B2
Á<B9ÂB9ÚprependrN   r1   zdict[str, tuple[str, ...]]Ú_TELEGRAM_PRIORITY_TIERSc               ó   € V ^8„  d   QhRR/# )r   r   údict[str, Any]r   )r   s   "r   r   r   x   s   € ÷ ñ  ~ñ r   c                 ó€  €  ^ RI Hp  V ! 4       ;'       g    / pR F,  p\        V\        4      '       d   VP                  V4      MRpK.  	  \        V\        4      '       d   TM/ p \        VP                  R\        4      4      p\        VP                  R4      ;'       g    R4      P                  4       P                  4       pVP                  R4      p\        V\        4      '       d=   V Uu. uF/  p\        V4      P                  4       '       g   K$  \        V4      NK1  	  ppM1\        V\        4      '       d   VP                  4       '       d   V.M. pR\        ^\        \         V4      4      RV\"        9   d   VRV/# RRV/#   \         d    / p EL€i ; i  \        \        3 d    \        p EL2i ; iu upi )zONormalized ``platforms.telegram.extra.command_menu`` config with safe defaults.)Úread_raw_configNÚmax_commandsÚpriority_moder`   Úpriority)Ú	platformsÚtelegramrQ   Úcommand_menu)Úhermes_cli.configre   Ú	ExceptionÚ
isinstancer   ÚgetrA   Ú#_DEFAULT_TELEGRAM_MENU_MAX_COMMANDSÚ	TypeErrorÚ
ValueErrorr   r   r0   r   ÚmaxÚminÚ_TELEGRAM_BOT_API_MAX_COMMANDSra   )	re   ÚnodeÚkeyÚmenu_cfgrf   rg   Úraw_priorityÚitemrh   s	            r   Ú_telegram_command_menu_configr{   x   s  € ðÝ5Ù#Ó%×+Ð+¨ˆó BˆÜ *¨4´× 9Ò 9ˆt�x‰x˜Œ}¸tŠñ Bä*4°T¼7×*CÒ*C¡$È€Hð;Ü˜8Ÿ<™<¨Ô8[Ó\Ó]ˆô ˜Ÿ™ _Ó5×BÐB¸ÓC×IÑIÓK×QÑQÓS€MØ—<‘< 
Ó+€LÜ�,¤×%Ò%Ù*6ÓL©, $¼#¸d»)¿/¹/×:K”I”C˜–I©,ˆÐLˆä%/°¼c×%BÒ%BÀ|×GYÑGY×G[ÒG[�L‘>Ðacˆàœ˜AœsÔ#AÀ<ÓPÓQØ¨-Ô;SÔ*S˜Ø�Hðð àYbØ�Hðð øô ô Ø‹ðûô ”zÐ"ô ;Ü:‹ð;üò
 Ms4   ‚F	 –F	 Á&F Ã0!F;ÄF;Æ	FÆFÆF8Æ7F8c               ó   € V ^8„  d   QhRR/# )r   r   rA   r   )r   s   "r   r   r   ’   s   € ÷ @ñ @ Cñ @r   c                 ó6   € \        \        4       R,          4      # )z@Return configured Telegram BotCommand menu cap with safe bounds.rf   )rA   r{   r   r   r   Útelegram_menu_max_commandsr~   ’   s   € äÔ,Ó.¨~Õ>Ó?Ð?r   c               ó    € V ^8„  d   QhRRRR/# )r   Ú	raw_nameszSequence[str]r   zdict[str, int]r   )r   s   "r   r   r   —   s   € ÷ ñ ˜}ð °ñ r   c                ó‚   € / pV  F6  p\        \        V4      4      pV'       g   K!  W19  g   K)  \        V4      W&   K8  	  V# )zUname -> rank for the deduped, Telegram-sanitized *raw_names* (first occurrence wins).)r9   r   rC   )r€   Úrankr$   r8   s   &   r   Ú_sanitized_rankrƒ   —   s;   € à€DÛˆÜ&¤s¨3£xÓ0ˆß‰4�DÖ$Ü˜T›ˆD‹Jñ ð €Kr   c               ó    € V ^8„  d   QhRRRR/# )r   Ú
candidatesúlist[tuple[str, str, str, str]]r   r   )r   s   "r   r   r   ¡   s    € ÷ Yñ YØ/ðYØ4SñYr   c                ó  aaaa€ \        4       p\        VR,          4      o\        \        4      o\        VR,          ,          oR VVV3R llo\	        \        V 4      V3R lR7       UUu. uF  w  r#VNK	  	  upp# u uppi )zÚOrder ``(final_name, description, source, raw_name)`` candidates; the default priority
applies to core only, "replace" mode ignores it. ``raw_name`` is the pre-clamp name so a
configured long command stays addressable.rh   rg   c               ó$   € V ^8„  d   QhRRRRRR/# )r   Ústable_indexrA   rR   ztuple[str, str, str, str]r   ztuple[int, int, int]r   )r   s   "r   r   Ú:_prioritize_telegram_menu_candidates.<locals>.__annotate__«   s#   € ÷ -ñ -˜Cð -Ð,Eð -ÐJ^ñ -r   c                óú   <€ Vw  r#rER S	P                  VS	P                  V4      4      RVR8X  d   S
P                  V4      MR/p\        S4       F  w  rxWh,          f   K  WvV,          V 3u # 	  \        S4      ^ V 3# )Ú
configuredÚdefaultÚcoreN)ro   Ú	enumeraterC   )r‰   rR   Ú
final_nameÚ_descÚsourceÚraw_nameÚindexesÚtierÚtableÚconfigured_rankÚdefault_rankÚtierss   &&       €€€r   Ú_rankÚ3_prioritize_telegram_menu_candidates.<locals>._rank«   sˆ   ø€ Ø.7Ñ+ˆ
˜6à˜/×-Ñ-¨h¸×8KÑ8KÈJÓ8WÓXØ°vÀÔ7G�|×'Ñ'¨
Ô3ÈTðSˆô % UÖ+‰KˆDØ�~Ô)Ø e�n¨lÐ;Ò;ñ ,ô �E“
˜A˜|Ð,Ð,r   c                ó   <€ S! V !  # r*   r   )rz   rš   s   &€r   Ú<lambda>Ú6_prioritize_telegram_menu_candidates.<locals>.<lambda>µ   s
   ø€ É%ÐQUÊ,r   )rw   )r{   rƒ   Ú_TELEGRAM_MENU_PRIORITYra   Úsortedr�   )r…   rx   Ú_iÚcrš   r—   r˜   r™   s   &   @@@@r   Ú$_prioritize_telegram_menu_candidatesr£   ¡   sk   û€ ô
 -Ó.€HÜ% h¨zÕ&:Ó;€OÜ"Ô#:Ó;€LÜ$ X¨oÕ%>Õ?€E÷-ò -ô "¤)¨JÓ"7Ô=VÕWÔXÑW‘%�"‹AÑWÒXÐXùÓXs   Á,A=c               ó   € V ^8„  d   QhRR/# )r   Úplatformr   r   )r   s   "r   r   r   º   s   € ÷ ,?ñ ,? 3ñ ,?r   c              #  ó>  a"  € ^ RI Hp ^ RIHp ^ RIHpHpHp ^ RIH	p  V! V R7      pVR,          P                  4       pVP                  4       .p	WE3 F8  p
 V
! 4        F)  p V	P                  V! V4      P                  4       4       K+  	  K:  	  V! 4       p\        V4       F²  pWÍ,          pVP                  RR4      pV'       g   K'  V! V4      P                  4       oSP!                  V4      '       d   KV  \#        V3R	 lV	 4       R
4      pVe   VP                  RR4      V9   d   K‰  WÞSP$                  P'                  V4      P(                  3x € K´  	  R
#   \         d    \        4       p ELIi ; i  \         d     EK&  i ; i  \         d     EKD  i ; i5i)a7  Yield ``(cmd_key, info, rel_parts)`` for skills eligible as gateway slash commands.

Scan roots: ``SKILLS_DIR`` plus ``skills.external_dirs`` / trusted project skills dirs;
anything elsewhere or under ``SKILLS_DIR/.hub`` is skipped, as are skills disabled for
*platform*. Paths are resolved on both sides (symlinked roots still match) and matched per
path component (``/my-skills`` never admits ``/my-skills-extra``). ``rel_parts`` is the skill
dir relative to its root (``("creative", "ascii-art")``). Alphabetical so first-wins
collision handling is deterministic.
)ÚPath)Úget_skill_commands)Úget_disabled_skill_namesÚget_external_skills_dirsÚget_project_skills_dirs)Ú
SKILLS_DIR)r¥   z.hubÚskill_md_pathr(   c              3  óZ   <"  € T F   pSP                  V4      '       g   K  Vx € K"  	  R # 5ir*   )Úis_relative_to)r,   ÚrÚsps   & €r   r.   Ú'_iter_gateway_skills.<locals>.<genexpr>ã   s    øé € Ð>¡˜1¨×):Ñ):¸1×)=—Q’Q£ùs   ƒ+¡
+Nr8   )Úpathlibr§   Úagent.skill_commandsr¨   Úagent.skill_utilsr©   rª   r«   Útools.skills_toolr¬   rm   rJ   ÚresolverN   r    ro   r¯   ÚnextÚparentÚrelative_toÚparts)r¥   r§   r¨   r©   rª   r«   r¬   ÚdisabledÚhub_dirÚrootsÚgetterr\   Ú
skill_cmdsÚcmd_keyÚinfoÚ
skill_pathÚrootr±   s   &                @r   Ú_iter_gateway_skillsrÅ   º   sr  øé € õ å7÷Uñ Uå,ðÙ+°XÔ>ˆð ˜FÕ"×+Ñ+Ó-€GØ×ÑÓ!Ð"€EØ+ÓEˆð	Ù–X�ðØ—L‘L¡ a£§¡Ó!2Ö3ó ñ Fñ $Ó%€JÜ˜*Ö%ˆØÕ"ˆØ—X‘X˜o¨rÓ2ˆ
ßÙÙ�*Ó×%Ñ%Ó'ˆØ×Ñ˜W×%Ò%ÙÜÔ>¡Ó>ÀÓEˆØŠ<˜4Ÿ8™8 F¨BÓ/°8Ô;ÙØ˜RŸY™Y×2Ñ2°4Ó8×>Ñ>Ð>Ô>ó &øô ô Ü“5‹ðûô !ô Ûðûäô 	Ûð	üsw   ƒF¡	E ª.FÁ
F
Á$%E7Â	F
ÂA)FÃ7A$FÅE4Å0FÅ3E4Å4FÅ7FÆF
ÆFÆF
Æ
FÆFÆFÆFc               ó0   € V ^8„  d   QhRRRRRRRRR	R
RR/# )r   r¥   r   Ú	max_slotsz
int | NoneÚreserved_namesrH   Ú
desc_limitrA   Úsanitize_namezCallable[[str], str] | Noner   z+tuple[list[tuple[str, str, str, str]], int]r   )r   s   "r   r   r   é   sF   € ÷ .Rñ .RØð.RØ(ð.RØ:Bð.RØPSð.Rà.ð.Rð 1ñ.Rr   c                ól  a aaa€ T;'       g    R oR VVV3R llpV 3R lpV! V! 4       4      pSP                  R V 4       4       V! R \        S 4       4       4      pVf   Wx,           ^ 3# \        ^ V\        V4      ,
          4      p	\        ^ \        V4      V	,
          4      p
WxRV	 ,           RV V
3# )uE  Collect plugin + skill entries for a gateway platform.

Plugin slash commands come first and are never trimmed; skill commands (alphabetical) fill
the remaining *max_slots* (``None`` = every candidate, caller caps). *reserved_names* is
mutated in place as names are claimed; *sanitize_name* runs before clamping and may return
"" to skip. Returns ``(entries, hidden_count)``, entries ``(name, description, cmd_key,
raw_name)`` â€” ``cmd_key`` "" for plugins; ``raw_name`` is the sanitized pre-clamp name used
for configured-priority matching (both survive a clamp-induced rename).
c                ó   € V # r*   r   )r[   s   &r   r�   Ú0_collect_gateway_skill_entries.<locals>.<lambda>ö   s   € ©1r   c               ó   € V ^8„  d   QhRR/# )r   r   r†   r   )r   s   "r   r   Ú4_collect_gateway_skill_entries.<locals>.__annotate__ø   s   € ÷ 
9ñ 
9Ð9ñ 
9r   c                ó¼   <€ . p V  F6  w  r#pS! V4      ;p'       g   K  VP                  V\        VS4      WE34       K8  	  \        VS4      #   \         d     Li ; i)z¦Sanitize + truncate ``(raw_name, description, cmd_key)`` rows, then clamp against
``reserved_names``; any failure in the lazy source yields the rows collected so far.)rN   rD   rm   rU   )	ÚrowsÚoutr$   r;   rÁ   r8   rÉ   rÈ   Úsanitizes	   &     €€€r   Ú_entriesÚ0_collect_gateway_skill_entries.<locals>._entriesø   sm   ø€ ð 02ˆð	Û&*Ñ"�˜7Ù# C›=Ð(�4×(Ð(Ø—J‘J ¤n°T¸:Ó&FÈÐVÖWñ '+ô
 $ C¨Ó8Ð8øô ô 	Ùð	ús   …A Ÿ"A ÁAÁAc               3  ó&  <"  € ^ RI Hp  V ! 4       p\        V4       Fo  pW,          pSR8X  d6   \        \	        VP                  R4      ;'       g    R4      4      '       d   KG  Y#P                  R4      ;'       g    \        R4      R3x € Kq  	  R# 5i)é    )Úget_plugin_commandsrj   r   r(   Údescriptionz slash.shared.plugin_command_descN)Úhermes_cli.pluginsrØ   r    r!   r   ro   r   )rØ   Úplugin_cmdsÚcmd_nameÚmetar¥   s       €r   Ú_plugin_rowsÚ4_collect_gateway_skill_entries.<locals>._plugin_rows  sx   øé € Ý:Ù)Ó+ˆÜ˜{Ö+ˆHØÕ(ˆDØ˜:Ô%Ô*<¼SÀÇÁÈ+ÓAV×A\ÐA\ÐZ\Ó=]×*^Ò*^ÙØŸH™H ]Ó3×\Ð\´qÐ9[Ó7\Ð^`Ð`Ô`ó	 ,ùs   ƒABÁBÁ!BÁ;Bc              3  ó(   "  € T F  vrVx € K
  	  R # 5ir*   r   )r,   r[   Ú_rests   &  r   r.   Ú1_collect_gateway_skill_entries.<locals>.<genexpr>  s   é € Ð<©^ 	 �!«^ùs   ‚c              3  óp   "  € T F,  w  rpVP                  R 4      VP                  RR4      V3x € K.  	  R# 5i)Ú/rÙ   r(   N)Úlstripro   )r,   rÁ   rÂ   Ú_rels   &   r   r.   râ     s8   é € ð Cá#AÑˆG˜4ð 
�‰˜Ó	˜dŸh™h }°bÓ9¸7ÕCÛ#Aùs   ‚46N)ÚupdaterÅ   rs   rC   )r¥   rÇ   rÈ   rÉ   rÊ   rÔ   rÞ   Úplugin_entriesÚskill_entriesÚ	remainingÚhidden_countrÓ   s   f&ff&      @r   Ú_collect_gateway_skill_entriesrì   é   sÁ   û€ ð ×-Ð-¡€H÷
9ò 
9õañ ™l›nÓ-€NØ×ÑÑ<©^Ó<Ô<Ùñ Cä#7¸Ô#AóCó C€Mð ÒØÕ-¨qÐ0Ð0Ü�A�y¤3 ~Ó#6Õ6Ó7€IÜ�qœ#˜mÓ,¨yÕ8Ó9€LØ¨:¨IÐ6Õ6¸
¸ÐCÀ\ÐQÐQr   c               ó    € V ^8„  d   QhRRRR/# )r   rf   rA   r   z!tuple[list[tuple[str, str]], int]r   )r   s   "r   r   r     s   € ÷ /ñ /¨ð /Ð7Xñ /r   c                óø  € \        \        RR7      4      p\        RRV UUu0 uF  w  r#VkK	  	  upp^(\        R7      w  rEV UUu. uF
  w  rgWgRV3NK  	  pppTV UUU	U
u. uF  w  rgršYgV	'       d   RMRV
3NK  	  up
p	pp,          p\	        V4      p\        ^ \        V4      V ,
          4      pVRV   UUUUu. uF  w  rgrÍV\        V4      3NK  	  pppppWåV,           3# u uppi u uppi u up
p	ppi u uppppi )	u“  ``(menu_commands, hidden_count)`` for Telegram, capped to the Bot API limit. Tier order:
core CommandDefs, plugin slash commands, skill commands (alphabetical; hub and
telegram-disabled skills excluded). Tiers keep relative order unless named in
``platforms.telegram.extra.command_menu.priority`` â€” applied *before* the cap, so a
prioritized dynamic command can displace an unprioritized core command.F)rV   rj   N)r¥   rÇ   rÈ   rÉ   rÊ   rŽ   ÚskillÚplugin)r   r_   rì   r9   r£   rs   rC   r>   )rf   Úcore_commandsr[   r'   rF   rë   r8   r;   r…   rÁ   r$   Úoverflow_countÚ_sourceÚ	_raw_nameÚmenus   &              r   Útelegram_menu_commandsrö     s  € ô Ô.¸uÔEÓF€MÜ:Ø tÉ=Ô<YÉ=Á4À1»QÉ=Ò<YØÔ%<ô>Ñ€Gñ @MÔM¹}±°�4˜v tÓ,¹}€JÑMØÙ3:ö<Ù3:Ñ/�t 7ð ¯7¡¸À#ÓFÙ3:ô<õ <€Jä5°jÓA€JÜ˜œC 
›O¨lÕ:Ó;€NØYcÐdqÐeqÑYrÖsÑYrÑ7U°tÀ7ˆTÔ+¨DÓ1Ó2ÑYr€DÓsØ Õ.Ð.Ð.ùó =ZùãMùõ<ùõ ts   ¢C ÁC&Á C,Â8C4
c               ó    € V ^8„  d   QhRRRR/# )r   rÈ   rH   r   zMtuple[dict[str, list[tuple[str, str, str]]], list[tuple[str, str, str]], int]r   )r   s   "r   r   r   /  s   € ÷ <-ñ <-Øð<-àRñ<-r   c                óP  € / p. p\         P                  V R4      p^ p \        R4       Fæ  w  rVpVP                  R4      R,          pVP	                  V4      p	V	R8X  d   \
        P                  RW…V4       MV	e   \
        P                  RW•W‰4       V	e   V^,          pKx  WSV&   V\        VP	                  RR4      ^d4      V3p
\        V4      ^8¼  d+   VP                  V^ ,          . 4      P                  V
4       KÕ  VP                  V
4       Kè  	  WV3#   \         d     Li ; i)	u•  ``(categories, uncategorized, hidden_count)`` for Discord ``/skill`` autocomplete.

Skills nested >= 2 levels under a scan root (``creative/ascii-art/SKILL.md``) group under
``categories[top_level]``; root-level skills are *uncategorized*. Entries are
``(name, description, cmd_key)``, names clamped to 32 chars, descriptions to 100. No
per-group cap (the caller flattens into one autocomplete callback); ``hidden_count`` only
reports 32-char clamp collisions against reserved names or earlier skills.

Scan roots include the local ``SKILLS_DIR`` **and** any configured ``skills.external_dirs`` â€” matching
the widened filter applied to the flat ``discord_skill_commands()`` collector in #18741. Without this
parity, external-dir skills are visible via ``hermes skills list`` and the agent's ``/skill-name``
dispatch but silently absent from Discord's ``/skill`` autocomplete.
The legacy 25-group Ã— 25-subcommand caps (from the old nested ``/skill <cat> <name>`` layout) are
**not** applied â€” the live caller (``_register_skill_group`` in ``gateway/platforms/discord.py``,
refactored in PR #11580) flattens these results and feeds them into a single autocomplete callback,
which scales to thousands of entries without any per-command payload concerns. ``hidden_count`` is
retained in the return tuple for backward compatibility and still reports skills dropped for other
reasons (32-char clamp collision vs a reserved name).
z
<reserved>Údiscordrä   :Né    Nuæ   Discord /skill: %r (from %r) collides on its 32-char clamp with a reserved gateway command name %r â€” the skill will not appear in the /skill autocomplete. Rename the skill's frontmatter ``name:`` to differ in its first 32 chars.uÐ   Discord /skill: %r and %r both clamp to %r on Discord's 32-char command-name limit â€” only %r will appear in the /skill autocomplete. Rename one skill's frontmatter ``name:`` to differ in its first 32 chars.rÙ   r(   )ÚdictÚfromkeysrÅ   rå   ro   ÚloggerÚwarningrD   rC   Ú
setdefaultrN   rm   )rÈ   Ú
categoriesÚuncategorizedÚ
names_usedÚhiddenrÁ   rÂ   Ú	rel_partsÚdiscord_nameÚpriorÚentrys   &          r   Ú"discord_skill_commands_by_categoryr  /  s5  € ð, 9;€JØ02€Mô "&§¡¨~¸|Ó!L€JØ€FðÜ(<¸YÖ(GÑ$ˆG˜9à"Ÿ>™>¨#Ó.¨sÕ3ˆLØ—N‘N <Ó0ˆEØ˜Ô$Ü—‘ð-ð
 !¨<õ9ð Ò"Ü—‘ð*ð
  Lô9ð Ò Ø˜!•�ÙØ'.�|Ñ$Ø!¤>°$·(±(¸=È"Ó2MÈsÓ#SÐU\Ð]ˆEÜ�9‹~ Ô"Ø×%Ñ% i°¥l°BÓ7×>Ñ>¸uÖEà×$Ñ$ UÖ+ñ9 )Hð>  fÐ,Ð,øô ô Ùðús   žC5D ÄD%Ä$D%z[^a-z0-9_\-]c               ó    € V ^8„  d   QhRRRR/# r#   r   )r   s   "r   r   r   ‰  s   € ÷ Uñ U˜cð U cñ Ur   c                óv   € \         P                  RV P                  4       4      P                  R4      R\         # )zKLowercase, strip chars outside ``[a-z0-9_-]`` and edge ``-_``, clamp to 32.r(   z-_N)Ú_SLACK_INVALID_CHARSr3   r0   r   Ú_SLACK_NAME_LIMIT)r$   s   &r   Ú_sanitize_slack_namer  ‰  s/   € ä×#Ñ# B¨¯	©	«Ó4×:Ñ:¸4Ó@ÐASÔBSÐTÐTr   c               ó   € V ^8„  d   QhRR/# )r   r   zlist[tuple[str, str, str]]r   )r   s   "r   r   r   Ž  s   € ÷ ñ Ð8ñ r   c                 ó  € \        4       p V  Uu. uF3  qP                  VP                  4       VP                  ;'       g    R3NK5  	  ppTV  UUu. uFR  qP                   F@  pT\        RVP                  VP                  4       R7      VP                  ;'       g    R3NKB  	  KT  	  upp,          pT\        4        UUUu. uF  w  rEqdYV;'       g    R3NK  	  uppp,          pR\        R4      R3.pR0pV F}  w  rEp\        V4      p	V	'       d1   W˜9   g+   V	\        9   g    V	\        9   g   \        V4      \        8¼  d   KK  VP                  W•R,          VR,          34       VP                  V	4       K  	  V# u upi u uppi u upppi )	aZ  (slash_name, description, usage_hint) triples for Slack: every gateway-available command
(canonical names first so they win slots at the cap, then aliases, then plugins) becomes a
standalone slash, deduped and clamped to the 50-command cap; Slack built-ins and
_SLACK_VIA_HERMES_ONLY are skipped. ``/hermes`` is always first for anything dropped.r(   zslash.shared.slack_alias_for)r8   rÙ   Úhermeszslash.hermes.descriptionz[subcommand] [args]:NéŒ   N:Néd   N)r   r8   rY   r   Úaliasesr   r
   r  Ú_SLACK_RESERVED_COMMANDSÚ_SLACK_VIA_HERMES_ONLYrC   Ú_SLACK_MAX_SLASH_COMMANDSrN   rM   )
Ú	availabler   ÚwantedÚaliasr8   r;   r]   rF   ÚseenÚ
slack_names
             r   Úslack_native_slashesr  Ž  sk  € ô
 ,Ó-€IÙIRÓSÉÀ#�x‰x˜Ÿ™›¨¯©×)<Ð)<¸"Ó=É€FÐSØ
Ù09ôTÙ09¨Ç{Ä{¸eð ”qÐ7¸c¿h¹hÐTW×T`ÑT`ÓTbÔcØ—‘×#Ð# ó%ÙGRñ%Ù09òTõ T€Fà
Ô@\Ô@^Õ_Ñ@^Ñ,<¨D¸�dŸJ˜J BÓ'Ñ@^Ó_Õ_€Fð 
”1Ð/Ó0Ð2GÐHð+J€Gàˆ:€DÛ"Ñˆ�DÜ)¨$Ó/ˆ
ß˜jÔ0°JÔBZÔ4ZØÔ!7Ô7Ü�w“<Ô#<Ô<Ùà�‰˜
¨¥J°°Tµ
Ð;Ô<Ø�‰�Öñ #ð €Nùò# TùóTùä_s   �0E<Á E<ÁAFÂFÃF
c               ó    € V ^8„  d   QhRRRR/# )r   Úrequest_urlr   r   rc   r   )r   s   "r   r   r   ¨  s   € ÷ 5ñ 5Øð5ØGUñ5r   c           	     ó¸   € . p\        4        FE  w  r#pRRV 2RT;'       g    \        RVR7      RRRV /pV'       d   WER	&   VP                  V4       KG  	  R
RV//# )z¸``features.slash_commands`` manifest portion only (decoupled from the rest of the manifest
users configure in the Slack UI); ``request_url`` is schema-required, ignored in Socket Mode.Úcommandrä   rÙ   z slash.shared.plugin_default_desc)r8   Úshould_escapeFÚurlÚ
usage_hintÚfeaturesÚslash_commands)r  r   rN   )r  Úslashesr8   r;   Úusager  s   &     r   Úslack_app_manifestr(  ¨  su   € ð €GÜ1Ö3Ñˆ�EØ˜a ˜v˜J¨°t×7oÐ7o¼qÐAcÐjnÔ?oØ  %¨°ð=ˆçØ"'�,ÑØ�‰�uÖñ 4ð Ð)¨7Ð3Ð4Ð4r   c               ó   € V ^8„  d   QhRR/# )r   r   zdict[str, str]r   )r   s   "r   r   r   ¶  s   € ÷ ñ ˜nñ r   c                 óà   € \        4        U Uu/ uF(  q P                  .V P                  O F	  pVRV 2bK  	  K*  	  pp p\        4        F  w  rpVP	                  VRV 24       K  	  V# u upp i )zUname/alias -> "/command" for the Slack ``/hermes`` handler, plugin commands included.rä   )r   r8   r  r
   rÿ   )r   r8   ÚmappingÚ_descriptionÚ
_args_hints        r   Úslack_subcommand_mapr.  ¶  s…   € ô /Ô0ôWá0ˆC¿h¹hÐ=UÈÏÉÓ=U°Tð 	��$�ˆjÒÙ=Uñ 	Ù0ð ñ Wô +GÖ*HÑ&ˆ˜JØ×Ñ˜4 1 T F Ö,ñ +Ià€NùóWs   Ž.A*)rŒ   r�   )r�   rŒ   )rŒ   )ÚhelpÚnewÚstopÚstatusÚegressÚresumeÚsessionsÚmodelÚdebugÚrestartrç   ÚverboseÚcommandsÚapproveÚdenyÚqueueÚsteerÚbgÚbtwÚ	reasoningr'  ri   r¥   ÚprofileÚwhoami)r  N)r  >   ÚmeÚdndÚmsgÚproÚwhoÚawayÚfeedÚjoinÚmuteÚopenÚleaveÚshrugÚtopicÚexpandÚremindÚsearchr2  ÚcollapseÚ	shortcuts>   ÚmoaÚdiffÚinitr7  ÚloginÚpauseÚtopupr3  ÚrefineÚreviewrç   rC  ÚdiscardÚversionÚinsightsr¥   Ú	autopruneÚ	heartbeat)z)https://hermes-agent.local/slack/commands)8Ú__conditional_annotations__Ú__doc__Ú
__future__r   ÚloggingÚreÚcollections.abcr   r   r   Útypingr   Ú
agent.i18nr   Úhermes_cli.commandsr   r	   r
   r   Ú	getLoggerrý   rK   Úcompiler2   r6   r   r!   r9   r=   r>   rD   rU   r_   rp   ru   ra   Ú__annotations__rŸ   r{   r~   rƒ   r£   rÅ   rì   rö   r  r  r  r  Ú	frozensetr  r  r  r  r(  r.  )rc  s   @r   Ú<module>rp     s`  øðôõ #ã Û 	ß 7Ñ 7Ý å ÷bó bð 
×	Ò	Ð0Ó	1€à€à—J’J˜}Ó-Ð Ø—z’z (Ó+Ð õVõ-õ
	:ð �ZŠZÐ:Ó;€
õ%õDõ
ð:s°T÷ sð ')Ð #Ø!$Ð ð Ð(¨(Ð4MØˆð8 Ð Ð4ó  ðHÐ õõ4@õ
õYõ2,?÷^.R÷b/õ*<-ðH Ð ØÐ Ø—z’z /Ó2Ð Ù$ò &Ló MÐ ñ #ò $ó Ð õUõ
÷45÷r   