
    i                        U d Z ddlmZ ddlZddlZddlmZmZ ddlm	Z	  e	e
      Z G d d      Zeeef   Z G d d	      Zdad
ed<   ddZdddZy)uG  
utils/event_hooks.py — 이벤트 훅 시스템

이벤트를 emit하면 등록된 핸들러를 순서대로 호출한다.
- 동기/비동기 핸들러 자동 감지
- 와일드카드 매칭 (dispatch:* → dispatch:start, dispatch:end …)
- 핸들러 예외 격리 (catch + log, 메인 파이프라인 블록 안 함)
- 디렉토리 기반 동적 로드 (HOOK.yaml + handler.py)

Usage:
    from utils.event_hooks import Event, get_registry, emit

    reg = get_registry()
    reg.register(Event.DISPATCH_START, my_handler)
    await emit(Event.DISPATCH_START, {"key": "value"})
    )annotationsN)AnyCallable)
get_loggerc                      e Zd ZU dZ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Zded<   dZded<   dZded<   y)Eventu   이벤트 타입 상수 모음.zdispatch:startstrDISPATCH_STARTzdispatch:endDISPATCH_ENDzdispatch:errorDISPATCH_ERRORzsession:startSESSION_STARTzsession:endSESSION_ENDz
agent:step
AGENT_STEPzsecurity:blockSECURITY_BLOCKzsecurity:warnSECURITY_WARNzskill:installSKILL_INSTALLN)__name__
__module____qualname____doc__r
   __annotations__r   r   r   r   r   r   r   r        B/home/jay/workspace/.worktrees/task-2116-dev1/utils/event_hooks.pyr   r   "   s_    )*NC*&L#&*NC*(M3($K$"J"*NC*(M3((M3(r   r   c                  F    e Zd ZdZd	dZd
ddZddZdddZdddZddZ	y)HookRegistryu$   이벤트 핸들러 레지스트리.c                    i | _         y N)	_handlers)selfs    r   __init__zHookRegistry.__init__:   s	    8:r   c                    || j                   vrg | j                   |<   ||xs t        |dt        |            d}| j                   |   j                  |       t        j                  d|d   |       y)ua   핸들러를 이벤트 타입에 등록한다 (와일드카드 포함 가능, e.g. "dispatch:*").r   )fnnamez&Registered handler '%s' for event '%s'r$   N)r   getattrreprappendloggerdebug)r    
event_typehandlerr$   infos        r   registerzHookRegistry.registerB   sg    T^^+)+DNN:&$+T5hWWjZ^_fZg=hiz"))$/=tF|ZXr   c                    g }| j                   j                         D ]2  \  }}||k(  st        j                  ||      s"|j                  |       4 |S )u^   event_type에 매칭되는 모든 핸들러를 반환한다 (정확 매칭 + 와일드카드).)r   itemsfnmatchextend)r    r*   resultpatternhandlerss        r   _matching_handlerszHookRegistry._matching_handlersN   sP    %'!%!5!5!7 	(GX*$
G(Lh'	( r   Nc           	       K   | j                  |      D ];  }|d   }|d   }	 t        j                  |      r ||       d{    n ||       = y7 # t        $ r$}t        j                  d|||d       Y d}~id}~ww xY ww)uZ   비동기 이벤트를 발생시킨다. 핸들러 예외는 격리되어 log만 남긴다.r#   r$   Nz8Hook handler '%s' for event '%s' raised an exception: %sTexc_info)r5   asyncioiscoroutinefunction	Exceptionr(   warning)r    r*   contextr,   r#   handler_nameexcs          r   emitzHookRegistry.emitZ   s     ++J7 	DdB<L..r2W+%%wK	
 &  N !   s@   B AAABA	BA=8B=BBc           	        	 t        j                         }|m|j                         r]| j	                  |      D ]H  }|d   }|d   }	 t        j
                  |      rt        j                   ||      |       n ||       J yt        j                  | j                  ||             y# t        $ r d}Y w xY w# t        $ r$}t        j                  d|||d       Y d}~d}~ww xY w)u   동기 컨텍스트에서 이벤트를 발생시킨다.

        루프 실행 중이면 ensure_future, 없으면 asyncio.run으로 실행.
        Nr#   r$   )loopz7Hook handler '%s' (sync emit) for event '%s' raised: %sTr7   )r9   get_running_loopRuntimeError
is_runningr5   r:   ensure_futurer;   r(   r<   runr@   )r    r*   r=   rB   r,   r#   r>   r?   s           r   	emit_synczHookRegistry.emit_syncq   s    
	++-D  1//
; $Z#F|2226--bkE7$ KK		*g67/  	D	 ! NNQ$"!% #  s)   B+ ;B<+B98B9<	C)C$$C)c                "    ddl m}  || |       y)u   디렉토리를 순회하여 HOOK.yaml + handler.py 기반 훅을 동적으로 로드한다.

        실제 로직은 utils.event_hooks_loader.discover_hooks에 위임한다.

        Args:
            hooks_dir: 훅 서브디렉토리들이 위치한 상위 디렉토리 경로
        r   )discover_hooksN)utils.event_hooks_loaderrJ   )r    	hooks_dirrJ   s      r   discover_and_loadzHookRegistry.discover_and_load   s     	<tY'r   )returnNone) )r*   r	   r+   zCallable[..., Any]r$   r	   rN   rO   )r*   r	   rN   zlist[_HandlerInfo]r   r*   r	   r=   r   rN   rO   )rL   r	   rN   rO   )
r   r   r   r   r!   r-   r5   r@   rH   rM   r   r   r   r   r   7   s%    .;Y.8H
(r   r   zHookRegistry | None	_registryc                 .    t         
t               a t         S )u;   프로세스 전역 싱글턴 HookRegistry를 반환한다.)rR   r   r   r   r   get_registryrT      s      N	r   c                T   K   t               j                  | |       d{    y7 w)uV   전역 싱글턴 레지스트리를 통해 이벤트를 발생시키는 편의 함수.N)rT   r@   )r*   r=   s     r   r@   r@      s     
.

j'
222s   (&()rN   r   r   rQ   )r   
__future__r   r9   r0   typingr   r   utils.loggerr   r   r(   r   dictr	   _HandlerInfor   rR   r   rT   r@   r   r   r   <module>r[      sb   " #     #	H	) )$ CH~h( h(^ "&	 %3r   