§
    ‰eîi  ã                   ó~   — d Z ddlZddlZddlmZmZmZmZm	Z	 ddl
Z
ddlmZ  e¦   «         dz  Z G d„ d¦  «        ZdS )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                   óÞ   — e Zd ZdZd„ Zedee         fd„¦   «         Zdd„Z	dd„Z
dedee         fd	„Zdded
eeeef                  ddfd„Z	 dded
eeeef                  dee         fd„ZdS )ÚHookRegistryzÏ
    Discovers, loads, and fires event hooks.

    Usage:
        registry = HookRegistry()
        registry.discover_and_load()
        await registry.emit("agent:start", {"platform": "telegram", ...})
    c                 ó"   — i | _         g | _        d S ©N)Ú	_handlersÚ_loaded_hooks©Úselfs    ú//home/div/.hermes/hermes-agent/gateway/hooks.pyÚ__init__zHookRegistry.__init__,   s   € à46ˆŒØ)+ˆÔÐÐó    Úreturnc                 ó*   — t          | j        ¦  «        S )z'Return metadata about all loaded hooks.)Úlistr   r   s    r   Úloaded_hookszHookRegistry.loaded_hooks1   s   € õ �DÔ&Ñ'Ô'Ð'r   Nc                 ó  — 	 ddl m} | j                             dg ¦  «                             |¦  «         | j                             dddgddœ¦  «         dS # t          $ r}t          d|› �d	¬
¦  «         Y d}~dS d}~ww xY w)z/Register built-in hooks that are always active.r   )Úhandlezgateway:startupzboot-mdz(Run ~/.hermes/BOOT.md on gateway startupz	(builtin)©ÚnameÚdescriptionÚeventsÚpathz.[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_hooksz$HookRegistry._register_builtin_hooks6   sÒ   € ð	TØNÐNÐNÐNÐNÐNàŒN×%Ò%Ð&7¸Ñ<Ô<×CÒCÀNÑSÔSÐSØÔ×%Ò%Ø!ØIØ,Ð-Ø#ð	'ð 'ñ ô ð ð ð øõ ð 	Tð 	Tð 	TÝÐFÀ1ÐFÐFÈdÐSÑSÔSÐSÐSÐSÐSÐSÐSÐSøøøøð	Tøøøs   ‚AA Á
BÁ"A<Á<Bc           	      óZ  — |                       ¦   «          t                               ¦   «         sdS t          t                               ¦   «         ¦  «        D �]S}|                     ¦   «         sŒ|dz  }|dz  }|                     ¦   «         r|                     ¦   «         sŒK	 t          j        |                     d¬¦  «        ¦  «        }|rt          |t          ¦  «        st          d|j        › d�d¬	¦  «         Œ¦|                     d
|j        ¦  «        }|                     dg ¦  «        }|st          d|› d�d¬	¦  «         Œït          j                             d|› �|¦  «        }|�|j        €t          d|› d�d¬	¦  «         �Œ2t          j                             |¦  «        }|j                             |¦  «         t)          |dd¦  «        }	|	€t          d|› d�d¬	¦  «         �Œ•|D ]0}
| j                             |
g ¦  «                             |	¦  «         Œ1| j                             ||                     dd¦  «        |t3          |¦  «        dœ¦  «         t          d|› d|› �d¬	¦  «         �Œ!# t4          $ r'}t          d|j        › d|› �d¬	¦  «         Y d}~�ŒMd}~ww xY wdS )aI  
        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: )r)   Ú	HOOKS_DIRÚexistsÚsortedÚiterdirÚis_dirÚyamlÚ	safe_loadÚ	read_textÚ
isinstanceÚdictr&   r   ÚgetÚ	importlibÚutilÚspec_from_file_locationÚloaderÚmodule_from_specÚexec_moduleÚgetattrr   r#   r$   r   Ústrr%   )r   Úhook_dirÚmanifest_pathÚhandler_pathÚmanifestÚ	hook_namer   ÚspecÚmoduleÚ	handle_fnÚeventr(   s               r   Údiscover_and_loadzHookRegistry.discover_and_loadE   s+  € ð 	×$Ò$Ñ&Ô&Ð&å×ÒÑ!Ô!ð 	ØˆFå�y×0Ò0Ñ2Ô2Ñ3Ô3ð 4	Vñ 4	VˆHØ—?’?Ñ$Ô$ð Øà$ {Ñ2ˆMØ# lÑ2ˆLà ×'Ò'Ñ)Ô)ð °×1DÒ1DÑ1FÔ1Fð Øð*VÝœ>¨-×*AÒ*AÈ7Ð*AÑ*SÔ*SÑTÔT�Øð ¥z°(½DÑ'AÔ'Að ÝÐP¨h¬mÐPÐPÐPÐX\Ð]Ñ]Ô]Ð]Øà$ŸLšL¨°´Ñ?Ô?�	Ø!Ÿš h°Ñ3Ô3�Øð ÝÐM¨iÐMÐMÐMÐUYÐZÑZÔZÐZØõ !”~×=Ò=Ø. 9Ð.Ð.°ñô �ð �< 4¤;Ð#6ÝÐT¨iÐTÐTÐTÐ\`ÐaÑaÔaÐaÙå"œ×8Ò8¸Ñ>Ô>�Ø”×'Ò'¨Ñ/Ô/Ð/å# F¨H°dÑ;Ô;�	ØÐ$ÝÐU¨iÐUÐUÐUÐ]aÐbÑbÔbÐbÙð $ð Kð K�EØ”N×-Ò-¨e°RÑ8Ô8×?Ò?À	ÑJÔJÐJÐJàÔ"×)Ò)Ø%Ø#+§<¢<°¸rÑ#BÔ#BØ$Ý ™MœMð	+ð +ñ ô ð õ ÐO¨iÐOÐOÀvÐOÐOÐW[Ð\Ñ\Ô\Ð\Ñ\øåð Vð Vð VÝÐH°H´MÐHÐHÀQÐHÐHÐPTÐUÑUÔUÐUÐUÐUÐUÐUÑUøøøøðVøøøðg4	Vð 4	Vs5   Â"AI7Ã<AI7ÅAI7ÆA!I7Ç+B
I7É7
J(ÊJ#Ê#J(Ú
event_typec                 óú   — t          | j                             |g ¦  «        ¦  «        }d|v rN|                     d¦  «        d         }|› d�}|                     | j                             |g ¦  «        ¦  «         |S )z¹Return all handlers that should fire for ``event_type``.

        Exact matches fire first, followed by wildcard matches (e.g.
        ``command:*`` matches ``command:reset``).
        ú:r   z:*)r   r   r8   ÚsplitÚextend)r   rK   ÚhandlersÚbaseÚwildcard_keys        r   Ú_resolve_handlerszHookRegistry._resolve_handlersŠ   sz   € õ ˜œ×*Ò*¨:°rÑ:Ô:Ñ;Ô;ˆØ�*ÐÐØ×#Ò# CÑ(Ô(¨Ô+ˆDØ"˜;˜;˜;ˆLØ�OŠO˜DœN×.Ò.¨|¸RÑ@Ô@ÑAÔAÐAØˆr   Úcontextc              ƒ   óð   K  — |€i }|                       |¦  «        D ]Y}	  |||¦  «        }t          j        |¦  «        r|ƒ d{V —† Œ,# t          $ r!}t	          d|› d|› �d¬¦  «         Y d}~ŒRd}~ww xY wdS )aì  
        Fire all handlers registered for an event, discarding return values.

        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ú[hooks] Error in handler for 'ú': Tr    )rS   ÚasyncioÚiscoroutiner%   r&   )r   rK   rT   ÚfnÚresultr(   s         r   ÚemitzHookRegistry.emit—   sÐ   è è € ð ˆ?ØˆGà×(Ò(¨Ñ4Ô4ð 	Wð 	WˆBðWØ˜˜J¨Ñ0Ô0�åÔ& vÑ.Ô.ð !Ø �L�L�L�L�L�L�LøøÝð Wð Wð WÝÐI°zÐIÐIÀaÐIÐIÐQUÐVÑVÔVÐVÐVÐVÐVÐVÐVøøøøðWøøøð	Wð 	Ws   Ÿ(AÁ
A3ÁA.Á.A3c              ƒ   ó"  K  — |€i }g }|                       |¦  «        D ]p}	  |||¦  «        }t          j        |¦  «        r|ƒ d{V —†}|�|                     |¦  «         ŒC# t          $ r!}t          d|› d|› �d¬¦  «         Y d}~Œid}~ww xY w|S )a‹  Fire handlers and return their non-None return values in order.

        Like :meth:`emit` but captures each handler's return value. Used for
        decision-style hooks (e.g. ``command:<name>`` policies that want to
        allow/deny/rewrite the command before normal dispatch).

        Exceptions from individual handlers are logged but do not abort the
        remaining handlers.
        NrV   rW   Tr    )rS   rX   rY   r$   r%   r&   )r   rK   rT   ÚresultsrZ   r[   r(   s          r   Úemit_collectzHookRegistry.emit_collect°   sæ   è è € ð ˆ?ØˆGàˆØ×(Ò(¨Ñ4Ô4ð 	Wð 	WˆBðWØ˜˜J¨Ñ0Ô0�ÝÔ& vÑ.Ô.ð *Ø#)˜\˜\˜\˜\˜\˜\�FØÐ%Ø—N’N 6Ñ*Ô*Ð*øøÝð Wð Wð WÝÐI°zÐIÐIÀaÐIÐIÐQUÐVÑVÔVÐVÐVÐVÐVÐVÐVøøøøðWøøøàˆs   ¡?A!Á!
BÁ+BÂB)r   Nr   )Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   Úpropertyr   r7   r   r)   rJ   r@   r   rS   r   r   r   r\   r_   © r   r   r   r   "   sB  € € € € € ðð ð,ð ,ð ,ð
 ð(˜d 4œjð (ð (ð (ñ „Xð(ðTð Tð Tð TðCVð CVð CVð CVðJ¨Cð °D¸´Nð ð ð ð ðWð W Sð W°8¸DÀÀcÀ¼NÔ3Kð WÐW[ð Wð Wð Wð Wð8 -1ðð àðð ˜$˜s C˜xœ.Ô)ðð 
ˆcŒð	ð ð ð ð ð r   r   )rc   rX   Úimportlib.utilr9   Útypingr   r   r   r   r   r3   Úhermes_cli.configr   r.   r   re   r   r   ú<module>ri      s»   ððð ð* €€€Ø Ð Ð Ð Ø 6Ð 6Ð 6Ð 6Ð 6Ð 6Ð 6Ð 6Ð 6Ð 6Ð 6Ð 6Ð 6Ð 6à €€€à -Ð -Ð -Ð -Ð -Ð -ð ˆOÑÔ Ñ'€	ðið ið ið ið iñ iô ið ið ið ir   