§
    ‰eîi8  ã                  óø   — 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d!d„Zd"d„Zd#d„Zd$d„Z G d„ d¦  «        Zd%d„Zd&d„ZdS )'aÌ  Memory provider plugin discovery.

Scans two directories for memory provider plugins:

1. Bundled providers: ``plugins/memory/<name>/`` (shipped with hermes-agent)
2. User-installed providers: ``$HERMES_HOME/plugins/<name>/``

Each subdirectory must contain ``__init__.py`` with a class implementing
the MemoryProvider ABC.  On name collisions, bundled providers take
precedence.

Only ONE provider 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("mnemosyne")  # MemoryProvider instance
é    )ÚannotationsN)ÚPath)ÚListÚOptionalÚTupleÚreturnúOptional[Path]c                 ó|   — 	 ddl m}   | ¦   «         dz  }|                     ¦   «         r|ndS # t          $ r Y dS w xY w)z8Return ``$HERMES_HOME/plugins/`` or None if unavailable.r   )Úget_hermes_homeÚpluginsN)Úhermes_constantsr   Úis_dirÚ	Exception)r   Úds     ú9/home/div/.hermes/hermes-agent/plugins/memory/__init__.pyÚ_get_user_plugins_dirr   (   sd   € ðØ4Ð4Ð4Ð4Ð4Ð4ØˆOÑÔ 	Ñ)ˆØ—H’H‘J”JÐ(ˆqˆq DÐ(øÝð ð ð Øˆtˆtðøøøs   ‚*- ­
;º;Úpathr   Úboolc                ó¨   — | dz  }|                      ¦   «         sdS 	 |                     d¬¦  «        dd…         }d|v pd|v S # t          $ r Y dS w xY w)	uÌ   Heuristic: does *path* look like a memory provider plugin?

    Checks for ``register_memory_provider`` or ``MemoryProvider`` in the
    ``__init__.py`` source.  Cheap text scan â€” no import needed.
    ú__init__.pyFÚreplace)ÚerrorsNi    Úregister_memory_providerÚMemoryProvider)ÚexistsÚ	read_textr   )r   Ú	init_fileÚsources      r   Ú_is_memory_provider_dirr   2   sƒ   € ð �}Ñ$€IØ×ÒÑÔð ØˆuðØ×$Ò$¨IÐ$Ñ6Ô6°u¸°uÔ=ˆØ)¨VÐ3ÐQÐ7GÈ6Ð7QÐQøÝð ð ð Øˆuˆuðøøøs   �%A Á
AÁAúList[Tuple[str, Path]]c                 óÖ  — t          ¦   «         } g }t                               ¦   «         r¦t          t                               ¦   «         ¦  «        D ]}|                     ¦   «         r|j                             d¦  «        rŒ1|dz                       ¦   «         sŒI|                      |j        ¦  «         | 	                    |j        |f¦  «         Œ€t          ¦   «         }|r‰t          |                     ¦   «         ¦  «        D ]g}|                     ¦   «         r|j                             d¦  «        rŒ1|j        | v rŒ;t          |¦  «        sŒK| 	                    |j        |f¦  «         Œh|S )zÈYield ``(name, path)`` for all discovered provider directories.

    Scans bundled first, then user-installed.  Bundled takes precedence
    on name collisions (first-seen wins via ``seen`` set).
    )Ú_ú.r   )ÚsetÚ_MEMORY_PLUGINS_DIRr   ÚsortedÚiterdirÚnameÚ
startswithr   ÚaddÚappendr   r   )ÚseenÚdirsÚchildÚuser_dirs       r   Ú_iter_provider_dirsr0   B   sh  € õ ‘”€DØ#%€Dõ ×!Ò!Ñ#Ô#ð -ÝÕ/×7Ò7Ñ9Ô9Ñ:Ô:ð 	-ð 	-ˆEØ—<’<‘>”>ð  U¤Z×%:Ò%:¸:Ñ%FÔ%Fð ØØ˜MÑ)×1Ò1Ñ3Ô3ð ØØ�HŠH�U”ZÑ Ô Ð Ø�KŠK˜œ UÐ+Ñ,Ô,Ð,Ð,õ %Ñ&Ô&€HØð -Ý˜H×,Ò,Ñ.Ô.Ñ/Ô/ð 	-ð 	-ˆEØ—<’<‘>”>ð  U¤Z×%:Ò%:¸:Ñ%FÔ%Fð ØØŒz˜TÐ!Ð!ØÝ*¨5Ñ1Ô1ð ØØ�KŠK˜œ UÐ+Ñ,Ô,Ð,Ð,à€Kó    r(   Ústrc                óè   — t           | z  }|                     ¦   «         r|dz                       ¦   «         r|S t          ¦   «         }|r*|| z  }|                     ¦   «         rt	          |¦  «        r|S dS )z^Resolve a provider name to its directory.

    Checks bundled first, then user-installed.
    r   N)r%   r   r   r   r   )r(   Úbundledr/   Úusers       r   Úfind_provider_dirr6   d   sƒ   € õ " DÑ(€GØ‡~‚~ÑÔð ˜W }Ñ4×<Ò<Ñ>Ô>ð Øˆå$Ñ&Ô&€HØð Ø˜$‰ˆØ�;Š;‰=Œ=ð 	Õ4°TÑ:Ô:ð 	ØˆKØˆ4r1   úList[Tuple[str, str, bool]]c                 óè  — g } t          ¦   «         D ]à\  }}d}|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|  	                    |||f¦  «         Œá| S )zÂScan bundled and user-installed directories for available providers.

    Returns list of (name, description, is_available) tuples.
    Bundled providers take precedence on name collisions.
    Ú úplugin.yamlr   NÚdescriptionTF)
r0   r   ÚyamlÚopenÚ	safe_loadÚgetr   Ú_load_provider_from_dirÚis_availabler+   )
Úresultsr(   r.   ÚdescÚ	yaml_filer<   ÚfÚmetaÚ	availableÚproviders
             r   Údiscover_memory_providersrI   z   s}  € ð €Gå*Ñ,Ô,ð 0ð 0‰ˆˆeàˆØ˜MÑ)ˆ	Ø×ÒÑÔð 	ðØ���Ý˜)‘_”_ð 3¨ØŸ>š>¨!Ñ,Ô,Ð2°�Dð3ð 3ð 3ñ 3ô 3ð 3ð 3ð 3ð 3ð 3ð 3øøøð 3ð 3ð 3ð 3à—x’x ¨rÑ2Ô2��øÝð ð ð Ø�ðøøøð ˆ	ð	Ý.¨uÑ5Ô5ˆHØð "Ø$×1Ò1Ñ3Ô3�	�	à!�	øøÝð 	ð 	ð 	ØˆIˆIˆIð	øøøð 	�Š˜˜d IÐ.Ñ/Ô/Ð/Ð/à€NsG   ²BÁA)ÁBÁ)A-	Á-BÁ0A-	Á1BÂ
BÂBÂ(CÃCÃCúOptional['MemoryProvider']c                ó(  — t          | ¦  «        }|st                               d| ¦  «         dS 	 t          |¦  «        }|r|S t                               d| ¦  «         dS # t
          $ r'}t                               d| |¦  «         Y d}~dS d}~ww xY w)a'  Load and return a MemoryProvider instance by name.

    Checks both bundled (``plugins/memory/<name>/``) and user-installed
    (``$HERMES_HOME/plugins/<name>/``) directories.  Bundled takes
    precedence on name collisions.

    Returns None if the provider is not found or fails to load.
    z9Memory provider '%s' not found in bundled or user pluginsNz:Memory provider '%s' loaded but no provider instance foundz'Failed to load memory provider '%s': %s)r6   ÚloggerÚdebugr@   Úwarningr   )r(   Úprovider_dirrH   Úes       r   Úload_memory_providerrQ   Ÿ   s±   € õ % TÑ*Ô*€LØð Ý�ŠÐPÐRVÑWÔWÐWØˆtðÝ*¨<Ñ8Ô8ˆØð 	ØˆOÝ�ŠÐSÐUYÑZÔZÐZØˆtøÝð ð ð Ý�ŠÐ@À$ÈÑJÔJÐJØˆtˆtˆtˆtˆtøøøøðøøøs   °A  ÁA  Á 
BÁ*BÂBrO   c                ó  — | j         }t          | j        v p| j        t          k    }|rd|› �nd|› �}| dz  }|                     ¦   «         sdS |t
          j        v rt
          j        |         }�n¶dD ]è}|t
          j        vrØt          t          ¦  «        j        }|dk    r|j        }|dz  }|                     ¦   «         r™t          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r¬t          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} t9          |¦  «        D ]Y}t;          ||d¦  «        }t=          |t>          ¦  «        r1tA          ||¦  «        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.ú_hermes_user_memory.r   N)r   zplugins.memoryr   )Úsubmodule_search_locationsz*.pyr#   zFailed to load submodule %s: %szFailed to exec_module %s: %sÚregisterzregister() failed for %s: %sr   )r   )!r(   r%   ÚparentsÚparentr   ÚsysÚmodulesr   Ú__file__Ú	importlibÚutilÚspec_from_file_locationr2   Úmodule_from_specÚloaderÚexec_moduler   ÚglobÚstemrL   rM   ÚpopÚhasattrÚ_ProviderCollectorrV   rH   Úagent.memory_providerr   ÚdirÚgetattrÚ
isinstanceÚtypeÚ
issubclass)rO   r(   Ú_is_bundledÚmodule_namer   ÚmodrX   Úparent_pathÚparent_initÚspecÚ
parent_modÚsub_fileÚsub_nameÚfull_sub_nameÚsub_specÚsub_modrP   Ú	collectorr   Ú	attr_nameÚattrs                        r   r@   r@   ¸   s¶  € ð Ô€Dõ &¨Ô)=Ð=ÐkÀÔATÕXkÒAk€KØ.9Ð\Ð* DÐ*Ð*Ð*Ð?\ÐVZÐ?\Ð?\€KØ˜}Ñ,€Ià×ÒÑÔð Øˆtð •c”kÐ!Ð!ÝŒk˜+Ô&ˆ‰ð 4ð 	!ð 	!ˆFØ�Sœ[Ð(Ð(Ý"¥8™nœnÔ3�Ø˜YÒ&Ð&Ø"-Ô"4�KØ)¨MÑ9�Ø×%Ò%Ñ'Ô'ð !Ý$œ>×AÒAØ¥ KÑ 0Ô 0Ý47¸Ñ4DÔ4DÐ3Eð Bñ ô �Dð ð !Ý%.¤^×%DÒ%DÀTÑ%JÔ%J˜
Ø.8�œ FÑ+ð!Ø œK×3Ò3°JÑ?Ô?Ð?Ð?øÝ(ð !ð !ð !Ø ˜Dð!øøøøõ Œ~×5Ò5Ø�˜Y™œÝ(+¨LÑ(9Ô(9Ð':ð 6ñ 
ô 
ˆð ð 	Ø�4åŒn×-Ò-¨dÑ3Ô3ˆØ#&�Œ�KÑ ð %×)Ò)¨&Ñ1Ô1ð 	Zð 	ZˆHØŒ} Ò-Ð-ØØ”}ˆHØ*Ð7Ð7¨XÐ7Ð7ˆMØ¥C¤KÐ/Ð/Ý$œ>×AÒAØ!¥3 x¡=¤=ñô �ð ð ZÝ'œn×=Ò=¸hÑGÔG�GØ18•C”K Ñ.ðZØ œ×3Ò3°GÑ<Ô<Ð<Ð<øÝ$ð Zð Zð ZÝŸšÐ%FÈÐWXÑYÔYÐYÐYÐYÐYÐYÐYøøøøðZøøøøð	ØŒK×#Ò# CÑ(Ô(Ð(Ð(øÝð 	ð 	ð 	Ý�LŠLÐ7¸ÀaÑHÔHÐHÝŒK�OŠO˜K¨Ñ.Ô.Ð.Ø�4�4�4�4�4øøøøð	øøøõ ˆs�JÑÔð BÝ&Ñ(Ô(ˆ	ð	BØ�LŠL˜Ñ#Ô#Ð#ØÔ!ð *Ø Ô)Ð)ð*øåð 	Bð 	Bð 	BÝ�LŠLÐ7¸¸qÑAÔAÐAÐAÐAÐAÐAÐAøøøøð	Bøøøð 5Ð4Ð4Ð4Ð4Ð4Ý˜‘X”Xð ð ˆ	Ý�s˜I tÑ,Ô,ˆÝ�t�TÑ"Ô"ð 	¥z°$¸Ñ'GÔ'Gð 	Ø Ð.Ð.ðØ�t‘v”v���øÝð ð ð Ø�ðøøøøð ˆ4sl   Ä.E	Å	
EÅEÉ&JÊ
J1ÊJ,Ê,J1Ê6K Ë
L"Ë<LÌL"Í"M( Í(
NÍ2NÎNÏ-	O9Ï9
PÐPc                  ó0   — e Zd ZdZd„ Zd„ Zd„ Zd„ Zd„ ZdS )rf   zAFake plugin context that captures register_memory_provider calls.c                ó   — d | _         d S ©N©rH   )Úselfs    r   Ú__init__z_ProviderCollector.__init__"  s   € ØˆŒˆˆr1   c                ó   — || _         d S r~   r   )r€   rH   s     r   r   z+_ProviderCollector.register_memory_provider%  s   € Ø ˆŒˆˆr1   c                ó   — d S r~   © ©r€   ÚargsÚkwargss      r   Úregister_toolz _ProviderCollector.register_tool)  ó   € Øˆr1   c                ó   — d S r~   r„   r…   s      r   Úregister_hookz _ProviderCollector.register_hook,  r‰   r1   c                ó   — d S r~   r„   r…   s      r   Úregister_cli_commandz'_ProviderCollector.register_cli_command/  r‰   r1   N)	Ú__name__Ú
__module__Ú__qualname__Ú__doc__r�   r   rˆ   r‹   r�   r„   r1   r   rf   rf     se   € € € € € ØKÐKðð ð ð!ð !ð !ðð ð ðð ð ðð ð ð ð r1   rf   ú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ÚmemoryrH   N)Úhermes_cli.configr”   r?   r   )r”   Úconfigs     r   Ú_get_active_memory_providerr˜   3  sm   € ðØ1Ð1Ð1Ð1Ð1Ð1Ø�‘”ˆØ�zŠz˜( BÑ'Ô'×+Ò+¨JÑ7Ô7Ð?¸4Ð?øÝð ð ð Øˆtˆtðøøøs   ‚:= ½
AÁ
Aú
List[dict]c            	     ó¬  — g } t                                ¦   «         s| S t          ¦   «         }|s| S t          |¦  «        }|s| S |dz  }|                     ¦   «         s| S t           |j        v p|j        t           k    }|rd|› d�nd|› d�}	 |t          j        v rt          j        |         }n€t          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&}t0                               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.pyrS   z.clirT   Úregister_cliNzManage z memory pluginr9   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˜   r6   r   rW   rX   rY   rZ   r\   r]   r^   r2   r`   r_   ra   ri   Úcallabler<   r=   r>   r?   r   r+   rL   rM   )rB   Úactive_providerÚ
plugin_dirÚcli_filerm   rn   Úcli_modrr   r›   Ú	help_textr;   rD   r<   rE   rF   rC   r    rP   s                     r   Údiscover_plugin_cli_commandsr¨   B  s/  € ð" €GÝ×%Ò%Ñ'Ô'ð Øˆå1Ñ3Ô3€OØð Øˆõ # ?Ñ3Ô3€JØð Øˆà˜HÑ$€HØ�?Š?ÑÔð Øˆå%¨Ô);Ð;Ðg¸zÔ?PÕTgÒ?g€KØ=HÐzÐ9 OÐ9Ð9Ð9Ð9ÐNzÐetÐNzÐNzÐNz€Kð.Zà�#œ+Ð%Ð%Ý”k +Ô.ˆGˆGå”>×9Ò9Ø�S ™]œ]ñô ˆDð ð ˜tœ{ð Ø�Ý”n×5Ò5°dÑ;Ô;ˆGØ'.�CŒK˜Ñ$ØŒK×#Ò# GÑ,Ô,Ð,å˜w¨¸Ñ=Ô=ˆÝ˜Ñ%Ô%ð 	ØˆNð >˜oÐ=Ð=Ð=ˆ	ØˆØ Ñ.ˆ	Ø×ÒÑÔð 
	ð	Ø���Ý˜)‘_”_ð 3¨ØŸ>š>¨!Ñ,Ô,Ð2°�Dð3ð 3ð 3ñ 3ô 3ð 3ð 3ð 3ð 3ð 3ð 3øøøð 3ð 3ð 3ð 3à—x’x ¨rÑ2Ô2�Øð 'Ø $�IØ"&�KøøÝð ð ð Ø�ðøøøõ ˜W¨Ð&BÐ&BÐ&BÀDÑIÔIð >Ý˜WÐ&6¸Ñ=Ô=ð 	ð 	�ŠØ#ØØ&Ø$Ø$Ø%ð
ð 
ñ 	ô 	ð 	ð 	øõ ð Zð Zð ZÝ�ŠÐDÀoÐWXÑYÔYÐYÐYÐYÐYÐYÐYøøøøðZøøøð €Nso   ÂAH! Ã$A)H! Å!H! Å0G ÆF'ÆG Æ'F+Æ+G Æ.F+Æ/G ÇH! Ç
GÇH! ÇGÇAH! È!
IÈ+IÉI)r   r	   )r   r   r   r   )r   r    )r(   r2   r   r	   )r   r7   )r(   r2   r   rJ   )rO   r   r   rJ   )r   r’   )r   r™   )r‘   Ú
__future__r   r\   Úimportlib.utilÚloggingrY   Úpathlibr   Útypingr   r   r   Ú	getLoggerrŽ   rL   r[   rX   r%   r   r   r0   r6   rI   rQ   r@   rf   r˜   r¨   r„   r1   r   ú<module>r¯      s“  ððð ð* #Ð "Ð "Ð "Ð "Ð "à Ð Ð Ð Ø Ð Ð Ð Ø €€€Ø 
€
€
€
Ø Ð Ð Ð Ð Ð Ø (Ð (Ð (Ð (Ð (Ð (Ð (Ð (Ð (Ð (à	ˆÔ	˜8Ñ	$Ô	$€à�d˜8‘n”nÔ+Ð ðð ð ð ðð ð ð ð ð ð ð ðDð ð ð ð,"ð "ð "ð "ðJð ð ð ð2dð dð dð dðNð ð ð ð ñ ô ð ð(ð ð ð ðTð Tð Tð Tð Tð Tr1   