
    i              	      
   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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           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-d.$           ed/d0d           ed1d2dd	d34           ed5d6dd	7           ed8d9dd:d;$           ed<d=dd>            ed?d@ddAd;$           edBdCd           edDdEdF           edGdHdd	dIJ           edKdLdd            edMdNdOd	           edPdQdOdR            edSdTdO           edUdVdF           edWdXdOd            edYdZdOd	d[\           ed]d^dOd	d_`           edadbdO           edcdddOdedfg           edhdidOdjdkg           edldmdOd	dn           edodpdOdqdrg           edsdtdudvd	w           edxdydud	           edzd{dud	d|}           ed~ddud	dd           edddu           edddud           edddud	dd           edddud	           edddFd	d4           edddF           edddd	7           edddF           edddFd            edddFd	d\           edddFd	           edddFd	dn           edddFd	7           edddF           edddd	d\          Zded<   ddZ e            Zded<   ddZdd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!         Z.e.e)v sej/        se-0                    ej/                  Z1e1r+e12                    d          3                    d          e)e.<   ` e4d eD                       Z5ded<   ddńZ6dddɄZ7dd˄Z8dd̈́Z9dZ:	 e:Z; ej,        dϦ          Z< ej,        dЦ          Z=dd҄Z>ddՄZ?e?Z@	 	 ddd߄ZAdddZBddZCddZDddZE G d de          ZF G d de          ZGddZHdS )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)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/agentuser/.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   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]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)bgz<prompt>btwzGEphemeral side question using session context (no tools, not persisted)z
<question>queuez4Queue a prompt for the next turn (doesn't interrupt))q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 sessionz[model] [--global]providerz-Show available providers and current provider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   yoloz7Toggle YOLO mode (skip all dangerous command approvals)	reasoningz#Manage reasoning effort and displayz[level|show|hide])
noneminimallowmediumhighxhighshowhideonoff)r   r   fastuS   Toggle fast mode — OpenAI Priority Processing / Anthropic Fast Mode (Normal/Fast)z[normal|fast|status])normalrU   r;   rS   rT   skinz%Show or change the display skin/theme)r   r   voicezToggle voice modez[on|off|tts|status])rS   rT   ttsr;   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pauser?   runremove)r   r   r   reloadz.Reload .env variables into the running sessionz
reload-mcpzReload MCP servers from config)
reload_mcpbrowserz1Connect browser tools to your live Chrome via CDPz[connect|disconnect|status])connect
disconnectr;   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pastez*Check clipboard for an image and attach it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_COMMANDS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 ]j}|}|j                            d          D ]/}t          |t                    r|	                    |          }-d} |r|
                    |j                   k|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>  s     BBB1A,ABQBBBr"   r   )read_raw_config.N)r}   sethermes_cli.configr   	Exceptionr   split
isinstancedictr   rc   r   )gatedr   cfgresultr   valkeys          r#   _resolve_config_gatesr     s    CB(BBBE uu555555o   uuuuF 	! 	!*0055 	 	C#t$$ ggcll 	!JJsx   Ms   4 AAconfig_overridesset[str] | Noner   c                \    | 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]]c                     t                      } g }t          D ]E}t          ||           st          |j                  }|r|                    ||j        f           F|S )zReturn (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.
    )r   r}   r   _sanitize_telegram_namer   r   r   )r   r   r   tg_names       r#   telegram_bot_commandsr   A  sn     &''I$&F 6 6$S)44 	)#(33 	6MM7CO4555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_UNDERSCOREstrip)r   r   s     r#   r   r   _  s[     99;;sC((D  T**D##C..D::c??r"   entries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rangerc   r   )	r   r   usedr   r   desc	candidateprefixdigits	            r#   _clamp_command_namesr   m  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           	        g }g }	 ddl m}  |            }t          |di           }	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   )get_plugin_manager_plugin_commandsr   Plugin commandN   ...c              3      K   | ]	\  }}|V  
d S r   r   r   nr   s      r#   r   z1_collect_gateway_skill_entries.<locals>.<genexpr>  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"   )hermes_cli.pluginsr   getattrsortedr   r   r   r   r   rx   r   agent.skill_utilsr   agent.skill_commandsr   tools.skills_toolr   r   resolve
startswithr   max) r   r   r   r   r   all_entriesplugin_pairsr   pm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_entriesr    sK   F /1K +-L999999!!b"4b99{++ 	. 	.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# #
D0/D06E
J 
JJ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)rb   r   r  r   r  r   extend)r  core_commandsr   all_commandsremaining_slotsr   r  s          r#   telegram_menu_commandsr%  
  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   )r  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   r'  r   r   r   r   r   r   r   r   Nr   r   r   a   r         r   )pathlibr+  r   r   r   r   r   r   r   r   r  r   r   r   r  r   rc   r   parentrelative_to
ValueErrorparts
setdefaultr   r  )r   _Pr	  r   
categoriesuncategorized_names_usedhiddenr   r   r  r  r  r  r  r  spr  r  discord_namer   relr3  cat_MAX_GROUPS_MAX_PER_GROUPtrimmed_categoriesgroup_countr   r$  s                                 r#   "discord_skill_commands_by_categoryrB  J  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/c                     t                      } i }t          D ]7}t          ||           sd|j         ||j        <   |j        D ]
}d| ||<   8|S )zReturn 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.
    r   )r   r}   r   r   r   )r   mappingr   r   s       r#   slack_subcommand_maprE    sx     &''I G ) )$S)44 	*NN[ 	) 	)E([[GENN	)Nr"   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-d.d            Z
ed,d            Zd-d.dZd/dZed0d             Zd1d2d"Zd3d%Zd& ZdS )4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~   Nonec                L    || _         || _        g | _        d| _        d| _        d S )Ng        r   )_skill_commands_provider_command_filter_file_cache_file_cache_time_file_cache_cwd)selfrH  rJ  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)rO  r   r   )rS  rU  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   )rN  r   )rS  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   r  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   )ospath
expanduserendswithdirnamebasenamelistdirOSErrorr   r   r  r   isdirrelpathisabs_file_size_labelr   r   )r[  rf  expanded
search_dirr   r   countprefix_lowerentry	full_pathis_dirdisplay_pathsuffixmetas                 r#   _path_completionsz'SlashCommandCompleter._path_completions  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   @ra  rb  s      r#   _extract_context_wordz+SlashCommandCompleter._extract_context_wordB  s      	4IIM1ffaCFA 1ffaCAEFF|s## 	4r"   c              #  $  K   |                                 }d}|D ]g\  }}|                                                     |          r;|                                 |k    r#t          |t          |           ||          V  hdD ]}|                    |          r|t          |          d         pd}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 ]}|r(|                                                     |          s,||k    r nt          j                            |
|          }t          j                            |          }t          j                            |          }|rdnd}|rd	nd
}|rdnt!          |          }d| d| | }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 contentrj  )r  r  Nr   r   r   r   folderfileri  r  :r   )r   r  r   r   rn  ro  rp  rq  rr  rs  rt  ru  r   r   rv  rw  ry  _fuzzy_file_completions)rS  r[  rf  lowered_STATIC_REFSr   r  r   	path_partrz  r{  match_prefixr   r|  r}  r~  r  r  r  r  kind
completionquerys                          r#   _context_completionsz*SlashCommandCompleter._context_completionsP  s      **,,
  , 	 	OIt  ++G44 9J9Jg9U9U $'II:%!%	      - $	 $	Fv&& # V.5#	7--i88$$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#%7??9#=#=L$*2SSF'-9886D$*K550@0K0KD!BT!B!BL!B&!B!BJ$"(+D		z %%)	      QJEEG#L QRR//eUCCCCCCCCCCCs   1E
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^  timeoutcwd
Ni  )rn  getcwdtime	monotonicrP  rR  rQ  shutilwhich
subprocessrg   
returncodestdoutr   r   ro  rx  rw  r   TimeoutExpiredru  )
rS  r  nowfilesr   toolprocr   pr<  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   <   r  r   r   z_-./g      ?#   r.  )rn  ro  rs  r   r  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   r  r  ri  r  r  rj  r   c                $    | d          | d         fS )Nr   r   r   )xs    r#   <lambda>z?SlashCommandCompleter._fuzzy_file_completions.<locals>.<lambda>  s    AaD5!A$- r"   )r   z  )r  rq  rn  ro  rs  ry  r   r  r   r   r  r   sort)rS  r[  r  rf  r  fpr  r  r  r  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           
   #  h  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  ]dS # t           $ r Y dS w xY w)zDYield completions for /model from config aliases + built-in aliases.r   )_ensure_direct_aliasesDIRECT_ALIASESMODEL_ALIASESz (r   rj  r   N)r   hermes_cli.model_switchr  r  r  itemsr  rc   r   r   rB   rC   r   keysvendorfamilyr   )
rS  r  r  seenr  r  r  r   daidentitys
             r#   _model_completionsz(SlashCommandCompleter._model_completions  s     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	     
 
  	 	 	DD	s   DD# #
D10D1c              #    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          rt          |          dk    r|d         nd}|                                }	d|vr$|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 # t,          $ r Y d S w xY w)Nr   r   maxsplitr   r   r   z/model)rk  rl  rj  r   zSkill command2   r   u   ⚡ )get_plugin_commandsr   u   🔌 )text_before_cursorr  r  r  rd  r  r   r   r   rq  r  r   rW  r   r   r  r]  rZ  r   r   r   r  r   )rS  documentcomplete_eventr^  ctx_word	path_wordr3  base_cmdr  r  r   r[  r   r   r  r  r   
short_descr  cmd_infos                       r#   get_completionsz%SlashCommandCompleter.get_completions8  s     *s## 
	11$77H#44X>>>>>>>>>//55I$11)<<<<<<<<<F 

A
&&8>>##u::>>c%jjAoo$--2D2Do#&u::>>uQxxrH ((I (""x8';';228YGGGGGGGGG (""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?O 
O+*O+NN)rH  rI  rJ  rK  r~   rL  )rU  r   r~   r   )r~   rX  )r  r   r[  r   r~   r   )r^  r   r~   r   )re  )r[  r   rf  r   r~   r   )r  r   r  r   r~   r   )r  )r[  r   r  r   rf  r   )r  r   r  r   )r   r   r   r    rT  rW  rZ  staticmethodr]  rd  r  r  r  r  r  r  r  r  r   r"   r#   rG  rG    s       TT VZ7;
' 
' 
' 
' 
'       @ @ @ \@    \. 0 0 0 0 \0d    \DD DD DD DD DDL' ' ' 'R * * * \*X) ) ) ) )V   BM M M M Mr"   rG  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~   rL  c                "    || _         || _        d S r   )_history
_completer)rS  r  r  s      r#   rT  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   r  r   r   r   )r  r  r  get_suggestionr   r   r   rq  r   r  rW  r	   r   )rS  bufferr  r^  r3  r  r[  r   r  r  r  r   s               r#   r  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  r  r  r  r~   rL  )r   r   r   r    rT  r  r   r"   r#   r  r    sN          /326$ $ $ $ $( ( ( ( (r"   r  ro  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)rn  ro  getsizeru  )ro  sizes     r#   ry  ry    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   N)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   )ro  r   r~   r   )Ir    
__future__r   rn  rer  r  r  collections.abcr   r   dataclassesr   typingr   prompt_toolkit.auto_suggestr   r	   prompt_toolkit.completionr
   r   ImportErrorobjectr   r}   r!   r   r   r   r   r   _cmdr   r   r   _aliasr   r   r4  r   _catr   r   rb   compile_PIPE_SUBS_REr   r   r]   mgroupr   	frozensetr   r   r   r   r   r   _TG_NAME_LIMITr   r   r   r   _clamp_telegram_namesr  r%  r(  rB  rE  rG  r  ry  r   r"   r#   <module>r
     s{     # " " " " " 				 				       - - - - - - - - ! ! ! ! ! !      CCCCCCCC?????????   KIJJJJ	 $+ + + + + + + +$n&JuH)!# # #n& Jw>	  	n& Jy5y  n& Jv6	  n& JwBINNn& Jv@)LLn& Jw=y!# # #n& JxPR[ H6 6 6n&  JzCY(* * *!n&$ JzCY#% % %%n&( JzUW` ,IK K K)n&, Jv>	JJ-n&. Jy? ,>@ @ @/n&2 Jv99 " " "3n&6 J|=y*6 6 67n&: Ju_aj%' ' ';n&> JwNPY5 5 5?n&B Jx,i88Cn&D JyGPPEn&F Jy=y -9 9 9Gn&J Jx<i!# # #Kn&R Jx5  Sn&V Jw7ThiiiWn&X JzJ   Yn&\ JxEvNN]n&` J}<o!# # #an&d J{A?g/ / /en&h JyU#BD D Din&n JvP   on&r J{A?,mo o osn&x Jvln}/DF F Fyn&~ Jv>2 2 2n&B Jw+_.<Z\ \ \Cn&J JwNP`:TK K KKn&N Jz46F  On&R JxE$EG G GSn&X Jv/1A`b b bYn&^ JxIK[\\_n&` J|=?O&( ( (an&d JyMO_(E>@ @ @en&j JyC$0 0 0kn&r JzG H6 6 6sn&v Jv0&99wn&x JyUW` " " "yn&| JwRTZ[[}n&~ Jz>!# # #n&B J{Dfl4 4 4Cn&F JwDf  Gn&J JwH&2 2 2Kn&N JxDf " " "On&R JwZ\bccSn&X Jv~vi1 1 1Yn&  n n n nj    *?)>)@)@ @ @ @ @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 * *        :        &   $  = ! BJ}-- !rz(++       F -  37l1 l1 l1 l1 l1f5 5 5 5 5D   <k5 k5 k5 k5\   *x x x x xI x x x~7 7 7 7 7k 7 7 7t1 1 1 1 1 1s   A AA