
    `gj4                         d Z ddlZddlmZmZ ddlmZmZmZm	Z	  ej                  e      Ze G d d             Z G d d      Z e       Zy)	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Optionalc                      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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de e   f      ed <   y)!PlatformEntryz3Metadata and factory for a single platform adapter.namelabeladapter_factorycheck_fnNvalidate_configis_connected)default_factoryrequired_env 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.standalone_sender_fn)!__name__
__module____qualname____doc__str__annotations__r   r   boolr   r   r   r   listr   r   r   r   r   r   r   r   intr   r   r   r   r    dictr!   r"   r#   r        L/root/.hermes/venv/lib/python3.12/site-packages/gateway/platform_registry.pyr
   r
   &   s   = I J
 seSj)) r4x  
 8<OXhud{34;
 59L(8SE4K018 t4L$4 L# .2HhxD)*1 FC
 K  sM3   Hd E3 "&$%
 M3 AExXd^); <=D  NR(8T4L(4.,H#IJQ !##"" FJ(8C4,@#ABIr/   r
   c                       e Zd ZdZddZdedeg df   ddfdZdeddfdZdd	Z	d
e
ddfdZd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defdZdededee   fdZy)PlatformRegistryzCentral registry of platform adapters.

    Thread-safe for reads (dict lookups are atomic under GIL).
    Writes happen at startup during sequential discovery.
    returnNc                      i | _         i | _        y N_entries	_deferredselfs    r0   __init__zPlatformRegistry.__init__   s    24 9;r/   r   loaderc                 @    || j                   v ry|| j                  |<   y)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.
        Nr6   )r:   r   r<   s      r0   register_deferredz"PlatformRegistry.register_deferred   s!     4== %tr/   c                     | j                   j                  |d      }|y	  |        y# t        $ r#}t        j	                  d||d       Y d}~yd}~ww xY w)z5Run the deferred loader for *name* if one is pending.Nz)Deferred load of platform '%s' failed: %sTexc_info)r8   pop	Exceptionloggerwarning)r:   r   r<   es       r0   _resolvezPlatformRegistry._resolve   s\    ##D$/>	H 	NN;	   	s   ) 	AAAc                 t    | j                   syt        | j                         D ]  }| j                  |        y)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)r8   r+   rG   r:   r   s     r0   _resolve_allzPlatformRegistry._resolve_all   s2     ~~( 	 DMM$	 r/   entryc                    | j                   j                  |j                  d       |j                  | j                  v rO| j                  |j                     }t        j                  d|j                  |j                  |j                         || j                  |j                  <   t        j                  d|j                  |j                         y)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).
        Nz,Platform '%s' re-registered (was %s, now %s)z$Registered platform adapter: %s (%s))r8   rB   r   r7   rD   infor   debug)r:   rK   prevs      r0   registerzPlatformRegistry.register   s     	5::t,::&==,DKK>

	 %*ejj!;UZZVr/   c                 v    | j                   j                  |d       | j                  j                  |d      duS )z5Remove a platform entry.  Returns True if it existed.N)r8   rB   r7   rI   s     r0   
unregisterzPlatformRegistry.unregister   s2    4&}}  t,D88r/   c                 v    || j                   vr| j                  |       | j                   j                  |      S )z!Look up a platform entry by name.)r7   rG   getrI   s     r0   rT   zPlatformRegistry.get   s/    t}}$MM$}}  &&r/   c                 h    | j                          t        | j                  j                               S )z'Return all registered platform entries.)rJ   r+   r7   valuesr9   s    r0   all_entrieszPlatformRegistry.all_entries  s&    DMM((*++r/   c                     | j                          | j                  j                         D cg c]  }|j                  dk(  s| c}S c c}w )z/Return only plugin-registered platform entries.r   )rJ   r7   rV   r   )r:   rF   s     r0   plugin_entrieszPlatformRegistry.plugin_entries
  s:    ==//1JaQXX5IJJJs   A	A	c                 >    || j                   v xs || j                  v S r5   r6   rI   s     r0   is_registeredzPlatformRegistry.is_registered  s!    
 t}}$>(>>r/   configc                    || j                   vr| j                  |       | j                   j                  |      }|y|j                         s@|j                  rd|j                   dnd}t
        j                  d|j                  |       y|j                  4	 |j                  |      s!t
        j                  d|j                         y	 	 |j                  |      }|S # t        $ r+}t
        j                  d|j                  |       Y d}~yd}~ww xY w# t        $ r-}t
        j                  d|j                  |d	
       Y d}~yd}~ww xY w)a  Create an adapter instance for the given platform name.

        Returns None if:
        - No entry registered for *name*
        - check_fn() returns False (missing deps)
        - validate_config() returns False (misconfigured)
        - The factory raises an exception
        Nz ()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@   )r7   rG   rT   r   r   rD   rE   r   r   rC   r   error)r:   r   r\   rK   hintrF   adapters          r0   create_adapterzPlatformRegistry.create_adapter  s?    t}}$MM$!!$'=~~161C1CR**+1-DNN6
   ,,,V4NN@   5
	++F3GN  ?KK
   	LL@	   	s0   1C" D "	D+!DD	E"#E

E)r3   N)r$   r%   r&   r'   r;   r(   r   r>   rG   rJ   r
   rP   r*   rR   r   rT   r+   rW   rY   r[   r   rb   r.   r/   r0   r2   r2      s    ;$&c &8BH3E &$ &S T  Wm W W&9s 9t 9
' ' 7 ',T-0 ,
K] 3 K
?# ?$ ?23 2 2 2r/   r2   )r'   loggingdataclassesr   r   typingr   r   r   r   	getLoggerr$   rD   r
   r2   platform_registryr.   r/   r0   <module>rh      sb   <  ( 5 5			8	$ xJ xJ xJvf fT %& r/   