
    i!+                        d Z ddlmZ ddlZddlZddlZddlZddlmZ ddl	m
Z
mZmZ  ej        e          Z ee          j        ZddZddZddZ G d d          ZddZddZdS )u  Memory provider plugin discovery.

Scans ``plugins/memory/<name>/`` directories for memory provider plugins.
Each subdirectory must contain ``__init__.py`` with a class implementing
the MemoryProvider ABC.

Memory providers are separate from the general plugin system — they live
in the repo and are always available without user installation. Only ONE
can be active at a time, selected via ``memory.provider`` in config.yaml.

Usage:
    from plugins.memory import discover_memory_providers, load_memory_provider

    available = discover_memory_providers()   # [(name, desc, available), ...]
    provider = load_memory_provider("openviking")  # MemoryProvider instance
    )annotationsN)Path)ListOptionalTuplereturnList[Tuple[str, str, bool]]c                    g } t                                           s| S t          t                                                     D ],}|                                r|j                            d          r2|dz  }|                                sLd}|dz  }|                                rj	 ddl}t          |          5 }|	                    |          pi }ddd           n# 1 swxY w Y   |
                    dd          }n# t          $ r Y nw xY wd}	 t          |          }	|	r|	                                }nd	}n# t          $ r d	}Y nw xY w|                     |j        ||f           .| S )
u   Scan plugins/memory/ for available providers.

    Returns list of (name, description, is_available) tuples.
    Does NOT import the providers — just reads plugin.yaml for metadata
    and does a lightweight availability check.
    )_.__init__.py plugin.yamlr   NdescriptionTF)_MEMORY_PLUGINS_DIRis_dirsortediterdirname
startswithexistsyamlopen	safe_loadget	Exception_load_provider_from_diris_availableappend)
resultschild	init_filedesc	yaml_filer   fmeta	availableproviders
             5/root/.hermes/hermes-agent/plugins/memory/__init__.pydiscover_memory_providersr*       s    G%%'' +335566 6 6||~~ 	!6!6z!B!B 	M)	!! 	 M)	 	)__ 3>>!,,2D3 3 3 3 3 3 3 3 3 3 3 3 3 3 3xxr22    		.u55H "$1133		!	 	 	 	III	 	
D)45555NsH   ,D?C#D#C'	'D*C'	+D
DD(EEEr   strOptional['MemoryProvider']c                N   t           | z  }|                                s#t                              d| t                      dS 	 t	          |          }|r|S t                              d|            dS # t          $ r'}t                              d| |           Y d}~dS d}~ww xY w)zxLoad and return a MemoryProvider instance by name.

    Returns None if the provider is not found or fails to load.
    z$Memory provider '%s' not found in %sNz:Memory provider '%s' loaded but no provider instance foundz'Failed to load memory provider '%s': %s)r   r   loggerdebugr   warningr   )r   provider_dirr(   es       r)   load_memory_providerr3   N   s    
 '-L   ;TCVWWWt*<88 	OSUYZZZt   @$JJJttttts   A3 A3 3
B$=BB$r1   r   c                   | j         }d| }| dz  }|                                sdS |t          j        v rt          j        |         }ndD ]}|t          j        vrt	          t
                    j        }|dk    r|j        }|dz  }|                                rt          j        	                    |t          |          t          |          g          }|rZt          j                            |          }	|	t          j        |<   	 |j                            |	           # t          $ r Y w xY wt          j        	                    |t          |          t          |           g          }|sdS t          j                            |          }|t          j        |<   |                     d          D ]}
|
j         dk    r|
j        }| d| }|t          j        vrt          j        	                    |t          |
                    }|r}t          j                            |          }|t          j        |<   	 |j                            |           # t          $ r&}t"                              d	||           Y d}~d}~ww xY w	 |j                            |           nT# t          $ rG}t"                              d
||           t          j                            |d           Y d}~dS d}~ww xY wt)          |d          rft+                      }	 |                    |           |j        r|j        S n3# t          $ r&}t"                              d||           Y d}~nd}~ww xY wddlm} t5          |          D ]Y}t7          ||d          }t9          |t:                    r1t=          ||          r!||ur	  |            c S # t          $ r Y Uw xY wZdS )u   Import a provider module and extract the MemoryProvider instance.

    The module must have either:
    - A register(ctx) function (plugin-style) — we simulate a ctx
    - A top-level class that extends MemoryProvider — we instantiate it
    plugins.memory.r   N)pluginszplugins.memoryr6   )submodule_search_locationsz*.pyr   zFailed to load submodule %s: %szFailed to exec_module %s: %sregisterzregister() failed for %s: %sr   )MemoryProvider)r   r   sysmodulesr   __file__parent	importlibutilspec_from_file_locationr+   module_from_specloaderexec_moduler   globstemr.   r/   pophasattr_ProviderCollectorr8   r(   agent.memory_providerr9   dirgetattr
isinstancetype
issubclass)r1   r   module_namer"   modr=   parent_pathparent_initspec
parent_modsub_filesub_namefull_sub_namesub_specsub_modr2   	collectorr9   	attr_nameattrs                       r)   r   r   c   s    D*D**K},I t ck!!k+& 4 	! 	!FS[(("8nn3Y&&"-"4K)M9%%'' !$>AAK 0 0474D4D3E B  D  !%.^%D%DT%J%J
.8F+! K33J????( ! ! ! D! ~55Y(+L(9(9': 6 
 
  	4n--d33#&K  %))&11 	Z 	ZH}--}H*77X77MCK//$>AA!3x==   Z'n==hGGG18CK.Z 33G<<<<$ Z Z Z%FWXYYYYYYYYZ	K##C(((( 	 	 	LL7aHHHKOOK...44444	 sJ B&((		BLL###! * ))* 	B 	B 	BLL7qAAAAAAAA	B 544444XX  	sIt,,tT"" 	z$'G'G 	..tvv    4sl   	D$$
D10D1I
J&JJJ, ,
K=6<K88K="M 
M3M..M3	O
O! O!c                  0    e Zd ZdZd Zd Zd Zd Zd ZdS )rH   zAFake plugin context that captures register_memory_provider calls.c                    d | _         d S Nr(   )selfs    r)   __init__z_ProviderCollector.__init__   s        c                    || _         d S r_   r`   )ra   r(   s     r)   register_memory_providerz+_ProviderCollector.register_memory_provider   s     rc   c                    d S r_    ra   argskwargss      r)   register_toolz _ProviderCollector.register_tool       rc   c                    d S r_   rg   rh   s      r)   register_hookz _ProviderCollector.register_hook   rl   rc   c                    d S r_   rg   rh   s      r)   register_cli_commandz'_ProviderCollector.register_cli_command   rl   rc   N)	__name__
__module____qualname____doc__rb   re   rk   rn   rp   rg   rc   r)   rH   rH      se        KK  ! ! !        rc   rH   Optional[str]c                     	 ddl m}   |             }|                    di                               d          pdS # t          $ r Y dS w xY w)u   Read the active memory provider name from config.yaml.

    Returns the provider name (e.g. ``"honcho"``) or None if no
    external provider is configured.  Lightweight — only reads config,
    no plugin loading.
    r   )load_configmemoryr(   N)hermes_cli.configrw   r   r   )rw   configs     r)   _get_active_memory_providerr{      sm    111111zz(B''++J77?4?   tts   := 
A
A
List[dict]c            	     z   g } t                                           s| S t                      }|s| S t           |z  }|                                s| S |dz  }|                                s| S d| d}	 |t          j        v rt          j        |         }nt          j                            |t          |                    }|r|j
        s| S t          j                            |          }|t          j        |<   |j
                            |           t          |dd          }t          |          s| S d| d}d}	|d	z  }
|
                                rp	 d
dl}t!          |
          5 }|                    |          pi }ddd           n# 1 swxY w Y   |                    dd          }|r|}|}	n# t&          $ r Y nw xY wt          || dd          pt          |dd          }|                     |||	|||d           n3# t&          $ r&}t*                              d||           Y d}~nd}~ww xY w| S )u  Return CLI commands for the **active** memory plugin only.

    Only one memory provider can be active at a time (set via
    ``memory.provider`` in config.yaml).  This function reads that
    value and only loads CLI registration for the matching plugin.
    If no provider is active, no commands are registered.

    Looks for a ``register_cli(subparser)`` function in the active
    plugin's ``cli.py``.  Returns a list of at most one dict with
    keys: ``name``, ``help``, ``description``, ``setup_fn``,
    ``handler_fn``.

    This is a lightweight scan — it only imports ``cli.py``, not the
    full plugin module.  Safe to call during argparse setup before
    any provider is loaded.
    zcli.pyr5   z.cliregister_cliNzManage z memory pluginr   r   r   r   _commandhoncho_command)r   helpr   setup_fn
handler_fnpluginz-Failed to scan CLI for memory plugin '%s': %s)r   r   r{   r   r:   r;   r>   r?   r@   r+   rB   rA   rC   rK   callabler   r   r   r   r   r   r.   r/   )r    active_provider
plugin_dircli_filerO   cli_modrS   r~   	help_textr   r$   r   r%   r&   r#   r   r2   s                    r)   discover_plugin_cli_commandsr      s   " G%%'' 133O  %6J H$H?? 9O999K.Z#+%%k+.GG>99S]] D  t{ n55d;;G'.CK$K##G,,,w==%% 	N >o===	.	 
		)__ 3>>!,,2D3 3 3 3 3 3 3 3 3 3 3 3 3 3 3xxr22 ' $I"&K    W&B&B&BDII >W&6== 	 	#&$$%
 
 	 	 	 	  Z Z ZDoWXYYYYYYYYZ Nso   2AH A)H 5!H F6 *FF6 FF6 FF6 5H 6
G H GAH 
H8H33H8)r   r	   )r   r+   r   r,   )r1   r   r   r,   )r   ru   )r   r|   )rt   
__future__r   r>   importlib.utilloggingr:   pathlibr   typingr   r   r   	getLoggerrq   r.   r<   r=   r   r*   r3   r   rH   r{   r   rg   rc   r)   <module>r      sB   " # " " " " "          



       ( ( ( ( ( ( ( ( ( (		8	$	$d8nn+ + + + +\   *a a a aH       (   S S S S S Src   