
    i=             	      L   U d Z ddlmZ ddlZddlZddlZddlZddlZddlm	Z	m
Z
 ddlmZ ddlmZ ddlmZ 	 ddlmZmZ dd	lmZmZ n# e$ r eZeZdZdZY nw xY w ed
           G d d                      Zg  edddd           edddd
           edddd
           edddd
           edddd
           eddd           eddd           ed d!dd"#           ed$d%dd&d"'           ed(d)dd*#           ed+d,dd-#           ed.d/dd
d0d12           ed3d4d           ed5d6dd
d78           ed9d:dd
;           ed<d=dd>d?'           ed@dAddB           edCdDddEd?'           edFdGdd?#           edHdIddJ#           edKdLd           edMdNdO           edPdQdd
dRS           edTdUdd"#           edVdWdXd
           edYdZdXd[d\'           ed]d^dOd
           ed_d`dXd"#           edadbdXd
dcd           ededfdXd
dgh           edidjdXdkdlm           edndodX           edpdqdXdrdsm           edtdudXdvdwm           edxdydXd
d"z           ed{d|dXd
d}d~           edddXddm           edddXd
dd           eddddd
           edddd
           edddd
d           edddd
dd           edddddm           edddddm           edddd
           edddd           edddd           edddd
dd           edddd
           edddOd
d8           edddO           edddd
;           edddO           edddOd#           edddOd
dd           edddOd
d-z           edddOd
           edddOd
dz           edddOd
;           edddO           edddd
dȬd          Zded<   d d̈́Z e            Zded<   d!d҄Zd"dԄZi Z ded<   eD ]AZ!e!j"        s8 ee!          e de!j#         <   e!j$        D ]Z%e!j&         de!j#         dٝe de% <   Bi Z'ded<   eD ]ZZ!e!j"        sQe'(                    e!j)        i           Z*e de!j#                  e*de!j#         <   e!j$        D ]Z%e de%          e*de% <   [i Z+ded<   eD ]$Z!e!j,        r e-e!j,                  e+de!j#         <   % ej.        dަ          Z/eD ]_Z!de!j#         Z0e0e+v se!j1        se/2                    e!j1                  Z3e3r+e34                    d          5                    dߦ          e+e0<   ` e6d eD                       Z7ded<   d#dZ8 e6h d          Z9ded<   d$dZ:d%dZ;d&d'dZ<d(dZ=d)dZ>d*dZ?dZ@	 e@ZA ej.        d          ZB ej.        d          ZCd+dZDd,dZEeEZF	 	 d-d.dZGd/d0d	ZHd1d
ZId2dZJdZKdZL ej.        d          ZM e6h d          ZNd+dZOd)dZPd3d4dZQd5dZRdaSded<   d(dZT G d de          ZU G d de          ZVd6dZWdS (7  a  Slash command definitions and autocomplete for the Hermes CLI.

Central registry for all slash commands. Every consumer -- CLI help, gateway
dispatch, Telegram BotCommands, Slack subcommand mapping, autocomplete --
derives its data from ``COMMAND_REGISTRY``.

To add a command: add a ``CommandDef`` entry to ``COMMAND_REGISTRY``.
To add an alias: set ``aliases=("short",)`` on the existing ``CommandDef``.
    )annotationsN)CallableMapping)	dataclass)Any)is_truthy_value)AutoSuggest
Suggestion)	Completer
CompletionT)frozenc                      e Zd ZU dZded<   ded<   ded<   dZded<   d	Zded
<   dZded<   dZded<   dZ	ded<   dZ
ded<   dS )
CommandDefz%Definition of a single slash command.strnamedescriptioncategory ztuple[str, ...]aliases 	args_hintsubcommandsFboolcli_onlygateway_onlyN
str | Nonegateway_config_gate)__name__
__module____qualname____doc____annotations__r   r   r   r   r   r   r       :/home/longshao/.hermes/hermes-agent/hermes_cli/commands.pyr   r   *   s         //IIIMMM!G!!!!I#%K%%%%HL&*******r#   r   newz0Start a new session (fresh session ID + history)Session)reset)r   clearz$Clear screen and start a new session)r   redrawz6Force a full UI repaint (recovers from terminal drift)historyzShow conversation historysavezSave the current conversationretryz(Retry the last message (resend to agent)undoz'Remove the last user/assistant exchangetitlez#Set a title for the current sessionz[name])r   branchz5Branch the current session (explore a different path))fork)r   r   compressz&Manually compress conversation contextz[focus topic]rollbackz&List or restore filesystem checkpointsz[number]snapshotz8Create or restore state snapshots of Hermes config/state)snapz[create|restore <id>|prune])r   r   r   stopz%Kill all running background processesapprovez#Approve a pending dangerous commandz[session|always])r   r   denyz Deny a pending dangerous command)r   
backgroundzRun a prompt in the background)bgbtwz<prompt>agentsz$Show active agents and running tasks)tasksqueuez4Queue a prompt for the next turn (doesn't interrupt))qsteerz>Inject a message after the next tool call without interruptinggoalz?Set a standing goal Hermes works on across turns until achievedz([text | pause | resume | clear | status]statuszShow session infoprofilez+Show active profile name and home directoryInfosethomez!Set this chat as the home channel)zset-home)r   r   resumez!Resume a previously-named sessionconfigzShow current configurationConfigurationmodelzSwitch model for this session)providerz$[model] [--provider name] [--global]gquotaz*Show Google Gemini Code Assist quota usagepersonalityzSet a predefined personality	statusbarz#Toggle the context/model status bar)sb)r   r   verbosez9Cycle tool progress display: off -> new -> all -> verbosezdisplay.tool_progress_command)r   r   footerz7Toggle gateway runtime-metadata footer on final repliesz[on|off|status])onoffrA   )r   r   yoloz7Toggle YOLO mode (skip all dangerous command approvals)	reasoningz#Manage reasoning effort and displayz[level|show|hide])
noneminimallowmediumhighxhighshowhiderP   rQ   fastuS   Toggle fast mode — OpenAI Priority Processing / Anthropic Fast Mode (Normal/Fast)z[normal|fast|status])normalr\   rA   rP   rQ   skinz%Show or change the display skin/theme)r   r   	indicatorz!Pick the TUI busy-indicator stylez[kaomoji|emoji|unicode|ascii])kaomojiemojiunicodeascii)r   r   r   voicezToggle voice modez[on|off|tts|status])rP   rQ   ttsrA   busyz/Control what Enter does while Hermes is workingz[queue|steer|interrupt|status])r=   r?   	interruptrA   toolsz4Manage tools: /tools [list|disable|enable] [name...]zTools & Skillsz[list|disable|enable] [name...])r   r   toolsetszList available toolsetsskillsz*Search, install, inspect, or manage skills)searchbrowseinspectinstall)r   r   cronzManage scheduled tasksz[subcommand])listaddcreateeditpauserE   runremovecuratorz8Background skill maintenance (status, run, pin, archive))rA   ru   rt   rE   pinunpinrestorekanbanz:Multi-profile collaboration board (tasks, links, comments))rp   lsrZ   rr   assignlinkunlinkclaimcommentcompleteblockunblockarchivetaildispatchcontextinitgcreloadz.Reload .env variables into the running sessionz
reload-mcpzReload MCP servers from config)
reload_mcpzreload-skillsz?Re-scan ~/.hermes/skills/ for newly installed or removed skills)reload_skillsbrowserz1Connect browser tools to your live Chrome via CDPz[connect|disconnect|status])connect
disconnectrA   pluginsz'List installed plugins and their statuscommandsz*Browse all commands and skills (paginated)z[page]helpzShow available commandsrestartz9Gracefully restart the gateway after draining active runsusagez8Show token usage and rate limits for the current sessioninsightsz!Show usage insights and analyticsz[days]	platformsz&Show gateway/messaging platform status)gatewaycopyz-Copy the last assistant response to clipboardpastez*Attach clipboard image from your clipboardimagez.Attach a local image file for your next promptz<path>updatez)Update Hermes Agent to the latest versiondebugz@Upload debug report (system info + logs) and get shareable linksquitzExit the CLIExit)exitzlist[CommandDef]COMMAND_REGISTRYreturndict[str, CommandDef]c                 P    i } t           D ]}|| |j        <   |j        D ]}|| |<   | S )z+Map every name and alias to its CommandDef.)r   r   r   )lookupcmdaliass      r$   _build_command_lookupr      sH    $&F    sx[ 	  	 EF5MM	 Mr#   _COMMAND_LOOKUPr   r   CommandDef | Nonec                    t                               |                                                     d                    S )zmResolve a command name or alias to its CommandDef.

    Accepts names with or without the leading slash.
    /)r   getlowerlstrip)r   s    r$   resolve_commandr      s.    
 tzz||22377888r#   r   c                R    | j         r| j         d| j         d| j          dS | j        S )z;Build a CLI-facing description string including usage hint.z
 (usage: / ))r   r   r   )r   s    r$   _build_descriptionr      s:    
} I/HHSXHHHHHH?r#   dict[str, str]COMMANDSr   z (alias for /r   zdict[str, dict[str, str]]COMMANDS_BY_CATEGORYzdict[str, list[str]]SUBCOMMANDSz[a-z]+(?:\|[a-z]+)+|c              #  \   K   | ]'}|j         r|j        |j        g|j        R D ]}|V  (d S N)r   r   r   r   ).0r   r   s      r$   	<genexpr>r     su       3 3<3 23 (CK((	3 3 	 	3 3 3 3 3 3 3r#   zfrozenset[str]GATEWAY_KNOWN_COMMANDSr   r   c                `    | sdS | t           v rdS t                      D ]\  }}}|| k    r dS dS )u  Return True if ``name`` resolves to a gateway-dispatchable slash command.

    This covers both built-in commands (``GATEWAY_KNOWN_COMMANDS`` derived
    from ``COMMAND_REGISTRY``) and plugin-registered commands, which are
    looked up lazily so importing this module never forces plugin
    discovery. Gateway code uses this to decide whether to emit
    ``command:<name>`` hooks — plugin commands get the same lifecycle
    events as built-ins.
    FT)r   _iter_plugin_command_entries)r   plugin_name_description
_args_hints       r$   is_gateway_known_commandr     sZ      u%%%t1M1O1O  -\:$44 5r#   >   r%   r7   r   r5   r=   r?   r;   rA   r   r6   rB   r   r   r8   ACTIVE_SESSION_BYPASS_COMMANDScommand_namec                ,    | rt          |           dundS )u  Return True for any resolvable slash command.

    Rationale: every gateway-registered slash command either has a
    specific Level-2 handler in gateway/run.py (/stop, /new, /model,
    /approve, etc.) or reaches the running-agent catch-all that returns
    a "busy — wait or /stop first" response. In both paths the command
    is dispatched, not queued.

    Queueing is always wrong for a recognized slash command because the
    safety net in gateway.run discards any command text that reaches
    the pending queue — which meant a mid-run /model (or /reasoning,
    /voice, /insights, /title, /resume, /retry, /undo, /compress,
    /usage, /reload-mcp, /sethome, /reset) would silently
    interrupt the agent AND get discarded, producing a zero-char
    response. See issue #5057 / PRs #6252, #10370, #4665.

    ACTIVE_SESSION_BYPASS_COMMANDS remains the subset of commands with
    explicit Level-2 handlers; the rest fall through to the catch-all.
    NF)r   )r   s    r$   should_bypass_active_sessionr   K  s"    ( 9EO?<((44%Or#   set[str]c                    d t           D             } | st                      S 	 ddlm}  |            }n# t          $ r t                      cY S w xY wt                      }| D ]y}|}|j                            d          D ]/}t          |t                    r|	                    |          }-d} t          |d          r|                    |j                   z|S )zReturn canonical names of commands whose ``gateway_config_gate`` is truthy.

    Reads ``config.yaml`` and walks the dot-separated key path for each
    config-gated command.  Returns an empty set on any error so callers
    degrade gracefully.
    c                     g | ]}|j         	|S r   )r   )r   cs     r$   
<listcomp>z)_resolve_config_gates.<locals>.<listcomp>i  s     BBB1A,ABQBBBr#   r   )read_raw_config.NF)default)r   sethermes_cli.configr   	Exceptionr   split
isinstancedictr   r   rq   r   )gatedr   cfgresultr   valkeys          r$   _resolve_config_gatesr   b  s    CB(BBBE uu555555o   uuuuF 	! 	!*0055 	 	C#t$$ ggcll3... 	!JJsx   Ms   4 AAconfig_overridesset[str] | Nonec                \    | j         sdS | j        r||nt                      }| j        |v S dS )a}  Check if *cmd* should appear in gateway surfaces (help, menus, mappings).

    Unconditionally available when ``cli_only`` is False.  When ``cli_only``
    is True but ``gateway_config_gate`` is set, the command is available only
    when the config value is truthy.  Pass *config_overrides* (from
    ``_resolve_config_gates()``) to avoid re-reading config for every command.
    TNF)r   r   r   r   )r   r   	overridess      r$   _is_gateway_availabler     sG     < t
 %(8(D$$J_JaJa	x9$$5r#   	list[str]c            	        t                      } g }t          D ]}t          ||           s|j        r
d|j         nd}g }|j        D ]Z}|                    dd          |j                            dd          k    r||j        k    rA|                    d| d           [|rdd                    |           d	nd}|                    d|j         | d
|j	         |            |S )z3Generate gateway help text lines from the registry.r   r   -_z`/`z	 (alias: z, r   z` -- )
r   r   r   r   r   replacer   appendjoinr   )r   linesr   argsalias_partsa
alias_notes          r$   gateway_help_linesr     s!   %''IE N N$S)44 	&)m;"3="""!# 	* 	*Ayyc""ch&6&6sC&@&@@@Q#(]]yAyyy))))>IQ:;!7!7::::r
L#(LDLLsL
LLMMMMLr#   list[tuple[str, str, str]]c                    	 ddl m}  n# t          $ r g cY S w xY w	  |             pi }n# t          $ r g cY S w xY wg }|                                D ]\  }}t	          |t
                    rt	          |t                    s0t          |                    d          pd|           }t          |                    d          pd                                          }|	                    |||f           |S )ae  Yield (name, description, args_hint) tuples for all plugin slash commands.

    Plugin commands are registered via
    :func:`hermes_cli.plugins.PluginContext.register_command`. They behave
    like ``CommandDef`` entries for gateway surfacing: they appear in the
    Telegram command menu, in Slack's ``/hermes`` subcommand mapping, and
    (via :func:`gateway.platforms.discord._register_slash_commands`) in
    Discord's native slash command picker.

    Lookup is lazy so importing this module never forces plugin discovery
    (which can trigger filesystem scans and environment-dependent
    behavior).
    r   get_plugin_commandsr   Run /r   r   )
hermes_cli.pluginsr   r   itemsr   r   r   r   stripr   )r   r   entriesr   metar   r   s          r$   r   r     s5   :::::::   			&&((.B   			*,Gnn&& 7 7
d$$$ 	JtT,B,B 	$((=11C^T^^DD--344::<<	k956666Ns   	 ) 88list[tuple[str, str]]c                 :   t                      } g }t          D ]E}t          ||           st          |j                  }|r|                    ||j        f           Ft                      D ].\  }}}t          |          }|r|                    ||f           /|S )a{  Return (command_name, description) pairs for Telegram setMyCommands.

    Telegram command names cannot contain hyphens, so they are replaced with
    underscores.  Aliases are skipped -- Telegram shows one menu entry per
    canonical command.

    Plugin-registered slash commands are included so plugins get native
    autocomplete in Telegram without touching core code.
    )r   r   r   _sanitize_telegram_namer   r   r   r   )r   r   r   tg_namer   r   r   s          r$   telegram_bot_commandsr     s     &''I$&F 6 6$S)44 	)#(33 	6MM7CO4555)E)G)G 2 2%k:)$// 	2MM7K0111Mr#       z
[^a-z0-9_]z_{2,}rawc                    |                                                      dd          }t                              d|          }t                              d|          }|                    d          S )uR  Convert a command/skill/plugin name to a valid Telegram command name.

    Telegram requires: 1-32 chars, lowercase a-z, digits 0-9, underscores only.
    Steps: lowercase → replace hyphens with underscores → strip all other
    invalid characters → collapse consecutive underscores → strip leading/
    trailing underscores.
    r   r   r   )r   r   _TG_INVALID_CHARSsub_TG_MULTI_UNDERSCOREr   r   r   s     r$   r   r     s[     99;;sC((D  T**D##C..D::c??r#   r   reservedc                V   t          |          }g }| D ]\  }}t          |          t          k    rF|dt                   }||v r1|dt          dz
           }t          d          D ]}| | }||vr na|}||v rh|                    |           |                    ||f           |S )a  Enforce 32-char command name limit with collision avoidance.

    Both Telegram and Discord cap slash command names at 32 characters.
    Names exceeding the limit are truncated.  If truncation creates a duplicate
    (against *reserved* names or earlier entries in the same batch), the name is
    shortened to 31 chars and a digit ``0``-``9`` is appended to differentiate.
    If all 10 digit slots are taken the entry is silently dropped.
    N   
   )r   len_CMD_NAME_LIMITrangerq   r   )	r   r  usedr   r   desc	candidateprefixdigits	            r$   _clamp_command_namesr    s     ]]D$&F $ $
dt99&&-o-.ID  2223"2YY  E#) 25 2 2I ,, - D4<<tTl####Mr#   d   platform	max_slotsintreserved_names
desc_limitsanitize_name'Callable[[str], str] | None'&tuple[list[tuple[str, str, str]], int]c           	     d   g }g }	 ddl m}  |            }t          |          D ]j}	|r ||	          n|	}
|
s||	                             dd          }t	          |          |k    r|d|dz
           dz   }|                    |
|f           kn# t          $ r Y nw xY wt          ||          }|                    d |D                        |D ]\  }}|                    ||d	f           t                      }	 dd
l
m}  ||           }n# t          $ r Y nw xY wg }	 ddlm} ddlm} t!          |                                          }t!          |dz                                            } |            }t          |          D ]}||         }|                    dd	          }|                    |          s6|                    |          rL|                    dd	          }||v rg|                    d          }|r ||          n|}
|
s|                    dd	          }t	          |          |k    r|d|dz
           dz   }|                    |
||f           n# t          $ r Y nw xY wd |D             }d |D             }t          ||          }t)          d|t	          |          z
            }t)          dt	          |          |z
            }|d|         D ]3\  }}|                    |||                    ||fd	          f           4|d|         |fS )a  Collect plugin + skill entries for a gateway platform.

    Priority order:
      1. Plugin slash commands (take precedence over skills)
      2. Built-in skill commands (fill remaining slots, alphabetical)

    Only skills are trimmed when the cap is reached.
    Hub-installed skills are excluded.  Per-platform disabled skills are
    excluded.

    Args:
        platform: Platform identifier for per-platform skill filtering
            (``"telegram"``, ``"discord"``, etc.).
        max_slots: Maximum number of entries to return (remaining slots after
            built-in/core commands).
        reserved_names: Names already taken by built-in commands.  Mutated
            in-place as new names are added.
        desc_limit: Max description length (40 for Telegram, 100 for Discord).
        sanitize_name: Optional name transform applied before clamping, e.g.
            :func:`_sanitize_telegram_name` for Telegram.  May return an
            empty string to signal "skip this entry".

    Returns:
        ``(entries, hidden_count)`` where *entries* is a list of
        ``(name, description, cmd_key)`` triples and *hidden_count* is the
        number of skill entries dropped due to the cap.  ``cmd_key`` is the
        original ``/skill-name`` key from :func:`get_skill_commands`.
    r   r   r   Plugin commandN   ...c              3      K   | ]	\  }}|V  
d S r   r   r   nr   s      r$   r   z1_collect_gateway_skill_entries.<locals>.<genexpr>U  s&      551!555555r#   r   get_disabled_skill_namesr  get_skill_commands
SKILLS_DIR.hubskill_md_pathr   r   c                    g | ]
\  }}}||fS r   r   )r   r"  dr   s       r$   r   z2_collect_gateway_skill_entries.<locals>.<listcomp>  s"    777gaAAq6777r#   c                     i | ]\  }}}||f|S r   r   )r   r"  r-  ks       r$   
<dictcomp>z2_collect_gateway_skill_entries.<locals>.<dictcomp>  s$    :::AqAq61:::r#   )r   r   sortedr   r
  r   r   r  r   r   agent.skill_utilsr$  agent.skill_commandsr'  tools.skills_toolr)  r   resolve
startswithr   max)r  r  r  r  r  all_entriesplugin_pairsr   plugin_cmdscmd_namer   r  r"  r-  _platform_disabledr$  skill_triplesr'  r)  _skills_dir_hub_dir
skill_cmdscmd_keyinfo
skill_path
skill_nameraw_nameskill_pairskey_by_pair	remaininghidden_counts                                  r$   _collect_gateway_skill_entriesrJ    s9   F /1K +-L::::::))++{++ 	. 	.H.;I==***D x(,,]<LMMD4yy:%%OZ!^O,u4t----	.     (nEEL55555555 ' '1Aq":&&&& $'55>>>>>>55xHHH    13M;;;;;;000000*,,..//
V+446677''))
j)) 	8 	8Gg&D/266J((55 $$X.. &"--J///~~c**H.;I==***D 88M2..D4yy:%%OZ!^O,u4  $g!67777#	8$    
 87777K::M:::K&{NCCK Ay3{#3#3344Iq#k**Y677LJYJ' @ @1Aq+//1a&""="=>????z	z"L00s7   B
B 
BB?D 
DD%E
I0 0
I=<I=max_commands!tuple[list[tuple[str, str]], int]c                <   t          t                                }d |D             }t          |          }t          d| t          |          z
            }t	          d||dt
                    \  }}|                    d |D                        |d|          |fS )u  Return Telegram menu commands capped to the Bot API limit.

    Priority order (higher priority = never bumped by overflow):
      1. Core CommandDef commands (always included)
      2. Plugin slash commands (take precedence over skills)
      3. Built-in skill commands (fill remaining slots, alphabetical)

    Skills are the only tier that gets trimmed when the cap is hit.
    User-installed hub skills are excluded — accessible via /skills.
    Skills disabled for the ``"telegram"`` platform (via ``hermes skills
    config``) are excluded from the menu entirely.

    Returns:
        (menu_commands, hidden_count) where hidden_count is the number of
        skill commands omitted due to the cap.
    c                    h | ]\  }}|S r   r   r!  s      r$   	<setcomp>z)telegram_menu_commands.<locals>.<setcomp>  s    222DAqa222r#   r   telegram(   )r  r  r  r  r  c              3  &   K   | ]\  }}}||fV  d S r   r   )r   r"  r-  _ks       r$   r   z)telegram_menu_commands.<locals>.<genexpr>  s,      7781aA777777r#   N)rp   r   r7  r
  rJ  r   extend)rK  core_commandsr  all_commandsremaining_slotsr   rI  s          r$   telegram_menu_commandsrX    s    " .0011M22M222N&&L!\C,=,==>>O:!%-  G\ 77w777777&44r#   c                B    t          d| t          |          d          S )u  Return skill entries for Discord slash command registration.

    Same priority and filtering logic as :func:`telegram_menu_commands`
    (plugins > skills, hub excluded, per-platform disabled excluded), but
    adapted for Discord's constraints:

    - Hyphens are allowed in names (no ``-`` → ``_`` sanitization)
    - Descriptions capped at 100 chars (Discord's per-field max)

    Args:
        max_slots: Available command slots (100 minus existing built-in count).
        reserved_names: Names of already-registered built-in commands.

    Returns:
        ``(entries, hidden_count)`` where *entries* is a list of
        ``(discord_name, description, cmd_key)`` triples.  ``cmd_key`` is
        the original ``/skill-name`` key needed for the slash handler callback.
    discordr  )r  r  r  r  )rJ  r   )r  r  s     r$   discord_skill_commandsr[    s/    , *>**	   r#   Mtuple[dict[str, list[tuple[str, str, str]]], list[tuple[str, str, str]], int]c           	     T   ddl m} t                      }	 ddlm}  |d          }n# t
          $ r Y nw xY wi }g }t          |           }d}	 ddlm} ddlm	}	 |	
                                }
|	dz  
                                } |            }t          |          D ]}||         }|                    d	d
          }|s$ ||          
                                }t          |                              t          |
                    sqt          |                              t          |                    r|                    dd
          }||v r|                    d          }|dd         }||v r|                    |           |                    dd
          }t#          |          dk    r|dd         dz   }	 |j                            |
          }n# t(          $ r Y Tw xY w|j        }t#          |          dk    r6|d         }|                    |g                               |||f           |                    |||f           n# t
          $ r Y nw xY wd}d}i }d}t          |          D ]d}||k    r|t#          ||                   z  }!||         d|         }|t1          dt#          ||                   |z
            z  }|||<   |dz  }e||z
  }t#          |          |k    r|t#          |          |z
  z  }|d|         }|||fS )u  Return skill entries organized by category for Discord ``/skill`` subcommand groups.

    Skills whose directory is nested at least 2 levels under ``SKILLS_DIR``
    (e.g. ``creative/ascii-art/SKILL.md``) are grouped by their top-level
    category.  Root-level skills (e.g. ``dogfood/SKILL.md``) are returned as
    *uncategorized* — the caller should register them as direct subcommands
    of the ``/skill`` group.

    The same filtering as :func:`discord_skill_commands` is applied: hub
    skills excluded, per-platform disabled excluded, names clamped.

    Returns:
        ``(categories, uncategorized, hidden_count)``

        - *categories*: ``{category_name: [(name, description, cmd_key), ...]}``
        - *uncategorized*: ``[(name, description, cmd_key), ...]``
        - *hidden_count*: skills dropped due to Discord group limits
          (25 subcommand groups, 25 subcommands per group)
    r   )Pathr#  rZ  r%  r&  r(  r*  r+  r   r   r   Nr   r   r  a   r        r  )pathlibr^  r   r2  r$  r   r3  r'  r4  r)  r5  r1  r   r   r6  r   rq   r
  parentrelative_to
ValueErrorparts
setdefaultr   r7  )r  _Pr<  r$  
categoriesuncategorized_names_usedhiddenr'  r)  r>  r?  r@  rA  rB  rC  sprD  rE  discord_namer  relrf  cat_MAX_GROUPS_MAX_PER_GROUPtrimmed_categoriesgroup_countr   rW  s                                 r$   "discord_skill_commands_by_categoryru    s   , #"""""#&55>>>>>>55yIII    9;J02M//KF/;;;;;;000000 ((**'0022''))
j)) &	D &	DGg&D/266J J''))Br77%%c+&6&677 2ww!!#h--00 &"--J///~~c**H#CRC=L{**OOL)))88M2..D4yy3CRCy5(i++K88   IE5zzQAh%%c2..55|T76STTTT$$lD'%BCCCCM&	DN     KN@BKj!!  +%%c*S/***FS//>/2#aZ_-->???")3q "K/O
=O++#m$$66%&6&67}f44sD   ) 
66E;I" G&%I" &
G40I" 3G44A-I" "
I/.I/2   z[^a-z0-9_\-]>   medndmsgprowhoawayfeedr   muteopenleaveshrugtopicexpandremindrk   rA   collapse	shortcutsc                    |                                  }t                              d|          }|                    d          }|dt                   S )zConvert a command name to a valid Slack slash command name.

    Slack allows lowercase a-z, digits, hyphens, and underscores. Max 32
    chars. Uppercase is lowercased; invalid chars are stripped.
    r   z-_N)r   _SLACK_INVALID_CHARSr  r   _SLACK_NAME_LIMITr  s     r$   _sanitize_slack_namer  R  sI     99;;D##B--D::dD"""##r#   c            	        t                      } g t                                          d                               d           dfd	}t          D ]1}t          ||           s ||j        |j        |j        pd
           2t          D ]A}t          ||           s|j	        D ]&} ||d|j         d|j         |j        pd
           'Bt                      D ]\  }}} ||||pd
           S )a  Return (slash_name, description, usage_hint) triples for Slack.

    Every gateway-available command in ``COMMAND_REGISTRY`` is surfaced as
    a standalone Slack slash command (e.g. ``/btw``, ``/stop``, ``/model``),
    matching Discord's and Telegram's model where every command is a
    first-class slash and not a ``/hermes <verb>`` subcommand.

    Both canonical names and aliases are included so users can type any
    documented form (e.g. ``/background``, ``/bg``, and ``/btw`` all work).
    Plugin-registered slash commands are included too.

    Commands whose sanitized name collides with a Slack built-in
    (e.g. ``/status``, ``/me``, ``/join``) are silently skipped.  Users
    can still reach them via ``/hermes <command>``.

    Results are clamped to Slack's 50-command limit with duplicate-name
    avoidance. ``/hermes`` is always reserved as the first entry so the
    legacy ``/hermes <subcommand>`` form keeps working for anything that
    gets dropped by the clamp or for free-form questions.
    )hermesz"Talk to Hermes or run a subcommandz[subcommand] [args]r  r   r   r  hintr   Nonec                    t          |           }|r|v rd S |t          v rd S t                    t          k    rd S                     ||d d         |d d         f                               |           d S )N   r  )r  _SLACK_RESERVED_COMMANDSr
  _SLACK_MAX_SLASH_COMMANDSr   rq   )r   r  r  
slack_namer   seens       r$   _addz"slack_native_slashes.<locals>._add{  s    )$//
 	Z4//F111Fw<<444F
D#JTcT
;<<<r#   r   zAlias for /u    — )r   r   r  r   r  r   r   r  )r   r   r   rq   r   r   r   r   r   r   r   )	r   r  r   r   r   r   r   r   r  s	          @@r$   slack_native_slashesr  ^  sg   * &''I*,GUUD NNZ[[[HHX
 
 
 
 
 
 
   = =$S)44 	SXs(;<<<<   ] ]$S)44 	[ 	] 	]E DFchFFS_FFH[Y[\\\\	] )E(F(F 1 1$k9T;	R0000Nr#   )https://hermes-agent.local/slack/commandsrequest_urldict[str, Any]c                    g }t                      D ]1\  }}}d| |pd| d| d}|r||d<   |                    |           2dd|iiS )u  Generate a Slack app manifest with all gateway commands as slashes.

    ``request_url`` is required by Slack's manifest schema for every slash
    command, but in Socket Mode (which we use) Slack ignores it and routes
    the command event through the WebSocket. A placeholder URL is fine.

    The returned dict is the ``features.slash_commands`` portion only —
    callers compose it into a full manifest (or merge into an existing
    one). Keeping it narrow avoids coupling us to the rest of the manifest
    schema (display_information, oauth_config, settings, etc.) which users
    set up once in the Slack UI and rarely change.
    r   r   F)commandr   should_escapeurl
usage_hintfeaturesslash_commands)r  r   )r  slashesr   r  r   entrys         r$   slack_app_manifestr    s     G133 	 	dE!4zz1>4>>"	
 
  	("'E,u)7344r#   c                     t                      } i }t          D ]7}t          ||           sd|j         ||j        <   |j        D ]
}d| ||<   8t                      D ]\  }}}||vrd| ||<   |S )a0  Return subcommand -> /command mapping for Slack /hermes handler.

    Maps both canonical names and aliases so /hermes bg do stuff works
    the same as /hermes background do stuff.

    Plugin-registered slash commands are included so ``/hermes <plugin-cmd>``
    routes through the plugin handler.
    r   )r   r   r   r   r   r   )r   mappingr   r   r   r   r   s          r$   slack_subcommand_mapr    s     &''I G ) )$S)44 	*NN[ 	) 	)E([[GENN	)*F*H*H ' '&lJw&JJGDMNr#   ztuple[float, list[str]] | None_LMSTUDIO_COMPLETION_CACHEc                 ~   t           j                            d          syt           j                            d          sZ	 ddlm}   |             pi }d|                    d          pi vrd|                    d          pi vrg S n# t
          $ r g cY S w xY wt          j                    }t          r!|t          d         z
  dk     rt          d	         S 	 dd
lm	}  |t           j                            dd          t           j                            d          pdd          }n# t
          $ r g }Y nw xY w||fa|S )zHLocally-loaded LM Studio models for /model autocomplete (cached, gated).
LM_API_KEYLM_BASE_URLr   )_load_auth_storelmstudio	providerscredential_poolg      >@r  )fetch_lmstudio_modelsr   zhttp://127.0.0.1:1234/v1g?)api_keybase_urltimeout)
osenvironr   hermes_cli.authr  r   timer  hermes_cli.modelsr  )r  storenowr  modelss        r$   _lmstudio_completion_modelsr    s    JNN<(( BJNN=,I,I 	888888$$&&,"E%))K"8"8">B??eii0A&B&B&HbII	 	 	 	III	
)++C! -s-G-J'Jd&R&R)!,,;;;;;;&&JNN<44Z^^M22P6P
 
 

    "%vMs&    AB BBAD' 'D65D6c                     e Zd ZdZ	 	 d)d*d	Zd+dZd,dZed-d            Zed.d            Z	ed/d0d            Z
ed.d            Zd/d0dZd1dZed2d             Zd3d4d"Zed5d%            Zed5d&            Zd5d'Zd( ZdS )6SlashCommandCompleterzJAutocomplete for built-in slash commands, subcommands, and skill commands.Nskill_commands_provider1Callable[[], Mapping[str, dict[str, Any]]] | Nonecommand_filterCallable[[str], bool] | Noner   r  c                L    || _         || _        g | _        d| _        d| _        d S )Ng        r   )_skill_commands_provider_command_filter_file_cache_file_cache_time_file_cache_cwd)selfr  r  s      r$   __init__zSlashCommandCompleter.__init__  s3    
 )@%-&('*$&r#   slash_commandr   r   c                |    | j         dS 	 t          |                      |                    S # t          $ r Y dS w xY w)NT)r  r   r   )r  r  s     r$   _command_allowedz&SlashCommandCompleter._command_allowed  sS    '4	,,];;<<< 	 	 	44	s   !- 
;;Mapping[str, dict[str, Any]]c                f    | j         i S 	 |                                  pi S # t          $ r i cY S w xY wr   )r  r   )r  s    r$   _iter_skill_commandsz*SlashCommandCompleter._iter_skill_commands  sP    (0I	00228b8 	 	 	III	s   ! 00r;  wordc                    | |k    r|  dn| S )aI  Return replacement text for a completion.

        When the user has already typed the full command exactly (``/help``),
        returning ``help`` would be a no-op and prompt_toolkit suppresses the
        menu. Appending a trailing space keeps the dropdown visible and makes
        backspacing retrigger it naturally.
        r   r   )r;  r  s     r$   _completion_textz&SlashCommandCompleter._completion_text  s     "*T!1!1(~~~~x?r#   textr   c                    | sdS t          |           dz
  }|dk    r#| |         dk    r|dz  }|dk    r| |         dk    | |dz   d         }|sdS |                    d          sd|v r|S dS )aC  Extract the current word if it looks like a file path.

        Returns the path-like token under the cursor, or None if the
        current word doesn't look like a path.  A word is path-like when
        it starts with ``./``, ``../``, ``~/``, ``/``, or contains a
        ``/`` separator (e.g. ``src/main.py``).
        Nr  r   r   )z./z../~/r   r   r
  r6  r  ir  s      r$   _extract_path_wordz(SlashCommandCompleter._extract_path_word!  s      	4 IIM1ffaCFA 1ffaCAEFF| 	4??344 	tKtr#      limitr  c              #  F  K   t           j                            |           }|                    d          r|}d}n@t           j                            |          pd}t           j                            |          }	 t          j        |          }n# t          $ r Y dS w xY wd}|                                }t          |          D ]W}|r(|                                
                    |          s-||k    r dS t           j                            ||          }	t           j                            |	          }
| 
                    d          rAdt           j                            |	t           j                            d                    z   }nAt           j                            |           r|	}nt           j                            |	          }|
r|dz  }|
rdnd}|
rdnt          |	          }t!          |t#          |            ||z   |	          V  |d
z  }YdS )z8Yield Completion objects for file paths matching *word*.r   r   r   Nr   ~r  dirstart_positiondisplaydisplay_metar  )r  path
expanduserendswithdirnamebasenamelistdirOSErrorr   r1  r6  r   isdirrelpathisabs_file_size_labelr   r
  )r  r  expanded
search_dirr  r   countprefix_lowerr  	full_pathis_dirdisplay_pathsuffixr   s                 r$   _path_completionsz'SlashCommandCompleter._path_completions9  s)      7%%d++S!! 	0!JFF229cJW%%h//F	j,,GG 	 	 	FF	 ||~~G__ 	 	E ekkmm66|DD ~~Z77IW]]9--F s## :#bgooiASASTWAXAX&Y&YYt$$ :(  "wy99 $#"*SSF"C55(8(C(CD #D		z!	      QJEE=	 	s   =B 
B B c                    | sdS t          |           dz
  }|dk    r#| |         dk    r|dz  }|dk    r| |         dk    | |dz   d         }|                    d          sdS |S )z=Extract a bare ``@`` token for context reference completions.Nr  r   r   @r  r  s      r$   _extract_context_wordz+SlashCommandCompleter._extract_context_wordl  s      	4IIM1ffaCFA 1ffaCAEFF|s## 	4r#   c              #  v  K   |                                 }d}|D ]g\  }}|                                                     |          r;|                                 |k    r#t          |t          |           ||          V  hdD ]}|dd         }||k    s|                    |          r|dk    }	||k    rdn|t          |          d         }
t          j                            |
          }|r|dk    rd	\  }}nZ|                    d
          r|d}}n@t          j                            |          pd}t          j        	                    |          }	 t	          j
        |          }n# t          $ r Y  dS w xY wd}|                                 }t          |          D ]}|r(|                                                     |          s,t          j                            ||          }t          j                            |          }|	|k    rr||k    r nlt          j                            |          }|rd
nd}|rdnt!          |          }| | | }t          |t          |           ||z   |          V  |dz  } dS |dd         }|                     |||          E d{V  dS )zYield Claude Code-style @ context completions.

        Bare ``@`` or ``@partial`` shows static references and matching
        files/folders.  ``@file:path`` and ``@folder:path`` are handled
        by the existing path completion path.
        ))z@diffzGit working tree diff)z@stagedzGit staged diff)@file:zAttach a file)@folder:zAttach a folder)z@git:z Git log with diffs (e.g. @git:5))z@url:zFetch web contentr  )r  r  Nr  r   r   )r   r   r   r   r  r  )r   r6  r   r
  r  r  r  r  r  r  r  r  r1  r   r  r  r  _fuzzy_file_completions)r  r  r  lowered_STATIC_REFSr  r   r  barewant_dir	path_partr  r  match_prefixr   r  r  r  r  r  r  r  
completionquerys                           r$   _context_completionsz*SlashCommandCompleter._context_completionsz  s0      **,,
  , 	 	OIt  ++G44 9J9Jg9U9U $'II:%!%	      - 0	 0	F#2#;Dt||tv66|!Z/"&$,,BBDV4F	7--i88 >8s??/6,J&&s++ >/7JJ!#!:!:!AcJ#%7#3#3H#=#=L j44GG   FFF +1133#G__  E# !EKKMM,D,D\,R,R !  "Z ? ?IW]]955F  6)) ~~#%7??9#=#=L$*2SSF$*K550@0K0KD$*!BL!B&!B!BJ$"(+D		z %%)	      QJEE[ ` QRR//eUCCCCCCCCCCCs   E00
E?>E?r   c                
   t          j                    }t          j                    }| j        r | j        |k    r|| j        z
  dk     r| j        S g }ddd|gdd|gdddd|gfD ]}|d	         }t          j        |          s 	 t          j
        |d
d
d|          }|j        d	k    r|j                                        r|j                                                            d          }|dd         D ]X}t           j                            |          r t           j                            ||          n|}	|                    |	           Y n# t          j        t(          f$ r Y 	w xY w|| _        || _        || _        |S )z9Return cached list of project files (refreshed every 5s).g      @rgz--filesz--sortr=modifiedfdz--typefz--base-directoryr   Tr`  )capture_outputr  r  cwd
Ni  )r  getcwdr  	monotonicr  r  r  shutilwhich
subprocessru   
returncodestdoutr   r   r  r  r  r   TimeoutExpiredr  )
r  r  r  filesr   toolprocr   pro  s
             r$   _get_project_filesz(SlashCommandCompleter._get_project_files  s   ikkn	$$++d++c11## 90#69c"8S"4c:
 	 	C
 q6D<%% !~4   ?a''DK,=,=,?,?'+++--33D99C $Z * *9;q9I9IPbgooa555qS))))E-w7    ! #"s   CEE+*E+filepathr  c                >   |sdS t           j                            |           }|                                }|                                 }|                                }||k    rdS |                    |          rdS ||v rdS ||v rdS d}|D ]&}|t          |          k     r|||         k    r|dz  }'|t          |          k    rTd}d}d}	|D ]1}|t          |          k     r|||         k    r|	dv r|dz  }|dz  }|}	2|t          |          d	z  k    rd
S dS dS )z?Score a file path against a fuzzy query. Higher = better match.r  r  P   <   rQ  r   r   z_-./g      ?#   ra  )r  r  r  r   r6  r
  )
r  r  filename
lower_file
lower_pathlower_qqir   boundary_hitsprevs
             r$   _score_pathz!SlashCommandCompleter._score_path  ss     	17##H--^^%%
^^%%
++--   3  )) 	2j  2j  2  	 	ACLL  Q'"+%5%5aWMBD  G$$gbk)9)9v~~%*!GBGs 222r2qr#      c           	   #    K   |                                  }|s|d|         D ]}|                    d          }t          j                            |          }|rdnd}|rdn=t          t          j                            t          j                    |                    }	t          d| d| t          |           ||	          V  dS g }
|D ]5}| 
                    ||          }|d	k    r|
                    ||f           6|
                    d
            |
d|         D ]\  }}|                    d          }t          j                            |          }|rdnd}|rdn=t          t          j                            t          j                    |                    }	t          d| d| t          |           ||	r| d|	 n|          V  dS )z-Yield fuzzy file completions for bare @query.Nr   folderfiler  r  :r  r   c                $    | d          | d         fS )Nr   r  r   )xs    r$   <lambda>z?SlashCommandCompleter._fuzzy_file_completions.<locals>.<lambda>A  s    AaD5!A$- r#   )r   z  )r  r  r  r  r  r  r   r  r   r
  r(  r   sort)r  r  r  r  r  fpr  r!  kindr   scoredsr   s                r$   r  z-SlashCommandCompleter._fuzzy_file_completions&  s8     '')) 	FUFm  S))7++B//#)5xxv & uu,<GLLb11- - !#OOrOO$'II:$!%	       F  	' 	'B  U++A1uuq"g&&&//000FUF^ 	 	EAr[[%%Fw''++H%1886D" 55(8RY[["--) )D D2 #D		z 04<__d___"	      	 	r#   sub_text	sub_lowerc           
   #  4  K   	 ddl m}  |            D ]r}|d         }|                    |          rS||k    rMt          |t	          |            ||                    dd          p|                    dd                    V  sdS # t          $ r Y dS w xY w)	z1Yield completions for /skin from available skins.r   )
list_skinsr   r   r   sourcer  N)hermes_cli.skin_enginer9  r6  r   r
  r   r   )r6  r7  r9  r5  r   s        r$   _skin_completionsz'SlashCommandCompleter._skin_completionsQ  s      	999999Z\\  y??9-- $)2C2C$(+H~ $%&UU="%=%=%TxQSATAT	        	 	 	DD	s   BB	 	
BBc              #    K   	 ddl m}  |                                di                               di           }d                    |          r)d|k    r#t	          dt          |            dd          V  |                                D ]\  }}|                    |          r||k    rt          |t                    r4|                    d          p|                    d	d
          dd         }nt          |          dd         }t	          |t          |            ||          V  dS # t          $ r Y dS w xY w)zAYield completions for /personality from configured personalities.r   )load_configagentpersonalitiesrT   zclear personality overlayr  r   system_promptr   Nrv  )r   r>  r   r6  r   r
  r   r   r   r   r   )r6  r7  r>  r@  r   promptr   s          r$   _personality_completionsz.SlashCommandCompleter._personality_completionsb  s     	555555'KMM--gr::>>PRSSM  ++ )0C0C $'MM>"!<	      !. 3 3 5 5  f??9-- 
$)2C2C!&$// 0%zz-88`FJJXZ<[<[\_]_\_<`"6{{3B3/$(+H~ $%)	        	 	 	DD	s   D.D4 4
EEc           
   #    K   t                      }	 ddlm}m}m}  |             |                                D ]h\  }}|                    |          rN||k    rH|                    |           t          |t          |           ||j
         d|j         d          V  it          |                                          D ]\}||v r|                    |          r@||k    r:||         }	t          |t          |           ||	j         d|	j                   V  ]n# t           $ r Y nw xY wt#                      D ]E}||v r|                    |          r)||k    r#t          |t          |           |d          V  FdS )	zDYield completions for /model from config aliases + built-in aliases.r   )_ensure_direct_aliasesDIRECT_ALIASESMODEL_ALIASESz (r   r  r   z	LM StudioN)r   hermes_cli.model_switchrE  rF  rG  r   r6  rq   r   r
  rH   rI   r1  keysvendorfamilyr   r  )
r  r6  r7  r  rE  rF  rG  r   daidentitys
             r$   _model_completionsz(SlashCommandCompleter._model_completions~  s7     uu	          #"$$$*0022  b??9-- $)2C2CHHTNNN$(+H~ $(*%B%BBK%B%B%B	      }113344 
 
4<<??9-- $)2C2C,T2H$(+H~ $(0%K%K(/%K%K	     
  	 	 	D	
 011 		 		Dt||y)) di.?.? $'MM> !,	     			 		s   DD" "
D/.D/c              #  p  K   |j         }|                    d          sh|                     |          }||                     |          E d {V  d S |                     |          }||                     |          E d {V  d S |                    d          }|d                                         }t          |          dk    s*t          |          dk    r(|	                    d          rt          |          dk    r|d         nd}|                                }	d|vrl|dk    r| 
                    ||	          E d {V  d S |dk    r|                     ||	          E d {V  d S |d	k    r|                     ||	          E d {V  d S d|vrk|t          v rb|                     |          rMt          |         D ]?}
|
                    |	          r(|
|	k    r"t          |
t          |           |

          V  @d S |dd          }t                                           D ]q\  }}|                     |          s|dd          }|                    |          r7t          |                     ||          t          |           ||          V  r|                                                                 D ]\  }}|dd          }|                    |          rt)          |                    dd                    }|d d         t          |          dk    rdndz   }t          |                     ||          t          |           |d|           V  	 ddlm}  |                                            D ]\  }}|                    |          rt)          |                    dd                    }|d d         t          |          dk    rdndz   }t          |                     ||          t          |           d| d|           V  d S # t0          $ r Y d S w xY w)Nr   r  maxsplitr   r   r   z/modelz/skinz/personality)r  r  r  r   zSkill commandrv  r  u   ⚡ r   r  u   🔌 )text_before_cursorr6  r  r  r  r  r   r   r
  r  rN  r<  rC  r   r  r   r   r   r  r  r   r   r   r   r   )r  documentcomplete_eventr  ctx_word	path_wordrf  base_cmdr6  r7  r  r  r   r  r;  rB  r   
short_descr   cmd_infos                       r$   get_completionsz%SlashCommandCompleter.get_completions  s     *s## 
	11$77H#44X>>>>>>>>>//55I$11)<<<<<<<<<F 

A
&&8>>##u::>>c%jjAoo$--2D2Do#&u::>>uQxxrH ((I (""x''#66xKKKKKKKKKFw&&#55h	JJJJJJJJJF~--#<<XyQQQQQQQQQF (""x;'>'>4CXCXYaCbCb'>&x0  C~~i00 SI5E5E(,/MM>$'     
 FABBx!)) 
	 
	IC((-- 122wH""4((  ))(D99$'II:!%	      2244::<< 
	 
	IC122wH""4(( !$((=/"J"JKK("-#k:J:JR:O:OUWX
 ))(D99$'II:!4
!4!4	     	>>>>>>&9&9&;&;&A&A&C&C 	 	"(&&t,, x||M;KLLMMD!%crcs4yy2~~ee2!NJ$--h==(+D		z .H%9Z%9%9	     		 	  	 	 	DD	s   &B?P' '
P54P5NN)r  r  r  r  r   r  )r  r   r   r   )r   r  )r;  r   r  r   r   r   )r  r   r   r   )r  )r  r   r  r  r   r   )r  r   r  r   r   r  )r)  )r  r   r  r   r  r  )r6  r   r7  r   )r   r   r    r!   r  r  r  staticmethodr  r  r  r  r  r  r(  r  r<  rC  rN  rZ  r   r#   r$   r  r    s       TT VZ7;
' 
' 
' 
' 
'       @ @ @ \@    \. 0 0 0 0 \0d    \TD TD TD TD TDl' ' ' 'R * * * \*X) ) ) ) )V    \     \6, , , ,\T T T T Tr#   r  c                  &    e Zd ZdZ	 	 ddd	Zd
 ZdS )SlashCommandAutoSuggestzInline ghost-text suggestions for slash commands and their subcommands.

    Shows the rest of a command or subcommand in dim text as you type.
    Falls back to history-based suggestions for non-slash input.
    Nhistory_suggestAutoSuggest | None	completerSlashCommandCompleter | Noner   r  c                "    || _         || _        d S r   )_history
_completer)r  r`  rb  s      r$   r  z SlashCommandAutoSuggest.__init__  s    
 (#r#   c                "   |j         }|                    d          s$| j        r| j                            ||          S d S |                    d          }|d                                         }t          |          dk    r|                    d          s|dd                                          }t          D ]o}| j	        | j	        
                    |          s$|dd          }|                    |          r,||k    r&t          |t          |          d                    c S pd S t          |          dk    r|d         nd}	|	                                }
| j	        | j	        
                    |          sd S |t          v rbt          |         rUd|	vrQt          |         D ]C}|                    |
          r,||
k    r&t          |t          |	          d                    c S D| j        r| j                            ||          S d S )Nr   r  rP  r   r   r   )rR  r6  re  get_suggestionr   r   r
  r  r   rf  r  r
   r   )r  bufferrS  r  rf  rW  r  r   r;  r6  r7  r  s               r$   rh  z&SlashCommandAutoSuggest.get_suggestion  s   * s## 	} F}33FHEEE4

A
&&8>>##u::??4==#5#5?8>>##D < <?.t7W7WX[7\7\.qrr7&&t,, <T1A1A%hs4yyzz&:;;;;;4  #5zzA~~5882NN$$	 ?&t/O/OPX/Y/Y&4{""{8'<"(""&x0 ? ?C~~i00 ?SI5E5E)#c(mmnn*=>>>>> = 	B=//AAAtr#   r[  )r`  ra  rb  rc  r   r  )r   r   r    r!   r  rh  r   r#   r$   r_  r_    sN          /326$ $ $ $ $( ( ( ( (r#   r_  r  c                    	 t           j                            |           }n# t          $ r Y dS w xY w|dk     r| dS |dk     r	|dz  ddS |dk     r	|dz  dd	S |dz  dd
S )z:Return a compact human-readable file size, or '' on error.r   i   Bi   z.0fKi   @z.1fMG)r  r  getsizer  )r  sizes     r$   r  r  A  s    wt$$   rrd{{zzzk+$$$$$   +&-----()00000s   " 
00)r   r   )r   r   r   r   )r   r   r   r   )r   r   r   r   )r   r   r   r   )r   r   r   )r   r   r   r   r   r   r\  )r   r   )r   r   )r   r   r   r   )r   r   r  r   r   r   )r  N)r  r   r  r  r  r   r  r  r  r  r   r  )r  )rK  r  r   rL  )r  r  r  r   r   r  )r  r   r   r\  )r  )r  r   r   r  )r   r   )r  r   r   r   )Xr!   
__future__r   r  rer  r  r  collections.abcr   r   dataclassesr   typingr   utilsr   prompt_toolkit.auto_suggestr	   r
   prompt_toolkit.completionr   r   ImportErrorobjectr   r   r"   r   r   r   r   r   _cmdr   r   r   _aliasr   r   rg  r   _catr   r   rp   compile_PIPE_SUBS_REr   r   rk   mgroupr   	frozensetr   r   r   r   r   r   r   r   r   r  _TG_NAME_LIMITr  r  r   r  _clamp_telegram_namesrJ  rX  r[  ru  r  r  r  r  r  r  r  r  r  r  r  r_  r  r   r#   r$   <module>r     ss     # " " " " " 				 				       - - - - - - - - ! ! ! ! ! !       ! ! ! ! ! !CCCCCCCC?????????   KIJJJJ	 $+ + + + + + + +$J&JuH)!# # #J& Jw>	  	J& JxQS\  J& Jy5y  J& Jv6	  J& JwBINNJ& Jv@)LLJ& Jw=y!# # #J&  JxPR[ H6 6 6!J&$ JzCY(* * *%J&( JzCY#% % %)J&, JzUW`i;XZ Z Z-J&0 Jv>	JJ1J&2 Jy? ,>@ @ @3J&6 Jv99 " " "7J&: J|=y$
< < <;J&> Jx?!# # #?J&B JwNPY5 5 5CJ&F JwXZc#% % %GJ&J JvXZcCE E EKJ&N Jx,i88OJ&P JyGPPQJ&R Jy=y -9 9 9SJ&V Jx<i!# # #WJ&^ Jx5  _J&b Jw7$0VX X XcJ&f JxEv  gJ&l J}<o!# # #mJ&p J{A?g/ / /qJ&t JyU#BD D DuJ&z JxR*;24 4 4{J&@ JvP   AJ&D J{A?,mo o oEJ&J Jvln}/DF F FKJ&P Jv>2 2 2QJ&T J{?(GCE E EUJ&Z Jw+_.<Z\ \ \[J&^ JvH/(HDF F F_J&h JwNP`:TK K KiJ&l Jz46F  mJ&p JxE$EG G GqJ&v Jv/1A`b b bwJ&| JyT>Z\ \ \}J&B JxU>IJ J JCJ&L JxIK[  MJ&P J|=?O&( ( (QJ&T J a);= = =UJ&X JyMO_(E>@ @ @YJ&^ JyC$0 0 0_J&f JzG H6 6 6gJ&j Jv0&99kJ&l JyUW` " " "mJ&p JwRTZ[[qJ&r Jz>!# # #sJ&v J{Dfl4 4 4wJ&z JvF
4 4 4{J&~ JwDf  J&B JwH&2 2 2CJ&F JxDf " " "GJ&J JwZ\bccKJ&P Jv~vi1 1 1QJ&  J J J Jb    *?)>)@)@ @ @ @ @9 9 9 9         T TD T$6$6t$<$<TY!l 	T 	TF(,(8%S%Sty%S%S%SH\\\"" 35  4 4 4 4 8 8D 8#..t}bAA (TY 9___l 	8 	8F!),f,,!7DV %' & & & & > >D >'+tD,<'='=O	OO$ 
122 1 1D
di//C
kT^,,A 1771::++C00C *3 3 33 3 3 * *        0 2;  2 2     (P P P P.   :        &   @   2  = ! BJ}-- !rz(++       F -  37k1 k1 k1 k1 k1d5 5 5 5 5D   <k5 k5 k5 k5j   !rz/22 $9 & & &   	$ 	$ 	$ 	$< < < <~5 5 5 5 56   > >B  A A A A   :I I I I II I I I`7 7 7 7 7k 7 7 7t1 1 1 1 1 1s   A
 
AA