
    sj5t                        d 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m	Z	m
Z
mZ ddlmZ  ej        e          Zde
dee         fdZdee         fd	Ze G d
 d                      Z G d d          Z e            ZdS )a  
Platform Adapter Registry

Allows platform adapters (built-in and plugin) to self-register so the gateway
can discover and instantiate them without hardcoded if/elif chains.

Built-in adapters continue to use the existing if/elif in _create_adapter()
for now.  Plugin adapters register here via PluginContext.register_platform()
and are looked up first -- if nothing is found the gateway falls through to
the legacy code path.

Usage (plugin side):

    from gateway.platform_registry import platform_registry, PlatformEntry

    platform_registry.register(PlatformEntry(
        name="irc",
        label="IRC",
        adapter_factory=lambda cfg: IRCAdapter(cfg),
        check_fn=check_requirements,
        validate_config=lambda cfg: bool(cfg.extra.get("server")),
        required_env=["IRC_SERVER"],
        install_hint="pip install irc",
    ))

Usage (gateway side):

    adapter = platform_registry.create_adapter("irc", platform_config)
    N)	dataclassfield)Any	AwaitableCallableOptionalhermes_home_keycallbackreturnc                 j    	 ddl m} |                    |           S # t          t          f$ r Y dS w xY w)zBInfer a plugin profile from code registered outside PluginContext.r   )registryN)tools.registryr   plugin_scope_for_callableImportErrorAttributeError)r   tool_registrys     =/home/agent/.hermes/hermes-agent/gateway/platform_registry.py_plugin_scope_from_callabler   *   sT    <<<<<<66x@@@(   tts    22c                      	 t          j        d          j                            dd          pd} n# t          $ r Y d S w xY wt          t          ddd| i                    S )N   __name__ _Caller 
__module__)sys	_getframe	f_globalsget	Exceptionr   type)module_names    r   _caller_plugin_scoper$   4   sx    mA&&044ZDDJ   tt&Y\;788  s   /2 
A A c                   $   e Zd ZU dZeed<   eed<   eegef         ed<   eg ef         ed<   dZ	e
eegef                  ed<   dZe
eg ef                  ed<   dZe
eegef                  ed	<    ee
          Zeed<   dZeed<   dZe
eg df                  ed<   dZeed<   dZeed<   dZeed<   dZeed<   dZeed<   dZeed<   dZeed<   dZeed<   dZeed<   dZe
eg e
e         f                  ed<   dZe
eeege
e         f                  ed<   dZeed<   dZ e
eege
e!ee
e         f                  f                  ed <   dZ"e
eegeez  f                  ed!<   dZ#e
eeeeegef                  ed"<   dZ$e
ed#e%e         f                  ed$<   dS )%PlatformEntryz3Metadata and factory for a single platform adapter.namelabeladapter_factorycheck_fnNvalidate_configensure_deps_fnis_connected)default_factoryrequired_envr   install_hintsetup_fnpluginsourceplugin_nameallowed_users_envallow_all_envr   max_message_lengthFpii_safeu   🔌emojiTallow_update_commandplatform_hintenv_enablement_fnapply_yaml_config_fncron_deliver_env_varparse_target_ref_fnvalidate_target_ref_fnsend_message_handler.standalone_sender_fn)&r   r   __qualname____doc__str__annotations__r   r   boolr+   r   r,   r-   r   listr/   r0   r1   r3   r4   r5   r6   r7   intr8   r9   r:   r;   r<   dictr=   r>   r?   tupler@   rA   rB   r   r       r   r&   r&   >   s        == III JJJ
 seSj)))) r4x    
 8<OXhud{34;;;" 48NHXb$h/0777
 59L(8SE4K01888 t444L$444 L# .2HhxD)*111 FC
 K  sM3   Hd E3 "&$%%%
 M3 AExXd^); <=DDD  NR(8T4L(4.,H#IJQQQ !##""" [_(C5(5hsmAS;T2U+U"VW^^^
 EIHXseTCZ.?%@AHHH
 LP(8T3S,A3,F#GHOOO" FJ(8C4,@#ABIIIIIrL   r&   c                      e Zd ZdZd dZedefd            Zdddee         d	e	de
eeef         eeeg df         f         f         fd
Zdddedeg df         dee         ddfdZdddedee         de
ee         eeg df                  f         fdZdddede
ee         eeg df                  f         de
ee         eeg df                  f         dee         de	f
dZd!dedee         ddfdZdddedee         de	fdZd dZdddedee         ddfdZdddedee         de	fdZdedee         fdZdee         fdZdee         fdZdee         fdZdede	fdZdededee         fdZdS )"PlatformRegistryzCentral registry of platform adapters.

    Registrations are serialized, and concurrent lazy lookups share an
    in-flight event while the loader runs outside the registry lock.
    r   Nc                     t          j                    | _        i | _        i | _        i | _        i | _        i | _        i | _        i | _	        t                      | _        i | _        d S N)	threadingRLock_lock_entries_scoped_entries	_deferred_scoped_deferred	_inflight_inflight_loaders_inflight_ownersset_cancelled_inflight_consumed_loadersselfs    r   __init__zPlatformRegistry.__init__   st    _&&
24 EG 9;JLKM  	 GICF55 
  	rL   c                      t                      S rP   r	   r   rL   r   current_scope_keyz"PlatformRegistry.current_scope_key  s       rL   Fcreatescoperd   c                    || j         | j        fS |r6| j                            |i           | j                            |i           fS | j                            |i           | j                            |i           fS rP   )rT   rV   rU   
setdefaultrW   r    )r_   re   rd   s      r   _scope_mapszPlatformRegistry._scope_maps  s     ==$.00 	$//r::%00;; 
  $$UB//!%%eR00
 	
rL   )re   r'   loaderc                    | j         5  |                     |d          \  }}| j                            ||fd           ||v r	 ddd           dS |||<   ddd           dS # 1 swxY w Y   dS )a  Register a lazy loader for a platform that hasn't been imported yet.

        *loader* is a zero-arg callable that imports the owning plugin module,
        which is expected to call :meth:`register` with the real entry for
        *name*.  The loader runs at most once, the first time *name* is looked
        up (or when the full entry list is materialized).  A real entry that is
        registered directly (e.g. a built-in) takes precedence -- the deferred
        loader is then dropped.
        Trc   N)rS   rh   r]   pop)r_   r'   ri   re   entriesdeferreds         r   register_deferredz"PlatformRegistry.register_deferred(  s      Z 	$ 	$ $ 0 0t 0 D DGX"&&t}d;;;w	$ 	$ 	$ 	$ 	$ 	$ 	$ 	$ $HTN	$ 	$ 	$ 	$ 	$ 	$ 	$ 	$ 	$ 	$ 	$ 	$ 	$ 	$ 	$ 	$ 	$ 	$s   =A$A$$A(+A(c                   | j         5  |                     |          \  }}|                    |          }|                    |          || j                            ||f          }|                    |          || j                            ||f          }|                    |          |fcddd           S # 1 swxY w Y   dS )a>  Return the concrete and deferred state for *name* without resolving it.

        This host-facing snapshot lets the plugin ledger restore a deferred
        platform loader that a concrete registration displaced, without
        importing the displaced adapter as a side effect of taking the
        snapshot.
        N)rS   rh   r    rY   r]   )r_   r'   re   rl   rm   ri   s         r   snapshot_registrationz&PlatformRegistry.snapshot_registration@  s    Z 	- 	- $ 0 0 7 7GX\\$''F{{4  (V^/33UDMBB{{4  (V^/33UDMBB;;t$$f,	- 	- 	- 	- 	- 	- 	- 	- 	- 	- 	- 	- 	- 	- 	- 	- 	- 	-s   B*B??CCcurrentpreviousc                0   | j         5  |                     |d          \  }}|                    |          }|                    |          }||f}	||| j                            |	          }||| j                            |	          }||f}
|
d         |d         up|
d         |d         u }|s	 ddd           dS |\  }}||                    |d           n|||<   ||                    |d           n|||<   |	| j        v r| j                            |	           | j                            |	d           |:|s| j	                            |d           |s| j
                            |d           	 ddd           dS # 1 swxY w Y   dS )at  Restore a platform registration if its full state is still current.

        The identity checks protect a later registration from being removed
        while still allowing an unloaded override to reveal the registration
        it displaced.  Both concrete entries and deferred loaders are part of
        the state because bundled platform plugins load lazily.
        Trc   Nr      F)rS   rh   r    rY   r]   rk   rX   r\   addrU   rW   )r_   r'   rq   rr   re   rl   rm   entryri   load_keycurrent_state
is_currentprevious_entryprevious_loaders                 r   restore_registrationz%PlatformRegistry.restore_registrationV  sC    Z "	 "	 $ 0 0t 0 D DGXKK%%E\\$''Ft}H}/33H==}/33H=="FOMa 
2 6 #71:5J  "	 "	 "	 "	 "	 "	 "	 "	" /7+NO%D$'''' .&T4((((!04>))(,,X666"&&x666  :(,,UD999 ;)--eT:::E"	 "	 "	 "	 "	 "	 "	 "	 "	 "	 "	 "	 "	 "	 "	 "	 "	 "	s   B-FB<FFFc                    d}d}d}| j         5  |p|                                 }|                     |          \  }}||f}	d|f}
| j                            |	          }|	}|||vr|                    |d          }|"| ||vr| j                            |
          }|
}|#|!||vr| j                            |d          }|
}|F|Dt          j                    }|| j        |<   || j	        |<   t          j
                    | j        |<   d}|	 ddd           dS |sX| j                            |          t          j
                    k    r)t                              d|           	 ddd           dS ddd           n# 1 swxY w Y   |s,|                                 |                     ||           dS 	  |             n5# t           $ r(}t                              d||d           Y d}~nd}~ww xY w| j         5  || j        v }|\  }}|                     |          \  }}|s||vr||vr
|| j        |<   | j                            |d           | j	                            |d           | j                            |d           | j                            |           |                                 ddd           n# 1 swxY w Y   n# | j         5  || j        v }|\  }}|                     |          \  }}|s||vr||vr
|| j        |<   | j                            |d           | j	                            |d           | j                            |d           | j                            |           |                                 ddd           w # 1 swxY w Y   w xY w|r|                     ||           dS dS )z5Run the deferred loader for *name* if one is pending.NFTz:Deferred platform '%s' recursively requested while loadingz)Deferred load of platform '%s' failed: %sexc_info)rS   rb   rh   rX   r    rk   rV   rQ   EventrY   	get_identrZ   loggerwarningwait_resolver!   r\   r]   discardr[   )r_   r'   re   ri   event	is_loaderactive_scoperl   rm   
scoped_key
global_keyrw   ewas_cancelled
load_scope
_load_names                   r   r   zPlatformRegistry._resolve  sa   /3+/	Z 	 	 <D$:$:$<$<L $ 0 0 > >GX&-JJN&&z22E!H}W!4!4!dD11}D4G4G**:66%}D4G4G++D$77%}!3!))+0x(39&x02;2E2G2G%h/ 	}-	 	 	 	 	 	 	 	0 )--h779;N;P;PPPP   ?	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	B  	JJLLL MM$---F	FHHHH 	 	 	NN;	         	    (D,D D)1&
J$($4$4Z$@$@!%>G++H,,7=D*84""8T222&**8T:::%))(D999(00:::		                 (D,D D)1&
J$($4$4Z$@$@!%>G++H,,7=D*84""8T222&**8T:::%))(D999(00:::		                 	.MM$-----	. 	.s   DFAFFF>
G	 K 	
G;G61K 6G;;K B:KKKN1B:N%N1%N))N1,N)-N1c                Z    | j         5  ||f| j        v cddd           S # 1 swxY w Y   dS )z@Return whether ownership teardown cancelled an in-flight loader.N)rS   r\   )r_   r'   re   s      r   is_deferred_load_cancelledz+PlatformRegistry.is_deferred_load_cancelled  s     Z 	= 	=4=D$<<	= 	= 	= 	= 	= 	= 	= 	= 	= 	= 	= 	= 	= 	= 	= 	= 	= 	=s    $$c                    |                                  }| j        5  |                     |          \  }}t          |          }t          | j                  }| j        D ]8\  }}||k    r|                    |           !||                    |           9	 ddd           n# 1 swxY w Y   t          |          D ]}|                     ||           t          |          D ]}|                     ||           dS )aF  Run every pending deferred loader.

        Used by the iterate-all accessors (``all_entries``/``plugin_entries``),
        which are only called by paths that genuinely need every adapter:
        gateway startup, ``hermes setup``/``gateway status``, channel
        directory.  CLI chat never iterates the full set.
        N)	rb   rS   rh   r[   rV   rX   ru   sortedr   )r_   r   rT   scoped_deferredscoped_namesglobal_namesinflight_scoper'   s           r   _resolve_allzPlatformRegistry._resolve_all  sf    --//Z 	+ 	+(,(8(8(F(F%Ho//Lt~..L(, + +$!\11 $$T****#+ $$T***	+		+ 	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+ <(( 	. 	.DMM$----<(( 	. 	.DMM$----	. 	.s   A<B%%B),B)rv   c                f   | j         5  |E|j        dk    r:t                      }|t          |j                  }|t          |j                  }|                     |d          \  }}| j                            ||j	        fd           |                    |j	        d           |j	        |v r9||j	                 }t                              d|j	        |j        |j                   |||j	        <   t                              d|j	        |j                   ddd           dS # 1 swxY w Y   dS )zRegister a platform adapter entry.

        If an entry with the same name exists, it is replaced (last writer
        wins -- this lets plugins override built-in adapters if desired).
        Nr2   Trc   z,Platform '%s' re-registered (was %s, now %s)z$Registered platform adapter: %s (%s))rS   r3   r$   r   r)   r*   rh   r]   rk   r'   r   infodebug)r_   rv   re   rl   rm   prevs         r   registerzPlatformRegistry.register  s    Z 	[ 	[}!9!9,..=78MNNE=7GGE $ 0 0t 0 D DGX"&&uz':DAAALLT***zW$$uz*BJKL	   #(GEJLL?U\ZZZ)	[ 	[ 	[ 	[ 	[ 	[ 	[ 	[ 	[ 	[ 	[ 	[ 	[ 	[ 	[ 	[ 	[ 	[s   DD&&D*-D*c                4   | j         5  ||nt                      }|p|                                 }|                     |          \  }}|||v s||v rv|                    |d           |                    |d          du}|s| j                            |d           |s| j                            |d           |cddd           S | j                            |d           | j                            |d          ducddd           S # 1 swxY w Y   dS )z5Remove a platform entry.  Returns True if it existed.N)	rS   r$   rb   rh   rk   rU   rW   rV   rT   )r_   r'   re   inferred_scoper   rl   rm   removeds           r   
unregisterzPlatformRegistry.unregister  s   Z 	= 	=&+&7UU=Q=S=SN)ET-C-C-E-EL $ 0 0 > >GX)TW__@P@PT4(((!++dD11= A(,,\4@@@ B)--lDAAA	= 	= 	= 	= 	= 	= 	= 	= NtT***=$$T400<	= 	= 	= 	= 	= 	= 	= 	= 	= 	= 	= 	= 	= 	= 	= 	= 	= 	=s   B4D	7DDDc                    |                                  }| j        5  |                     |          \  }}||vo+||v p'|| j        vo|| j        v p||f| j        v p
d|f| j        v }ddd           n# 1 swxY w Y   |r|                     ||           | j        5  |                     |          \  }}|                    |          p| j                            |          cddd           S # 1 swxY w Y   dS )z!Look up a platform entry by name.N)rb   rS   rh   rT   rV   rX   r   r    )r_   r'   re   rl   rm   needs_resolverV   s          r   r    zPlatformRegistry.get)  s   &&((Z 	 	 $ 0 0 7 7GX /   2-H$$.2H24=DN22 $<4>1	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	  	'MM$&&&Z 	@ 	@!%!1!1%!8!8GY;;t$$?(9(9$(?(?	@ 	@ 	@ 	@ 	@ 	@ 	@ 	@ 	@ 	@ 	@ 	@ 	@ 	@ 	@ 	@ 	@ 	@s%   A	A11A58A5AC//C36C3c                 V   |                                   | j        5  t          | j                  }|                    | j                            |                                 i                      t          |	                                          cddd           S # 1 swxY w Y   dS )z'Return all registered platform entries.N)
r   rS   rJ   rT   updaterU   r    rb   rH   values)r_   rl   s     r   all_entrieszPlatformRegistry.all_entries:  s    Z 	* 	*4=))GNN4/33D4J4J4L4LbQQRRR(())	* 	* 	* 	* 	* 	* 	* 	* 	* 	* 	* 	* 	* 	* 	* 	* 	* 	*s   A5BB"%B"c                 f    |                                   d |                                 D             S )z/Return only plugin-registered platform entries.c                 (    g | ]}|j         d k    |S )r2   )r3   ).0r   s     r   
<listcomp>z3PlatformRegistry.plugin_entries.<locals>.<listcomp>E  s$    FFFaX1E1E1E1E1ErL   )r   r   r^   s    r   plugin_entrieszPlatformRegistry.plugin_entriesB  s4    FF4++--FFFFrL   c                 X   | j         5  |                                 }|                     |          \  }}|                                |                                z  | j                                        z  | j                                        z  	 cddd           S # 1 swxY w Y   dS )ax  Return concrete and deferred platform names without loading adapters.

        Mirrors ``is_registered()``'s scope semantics: names registered under
        the current profile scope AND process-global names both count. Plugin
        platforms register deferred loaders under a profile scope, so reading
        only the global maps would miss every plugin platform.
        N)rS   rb   rh   keysrT   rV   )r_   re   rl   rm   s       r   registered_namesz!PlatformRegistry.registered_namesG  s     Z 	 	**,,E $ 0 0 7 7GX--//"-$$&&' .%%''(	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	s   B
BB#&B#c                     | j         5  |                                 }|                     |          \  }}||v p+||v p'|| j        v p|| j        v p||f| j        v p
d |f| j        v 	 cd d d            S # 1 swxY w Y   d S rP   )rS   rb   rh   rT   rV   rX   )r_   r'   re   rl   rm   s        r   is_registeredzPlatformRegistry.is_registeredY  s    
 Z 
	 
	**,,E $ 0 0 7 7GX 28#24=(2 4>)2 4=DN2	2
 $<4>1
	 
	 
	 
	 
	 
	 
	 
	 
	 
	 
	 
	 
	 
	 
	 
	 
	 
	s   AA22A69A6configc                    |                      |          }|dS d}	 t          |                                          }n8# t          $ r+}t                              d|j        |           Y d}~nd}~ww xY w|s|j        }t                              d|j                   	 t          |                                          }n:# t          $ r-}t                              d|j        |           d}Y d}~nd}~ww xY w|s7|j	        rd|j	         dnd}t                              d	|j        |           dS |j
        r	 |
                    |          s"t                              d
|j                   dS n9# t          $ r,}t                              d|j        |           Y d}~dS d}~ww xY w	 |                    |          }|S # t          $ r.}t                              d|j        |d           Y d}~dS d}~ww xY w)ah  Create an adapter instance for the given platform name.

        Returns None if:
        - No entry registered for *name*
        - check_fn() returns False and deps can't be installed
          (no ensure_deps_fn, or ensure_deps_fn() returned False)
        - validate_config() returns False (misconfigured)
        - The factory raises an exception
        NFz!Platform '%s' check_fn raised: %su<   Platform '%s' dependencies missing — attempting install...z+Platform '%s' dependency install raised: %sz ()r   z$Platform '%s' requirements not met%sz&Platform '%s' config validation failedz)Platform '%s' config validation error: %sz.Failed to create adapter for platform '%s': %sTr~   )r    rG   r*   r!   r   r   r(   r,   r   r0   r+   r)   error)r_   r'   r   rv   deps_okr   hintadapters           r   create_adapterzPlatformRegistry.create_adapterj  s    =4	5>>++,,GG 	 	 	NN3U[!       	  	 5/; KKN   u335566      AK  
     	161CK-*----DNN6  
 4 ,,,V44  NN@    4     ?K  
 ttttt
	++F33GN 	 	 	LL@	     44444	s]   !? 
A4	!A//A4!!C 
C:#C55C:>5E6 6
F, !F''F,0G 
G?#G::G?)r   NrP   ) r   r   rC   rD   r`   staticmethodrE   rb   r   rG   rK   rJ   r&   r   rh   rn   rp   r|   r   r   r   r   r   r    rH   r   r   r[   r   r   r   r   r   rL   r   rN   rN      s           B !s ! ! ! \! 	
 
 
}
 	

 
tC&'c8BH3E.E)FF	G
 
 
 
2  $$ $ $$ T"$
 }$ 
$ $ $ $8  $	- - -- }	-
 
x&"d(1C(DD	E- - - -8  $1 1 11 x."d(9K0LLM1 /(2t8:L1MMN	1 }1 
1 1 1 1fI. I.S I.# I.$ I. I. I. I.^  $	= = == }	=
 
= = = =. . . .:  $	[ [ [[ }	[
 
[ [ [ [B ?C = = =s =hsm =t = = = ="@ @ 7 @ @ @ @"*T-0 * * * *G] 3 G G G G
#c(    $# $    "L3 L L L L L L L LrL   rN   )rD   loggingr   rQ   dataclassesr   r   typingr   r   r   r   hermes_constantsr
   	getLoggerr   r   rE   r   r$   r&   rN   platform_registryr   rL   r   <module>r      sa   <  



     ( ( ( ( ( ( ( ( 5 5 5 5 5 5 5 5 5 5 5 5 , , , , , ,		8	$	$( x}    hsm     fJ fJ fJ fJ fJ fJ fJ fJRN N N N N N N Nd %$&&   rL   