+
    Ji                     z    R t ^ RIt^ RIt^ RIHtHtHtHtH	t	 ^ RI
t
^ RIHt ]! 4       R,          t ! R R4      tR# )a  
Event Hook System

A lightweight event-driven system that fires handlers at key lifecycle points.
Hooks are discovered from ~/.hermes/hooks/ directories, each containing:
  - HOOK.yaml  (metadata: name, description, events list)
  - handler.py (Python handler with async def handle(event_type, context))

Events:
  - gateway:startup     -- Gateway process starts
  - session:start       -- New session created (first message of a new session)
  - session:end         -- Session ends (user ran /new or /reset)
  - session:reset       -- Session reset completed (new session entry created)
  - agent:start         -- Agent begins processing a message
  - agent:step          -- Each turn in the tool-calling loop
  - agent:end           -- Agent finishes processing
  - command:*           -- Any slash command executed (wildcard match)

Errors in hooks are caught and logged but never block the main pipeline.
N)AnyCallableDictListOptional)get_hermes_homehooksc                      a  ] tR t^"t o RtR t]V 3R lR l4       tV 3R lR ltV 3R lR lt	RV 3R
 lR llt
RtV tR	# )HookRegistryz
Discovers, loads, and fires event hooks.

Usage:
    registry = HookRegistry()
    registry.discover_and_load()
    await registry.emit("agent:start", {"platform": "telegram", ...})
c                "    / V n         . V n        R # N	_handlers_loaded_hooksselfs   &*/home/ubuntu/hermes-agent/gateway/hooks.py__init__HookRegistry.__init__,   s    46)+    c                0   < V ^8  d   QhRS[ S[,          /# )   return)r   dict)format__classdict__s   "r   __annotate__HookRegistry.__annotate__2   s     ( (d4j (r   c                ,    \        V P                  4      # )z'Return metadata about all loaded hooks.)listr   r   s   &r   loaded_hooksHookRegistry.loaded_hooks1   s     D&&''r   c                   < V ^8  d   QhRR/# r   r   N )r   r   s   "r   r   r   6   s     T T Tr   c           
         ^ RI Hp V P                  P                  R. 4      P	                  V4       V P
                  P	                  RRRRRR.RR	/4       R#   \         d   p\        R
T 2RR7        Rp?R# Rp?ii ; i)z/Register built-in hooks that are always active.)handlezgateway:startupnamezboot-mddescriptionz(Run ~/.hermes/BOOT.md on gateway startupeventspathz	(builtin)z.[hooks] Could not load built-in boot-md hook: TflushN)gateway.builtin_hooks.boot_mdr&   r   
setdefaultappendr   	Exceptionprint)r   boot_md_handlees   &  r   _register_builtin_hooks$HookRegistry._register_builtin_hooks6   s    	TNNN%%&7<CCNS%%	I,-	'   	TB1#FdSS	Ts   AA A?$A::A?c                   < V ^8  d   QhRR/# r#   r$   )r   r   s   "r   r   r   E   s     CV CV4 CVr   c                v   V P                  4        \        P                  4       '       g   R# \        \        P	                  4       4       EF3  pVP                  4       '       g   K  VR,          pVR,          pVP                  4       '       d   VP                  4       '       g   K\   \        P                  ! VP                  RR7      4      pV'       d   \        V\        4      '       g   \        RVP                   R2RR	7       K  VP                  R
VP                  4      pVP                  R. 4      pV'       g   \        RV R2RR	7       EK  \        P                  P!                  RV 2V4      pVe   VP"                  f   \        RV R2RR	7       EKQ  \        P                  P%                  V4      pVP"                  P'                  V4       \)        VRR4      p	V	f   \        RV R2RR	7       EK  V F.  p
V P*                  P-                  V
. 4      P/                  V	4       K0  	  V P0                  P/                  R
VRVP                  RR4      RVR\3        V4      /4       \        RV RV 2RR	7       EK6  	  R#   \4         d*   p\        RTP                   RT 2RR	7        Rp?EKi  Rp?ii ; i)a  
Scan the hooks directory for hook directories and load their handlers.

Also registers built-in hooks that are always active.

Each hook directory must contain:
  - HOOK.yaml with at least 'name' and 'events' keys
  - handler.py with a top-level 'handle' function (sync or async)
Nz	HOOK.yamlz
handler.pyzutf-8)encodingz[hooks] Skipping z: invalid HOOK.yamlTr+   r'   r)   z: no events declaredhermes_hook_z: could not load handler.pyr&   z: no 'handle' function foundr(    r*   z[hooks] Loaded hook 'z' for events: z[hooks] Error loading hook z: )r4   	HOOKS_DIRexistssortediterdiris_diryaml	safe_load	read_text
isinstancer   r1   r'   get	importlibutilspec_from_file_locationloadermodule_from_specexec_modulegetattrr   r.   r/   r   strr0   )r   hook_dirmanifest_pathhandler_pathmanifest	hook_namer)   specmodule	handle_fneventr3   s   &           r   discover_and_loadHookRegistry.discover_and_loadE   sg    	$$&!!y0023H??$$${2M#l2L ''))1D1D1F1F*V>>-*A*A7*A*STz(D'A'A-hmm_<OPX\]$LL?	!h3-i[8LMUYZ !~~=="9+. <4;;#6-i[8ST\`a"88>''/#FHd;	$-i[8TU]ab $ENN--eR8??	J $ ""))I!8<<r#BfCM	+  -i[vhOW[\\c 4f  V3HMM?"QCHPTUUVs?   '-J1J5J>JAJAJ:BJJ8J33J8Nc                P   < V ^8  d   QhRS[ RS[S[S[ S[3,          ,          RR/# )r   
event_typecontextr   N)rL   r   r   r   )r   r   s   "r   r   r      s5      W  WS  W8DcN3K  WW[  Wr   c                  "   Vf   / p\        V P                  P                  V. 4      4      pRV9   dI   VP                  R4      ^ ,          pV R2pVP	                  V P                  P                  V. 4      4       V F4  p V! W4      p\
        P                  ! V4      '       d   VG Rj  xL
  K4  K6  	  R#  L  \         d   p\        RT RT 2RR7        Rp?K`  Rp?ii ; i5i)a  
Fire all handlers registered for an event.

Supports wildcard matching: handlers registered for "command:*" will
fire for any "command:..." event. Handlers registered for a base type
like "agent" won't fire for "agent:start" -- only exact matches and
explicit wildcards.

Args:
    event_type: The event identifier (e.g. "agent:start").
    context:    Optional dict with event-specific data.
N:z:*z[hooks] Error in handler for 'z': Tr+   )	r   r   rD   splitextendasyncioiscoroutiner0   r1   )	r   rY   rZ   handlersbasewildcard_keyfnresultr3   s	   &&&      r   emitHookRegistry.emit   s      ?G **:r:; *##C(+D"V2;LOODNN..|R@ABWJ0&&v.. LL /	 
 ! W6zl#aSIQUVVWsB   B C')B;,B9-B;1C'9B;;C$CC'C$$C'r   r   )__name__
__module____qualname____firstlineno____doc__r   propertyr    r4   rV   rf   __static_attributes____classdictcell__)r   s   @r   r
   r
   "   sP     ,
 ( (T TCV CVJ W  W  Wr   r
   )rl   r_   importlib.utilrE   typingr   r   r   r   r   r@   hermes_cli.configr   r;   r
   r$   r   r   <module>rs      s;   *   6 6  - '	HW HWr   