Ë
    áß²j¥'  ã                  ó\  — 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m	Z	 ddl
mZ ddlmZmZmZmZmZ  ej$                  e«      Zdd„Zdd	dd
œ	 	 	 	 	 dd„ZdZdZ eh d£«      Zdd„Z ed¬«       G d„ d«      «       Z ej:                  dej<                  «      Zdd„Z  G d„ de«      Z!y)aH  Abstract base class for pluggable memory providers.

Plugins ship in ``plugins/memory/<name>/``, activated via ``memory.provider`` (ONE external
provider at a time). Lifecycle, driven by MemoryManager: initialize -> system_prompt_block /
prefetch / sync_turn per turn -> tool dispatch -> shutdown, plus optional ``on_*`` hooks.
é    )ÚannotationsN)ÚABCÚabstractmethod)Ú	dataclass)ÚAnyÚCallableÚDictÚListÚOptionalc                ó:   ‡ ‡— t        j                  «       Šˆˆ fd„S )a  Bind ``fn`` to the CALLER's contextvars for another thread/executor. Profile isolation
    is a ContextVar-scoped HERMES_HOME override plus the per-turn secret scope; a worker started
    with an empty context silently lands on the default profile (or fails closed on secrets).c                 ó0   •—  ‰j                   ‰g| ¢­i |¤ŽS ©N)Úrun)ÚargsÚkwargsÚctxÚfns     €€ú:/home/ubuntu/.hermes/hermes-agent/agent/memory_provider.pyú<lambda>zctx_bound.<locals>.<lambda>   s   ø€  7 3§7¡7¨2Ð#?°Ò#?¸Ñ#?€ ó    )ÚcontextvarsÚcopy_context)r   r   s   `@r   Ú	ctx_boundr      s   ù€ ô ×
"Ñ
"Ó
$€CÜ?Ð?r   T© )Údaemonr   r   c               óH   — t        j                  t        | «      ||||¬«      S )z¸Unstarted thread running *target* under the spawner's contextvars (see :func:`ctx_bound`).
    Every memory-provider background job (prefetch, sync, writer loops) must go through this.)Útargetr   r   Únamer   )Ú	threadingÚThreadr   )r   r   r   r   r   s        r   Úspawn_context_threadr!      s$   € ô ×Ñ¤9¨VÓ#4¸4ÈÐUYÐbhÔiÐir   é   u   ðŸ§ >   úbuilt-inÚ ÚnoneÚbuiltinÚdefaultc                ód   — t        | xs d«      j                  «       j                  «       t        v S )zXTrue when ``memory.provider`` selects the built-in store rather than an external plugin.r$   )ÚstrÚstripÚlowerÚCORE_MEMORY_PROVIDER_SENTINELS)r   s    r   Úis_core_memory_providerr-   /   s(   € äˆtŠz�r‹?× Ñ Ó"×(Ñ(Ó*Ô.LÐLÐLr   )Úfrozenc                  ó4   — e Zd ZU dZded<   ded<   eZded<   y)ÚRecallStatuszçWhat the last prefetch injected, for the deterministic recall indicator
    (``MemoryManager.describe_recall``). ``count == 0`` means content without a
    discrete count (e.g. a synthesized reflect answer) and renders generically.r)   Úprovider_labelÚintÚcountÚglyphN)Ú__name__Ú
__module__Ú__qualname__Ú__doc__Ú__annotations__ÚINDICATOR_GLYPHr4   r   r   r   r0   r0   4   s   … ñSð ÓØƒJØ €Eˆ3Ô r   r0   zí^(yes|no|ok|okay|sure|thanks|thank you|y|n|yep|nope|yeah|nah|hi|hey|hello|yo|sup|continue|go ahead|do it|proceed|got it|cool|nice|great|done|next|lgtm|k)[\s!?.:;,"'~\u2018\u2019\u201c\u201d\u2014\u2013\u2026()\[\]{}<>*&^%$#@!+=`\u00a0]*$c                óŽ   — | xs dj                  «       }|r|j                  d«      ryt        t        j	                  |«      «      S )zªTrue for empty input, slash commands and bare greetings/acknowledgements (skipping
    recall saves a round-trip and keeps stale context from derailing one-word replies).r$   ú/T)r*   Ú
startswithÚboolÚTRIVIAL_PROMPT_REÚmatch)ÚtextÚstrippeds     r   Úis_trivial_promptrC   K   s@   € ð ’
˜×!Ñ!Ó#€HÙ�x×*Ñ*¨3Ô/ØÜÔ!×'Ñ'¨Ó1Ó2Ð2r   c                  óF  — e Zd ZdZdZeed d„«       «       Zed!d„«       Zed"d„«       Z	d d„Z
d d„Zdd	œd#d
„Zdd	œd$d„Zd%d„Zddddœ	 	 	 	 	 	 	 	 	 	 	 d&d„Zed'd„«       Zd(d„Zd)d„Zd*d„Zd+d„Zd,d„Zddddœ	 	 	 	 	 	 	 	 	 d-d„Zd.d„Zddœd/d„Zd'd„Zd0d„Zd1d2d„Zd3d„Zy)4ÚMemoryProviderz)Abstract base class for memory providers.é   c                 ó   — y)zKShort identifier for this provider (e.g. 'builtin', 'honcho', 'hindsight').Nr   ©Úselfs    r   r   zMemoryProvider.name[   ó   � r   c                 ó   — y)zYConfigured, credentialed and ready? Gates activation; check config/deps only, no network.Nr   rH   s    r   Úis_availablezMemoryProvider.is_availableb   rJ   r   c                 ó   — y)u®  Initialize once at agent startup (connections, resources, threads).

        kwargs always include ``hermes_home`` (profile-scoped storage; never hardcode
        ``~/.hermes``) and ``platform``; may include ``agent_context`` ("primary" |
        "subagent" | "cron" | "flush" â€” skip writes for non-primary contexts),
        ``agent_identity``, ``agent_workspace``, ``parent_session_id``, ``user_id``, ``user_id_alt``.
        Nr   )rI   Ú
session_idr   s      r   Ú
initializezMemoryProvider.initializef   rJ   r   c                 ó   — y)z[User-facing hint for the "provider unavailable" warning (``initialize()`` never runs then).r$   r   rH   s    r   Úunavailable_reasonz!MemoryProvider.unavailable_reasonp   ó   € àr   c                 ó   — y)zZSTATIC system-prompt text; "" to skip. Recalled context goes through prefetch(), not here.r$   r   rH   s    r   Úsystem_prompt_blockz"MemoryProvider.system_prompt_blockt   rR   r   r$   )rN   c                ó   — y)u´   Formatted recall context for the upcoming turn ("" if none). Must be fast â€” recall
        in the background and return cached results; ``session_id`` scopes concurrent sessions.r$   r   ©rI   ÚqueryrN   s      r   ÚprefetchzMemoryProvider.prefetchx   s   € ð r   c                ó   — y)zLQueue a background recall after each turn; prefetch() consumes it next turn.Nr   rV   s      r   Úqueue_prefetchzMemoryProvider.queue_prefetch}   rJ   r   c                 ó   — y)z‘What the most recent :meth:`prefetch` injected (``None`` = no indicator). Must reflect
        only the LAST prefetch, never a stale prior count.Nr   rH   s    r   Úrecall_statuszMemoryProvider.recall_status€   s   € ð r   N)rN   ÚmessagesÚturn_authorc                ó   — y)záPersist a completed turn (non-blocking). ``messages`` is the OpenAI-style list so far.
        ``turn_author`` (``{"id", "name", "is_bot"}``) is who wrote the user side; the manager sends it only to signatures that accept it.Nr   )rI   Úuser_contentÚassistant_contentrN   r]   r^   s         r   Ú	sync_turnzMemoryProvider.sync_turn…   rJ   r   c                 ó   — y)zTOpenAI function-calling schemas ({"name", "description", "parameters"}); [] if none.Nr   rH   s    r   Úget_tool_schemaszMemoryProvider.get_tool_schemas�   rJ   r   c                ó8   — t        d| j                  › d|› �«      ‚)z?Handle one of this provider's tools; must return a JSON string.z	Provider z does not handle tool )ÚNotImplementedErrorr   )rI   Ú	tool_namer   r   s       r   Úhandle_tool_callzMemoryProvider.handle_tool_call‘   s   € ä! I¨d¯i©i¨[Ð8NÈyÈkÐ"ZÓ[Ð[r   c                 ó   — y)u3   Clean shutdown â€” flush queues, close connections.Nr   rH   s    r   ÚshutdownzMemoryProvider.shutdown•   rJ   r   c                 ó   — y)aG  Per-turn tick. kwargs may include remaining_tokens, model, platform, tool_count, author_id, author_name,
        author_is_bot. The author trio names who wrote THIS turn (None, None, False without one): a shared session
        carries several participants, so a provider keying durable state on identity must read it per turn.Nr   )rI   Úturn_numberÚmessager   s       r   Úon_turn_startzMemoryProvider.on_turn_startš   rJ   r   c                ó   — i S )a9  Identity-mapping values that must bust a cached gateway agent when they change (writer identity, alias
        tables, session-name prefixing). Provider-namespaced keys, JSON-serializable values. The gateway calls this
        on an uninitialized instance on every inbound message, so keep it cheap and read-only.r   rH   s    r   Úidentity_signaturez!MemoryProvider.identity_signatureŸ   s	   € ð ˆ	r   c                 ó   — y)zQEnd-of-session extraction; fires only at real session boundaries, never per-turn.Nr   ©rI   r]   s     r   Úon_session_endzMemoryProvider.on_session_end¥   rJ   r   F)Úparent_session_idÚresetÚrewoundc                ó   — y)a<  session_id reassigned mid-process (/resume, /branch, /reset, /new, compression)
        without teardown: rebind per-session state so later writes land in the right record.
        ``reset`` is True only for a genuinely new conversation (flush buffers); ``rewound``:
        same id but the transcript was truncated.Nr   )rI   Únew_session_idrt   ru   rv   r   s         r   Úon_session_switchz MemoryProvider.on_session_switch¨   rJ   r   c                 ó   — y)zWExtract insights from ``messages`` about to be compressed, fed into the summary prompt.r$   r   rr   s     r   Úon_pre_compresszMemoryProvider.on_pre_compress°   rR   r   )Úchild_session_idc                ó   — y)zYPARENT-side observation of a completed delegation (the subagent has no provider session).Nr   )rI   ÚtaskÚresultr|   r   s        r   Úon_delegationzMemoryProvider.on_delegation´   rJ   r   c                ó   — g S )aL  Setup fields for ``hermes memory setup`` ([] if none): ``key``, ``description``,
        optional ``secret`` (goes to .env), ``required``, ``default``, ``choices``, ``type``
        (text | integer | number | boolean), ``minimum``/``maximum``/``step``, ``url``,
        ``env_var`` (explicit secret env var; default auto-generated).r   rH   s    r   Úget_config_schemaz MemoryProvider.get_config_schema·   s	   € ð
 ˆ	r   c                 ó   — y)z¬Write non-secret setup ``values`` to the provider's native config. Plugins MUST either
        override this or use only env vars (every schema field carrying ``env_var``).Nr   )rI   ÚvaluesÚhermes_homes      r   Úsave_configzMemoryProvider.save_config¾   rJ   r   c                 ó   — y)z²Mirror a built-in memory-tool write (``action``: add | replace | remove; ``target``:
        memory | user; ``metadata``: provenance such as write_origin, session_id, tool_name).Nr   )rI   Úactionr   ÚcontentÚmetadatas        r   Úon_memory_writezMemoryProvider.on_memory_writeÂ   rJ   r   c                ó   — g S )z¶Absolute paths of provider state OUTSIDE HERMES_HOME for ``hermes backup``/``import``
        (paths outside the home dir are skipped). MUST work without ``initialize()`` or network.r   rH   s    r   Úbackup_pathszMemoryProvider.backup_pathsÆ   s	   € ð ˆ	r   )Úreturnr)   )rŽ   r>   )rN   r)   rŽ   ÚNone)rW   r)   rN   r)   rŽ   r)   )rW   r)   rN   r)   rŽ   r�   )rŽ   zOptional[RecallStatus])r`   r)   ra   r)   rN   r)   r]   zOptional[List[Dict[str, Any]]]r^   úOptional[Dict[str, Any]]rŽ   r�   )rŽ   úList[Dict[str, Any]])rg   r)   r   úDict[str, Any]rŽ   r)   )rŽ   r�   )rl   r2   rm   r)   rŽ   r�   )rŽ   r’   )r]   r‘   rŽ   r�   )
rx   r)   rt   r)   ru   r>   rv   r>   rŽ   r�   )r]   r‘   rŽ   r)   )r~   r)   r   r)   r|   r)   rŽ   r�   )r„   r’   r…   r)   rŽ   r�   r   )
rˆ   r)   r   r)   r‰   r)   rŠ   r�   rŽ   r�   )rŽ   z	List[str])r5   r6   r7   r8   Ú#pre_compress_checkpoint_api_versionÚpropertyr   r   rL   rO   rQ   rT   rX   rZ   r\   rb   rd   rh   rj   rn   rp   rs   ry   r{   r€   r‚   r†   r‹   r�   r   r   r   rE   rE   T   sW  „ Ù3ð +,Ð'àØòZó ó ðZð
 òhó ðhð òó ðóóð 9;õ ð
 ?Aõ [óð ÈØ04ñNØðNØ47ðNàðNà(FðNð .ðNð 
ó	Nð òcó ðcó\óBó
oó
ó`ð @BÐQVÐhmñ5Ø!ð5Ø9<ð5ØJNð5Øaeð5à	ó5óð PRõ hóóYôaôr   rE   )r   úCallable[..., Any]rŽ   r•   )r   r•   r   r)   r   r>   r   Útupler   r�   rŽ   zthreading.Thread)r   úOptional[str]rŽ   r>   )rA   r—   rŽ   r>   )"r8   Ú
__future__r   r   ÚloggingÚrer   Úabcr   r   Údataclassesr   Útypingr   r   r	   r
   r   Ú	getLoggerr5   Úloggerr   r!   Ú#PRE_COMPRESS_CHECKPOINT_API_VERSIONr:   Ú	frozensetr,   r-   r0   ÚcompileÚ
IGNORECASEr?   rC   rE   r   r   r   ú<module>r¤      sâ   ðñõ #ã Û Û 	Û ß #Ý !ß 6Õ 6à	ˆ×	Ñ	˜8Ó	$€ó@ð SWØ')ÈdñjØ$ðjØ3KðjØWgójð '(Ð #ð €ñ "+Ò+YÓ!ZÐ óMñ
 �$Ô÷!ð !ó ð!ð �B—J‘Jðgð ‡M�MóÐ ó3ôu�Sõ ur   