
    i7                    "   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Zddlm	Z	m
Z
mZ ddlmZ ddlmZ  ej        e          ZdZdZd$dZdddi g ddZddddddddddddddgddZdddddddidgddZ G d  d!e          Zd%d#ZdS )&u  Mem0 memory plugin — MemoryProvider interface.

Server-side LLM fact extraction, semantic search with reranking, and
automatic deduplication via the Mem0 Platform API.

Original PR #2933 by kartik-mem0, adapted to MemoryProvider ABC.

Config via environment variables:
  MEM0_API_KEY       — Mem0 Platform API key (required)
  MEM0_USER_ID       — User identifier (default: hermes-user)
  MEM0_AGENT_ID      — Agent identifier (default: hermes)

Or via $HERMES_HOME/mem0.json.
    )annotationsN)AnyDictList)MemoryProvider)
tool_error   x   returndictc                    ddl m}  t          j                            dd          t          j                            dd          t          j                            dd          d	d
d} |             dz  }|                                rk	 t          j        |                    d                    }|	                    d |
                                D                        n# t          $ r Y nw xY w|S )a+  Load config from env vars, with $HERMES_HOME/mem0.json overrides.

    Environment variables provide defaults; mem0.json (if present) overrides
    individual keys.  This avoids a silent failure when the JSON file exists
    but is missing fields like ``api_key`` that the user set in ``.env``.
    r   )get_hermes_homeMEM0_API_KEY MEM0_USER_IDhermes-userMEM0_AGENT_IDhermesTF)api_keyuser_idagent_idrerankkeyword_search	mem0.jsonzutf-8)encodingc                *    i | ]\  }}||dk    ||S )Nr    ).0kvs      A/home/piyush/.hermes/hermes-agent/plugins/memory/mem0/__init__.py
<dictcomp>z _load_config.<locals>.<dictcomp>=   s2     9 9 9DAqmR a07    )hermes_constantsr   osenvirongetexistsjsonloads	read_textupdateitems	Exception)r   configconfig_pathfile_cfgs       r!   _load_configr2   (   s    100000 :>>."55:>>.-@@JNN?H== F "/##k1K 	z+"7"7"7"I"IJJHMM 9 9HNN,<,< 9 9 9 : : : : 	 	 	D	 Ms   AC% %
C21C2mem0_profileu   Retrieve all stored memories about the user — preferences, facts, project context. Fast, no reranking. Use at conversation start.object)type
propertiesrequired)namedescription
parametersmem0_searchzSearch memories by meaning. Returns relevant facts ranked by similarity. Set rerank=true for higher accuracy on important queries.stringzWhat to search for.)r5   r9   booleanz0Enable reranking for precision (default: false).integerz#Max results (default: 10, max: 50).)queryr   top_kr?   mem0_concludezStore a durable fact about the user. Stored verbatim (no LLM extraction). Use for explicit preferences, corrections, or decisions.
conclusionzThe fact to store.c                      e Zd ZdZd Zed)d            Zd*dZd Zd	 Z	d
 Z
d*dZd Zd Zd+dZd,dZd,dZed-d            Zd)dZddd.dZddd/dZddd0d Zd1d"Zd2d&Zd3d'Zd(S )4Mem0MemoryProviderzEMem0 Platform memory with server-side extraction and semantic search.c                    d | _         d | _        t          j                    | _        d| _        d| _        d| _        d| _        d| _	        t          j                    | _
        d | _        d | _        d| _        d| _        d S )Nr   r   r   Tr   g        )_config_client	threadingLock_client_lock_api_key_user_id	_agent_id_rerank_prefetch_result_prefetch_lock_prefetch_thread_sync_thread_consecutive_failures_breaker_open_untilselfs    r!   __init__zMem0MemoryProvider.__init__z   sz    %N,,%! "'n.. $ %&"#&   r#   r   strc                    dS )Nmem0r   rU   s    r!   r8   zMem0MemoryProvider.name   s    vr#   boolc                b    t                      }t          |                    d                    S )Nr   )r2   r[   r'   )rV   cfgs     r!   is_availablezMem0MemoryProvider.is_available   s%    nnCGGI&&'''r#   c                >   ddl }ddlm}  ||          dz  }i }|                                r4	  |j        |                                          }n# t          $ r Y nw xY w|                    |           |                     |j	        |d                     dS )z'Write config to $HERMES_HOME/mem0.json.r   N)Pathr      )indent)
r)   pathlibr`   r(   r*   r+   r.   r,   
write_textdumps)rV   valueshermes_homer)   r`   r0   existings          r!   save_configzMem0MemoryProvider.save_config   s          d;''+5 	%4:k&;&;&=&=>>   ztz(1===>>>>>s   "A 
A A c                :    dddddddddd	d
dddd
dddddgdgS )Nr   zMem0 Platform API keyTr   zhttps://app.mem0.ai)keyr9   secretr7   env_varurlr   zUser identifierr   )rk   r9   defaultr   zAgent identifierr   r   zEnable reranking for recalltruefalse)rk   r9   ro   choicesr   rU   s    r!   get_config_schemaz$Mem0MemoryProvider.get_config_schema   sf    .EQUcg  uC  La  b  b.?MZZ/AhWW-JW]kqszj{||	
 	
r#   c                    | j         5  | j        | j        cddd           S 	 ddlm}  || j                  | _        | j        cddd           S # t
          $ r t          d          w xY w# 1 swxY w Y   dS )z5Thread-safe client accessor with lazy initialization.Nr   )MemoryClient)r   z3mem0 package not installed. Run: pip install mem0ai)rJ   rG   rZ   ru   rK   ImportErrorRuntimeError)rV   ru   s     r!   _get_clientzMem0MemoryProvider._get_client   s#    	Z 	Z|'|	Z 	Z 	Z 	Z 	Z 	Z 	Z 	ZZ------+|DMBBB|	Z 	Z 	Z 	Z 	Z 	Z 	Z 	Z  Z Z Z"#XYYYZ	Z 	Z 	Z 	Z 	Z 	Z 	Z 	Z 	Z 	Zs"   A0"AA--A00A47A4c                t    | j         t          k     rdS t          j                    | j        k    r	d| _         dS dS )zBReturn True if the circuit breaker is tripped (too many failures).Fr   T)rS   _BREAKER_THRESHOLDtime	monotonicrT   rU   s    r!   _is_breaker_openz#Mem0MemoryProvider._is_breaker_open   s>    %(:::5>t777)*D&5tr#   c                    d| _         d S )Nr   )rS   rU   s    r!   _record_successz"Mem0MemoryProvider._record_success   s    %&"""r#   c                    | xj         dz  c_         | j         t          k    rHt          j                    t          z   | _        t                              d| j         t                     d S d S )N   zVMem0 circuit breaker tripped after %d consecutive failures. Pausing API calls for %ds.)rS   rz   r{   r|   _BREAKER_COOLDOWN_SECSrT   loggerwarningrU   s    r!   _record_failurez"Mem0MemoryProvider._record_failure   sq    ""a'""%);;;'+~'7'7:P'PD$NN-*,B     <;r#   
session_idNonec                V   t                      | _        | j                            dd          | _        |                    d          p| j                            dd          | _        | j                            dd          | _        | j                            dd          | _        d S )	Nr   r   r   r   r   r   r   T)r2   rF   r'   rK   rL   rM   rN   )rV   r   kwargss      r!   
initializezMem0MemoryProvider.initialize   s    #~~((B77 

9--[1A1A)]1[1[))*h??|''$77r#   Dict[str, Any]c                    d| j         iS )uL   Filters for search/get_all — scoped to user only for cross-session recall.r   rL   rU   s    r!   _read_filtersz Mem0MemoryProvider._read_filters   s    4=))r#   c                     | j         | j        dS )u;   Filters for add — scoped to user + agent for attribution.)r   r   )rL   rM   rU   s    r!   _write_filtersz!Mem0MemoryProvider._write_filters   s    =dnEEEr#   responser   listc                    t          | t                    r|                     dg           S t          | t                    r| S g S )uG   Normalize Mem0 API response — v2 wraps results in {"results": [...]}.results)
isinstancer   r'   r   )r   s    r!   _unwrap_resultsz"Mem0MemoryProvider._unwrap_results   sF     h%% 	/<<	2...h%% 	O	r#   c                    d| j          dS )Nz# Mem0 Memory
Active. User: zc.
Use mem0_search to find memories, mem0_conclude to store facts, mem0_profile for a full overview.r   rU   s    r!   system_prompt_blockz&Mem0MemoryProvider.system_prompt_block   s     0!]0 0 0	
r#   r   )r   r?   c                   | j         r4| j                                         r| j                             d           | j        5  | j        }d| _        d d d            n# 1 swxY w Y   |sdS d| S )Ng      @timeoutr   z## Mem0 Memory
)rQ   is_alivejoinrP   rO   )rV   r?   r   results       r!   prefetchzMem0MemoryProvider.prefetch   s      	4T%:%C%C%E%E 	4!&&s&333  	' 	'*F$&D!	' 	' 	' 	' 	' 	' 	' 	' 	' 	' 	' 	' 	' 	' 	'  	2*&***s   AA"%A"c                                                      rd S  fd}t          j        |dd           _         j                                         d S )Nc                    	                                  }                     |                                                     j        d                    }|rOd |D             }j        5  d                    d |D                       _        d d d            n# 1 swxY w Y                                    d S # t          $ r:}
                                 t                              d|           Y d }~d S d }~ww xY w)Nr	   r?   filtersr   r@   c                d    g | ]-}|                     d           |                     d d          .S memoryr   r'   r   rs     r!   
<listcomp>zCMem0MemoryProvider.queue_prefetch.<locals>._run.<locals>.<listcomp>  s5    UUUQQUU8__UQUU8R00UUUr#   
c              3      K   | ]	}d | V  
dS )z- Nr   )r   ls     r!   	<genexpr>zBMem0MemoryProvider.queue_prefetch.<locals>._run.<locals>.<genexpr>  s(      9R9Rq(q((9R9R9R9R9R9Rr#   zMem0 prefetch failed: %s)rx   r   searchr   rN   rP   r   rO   r   r.   r   r   debug)clientr   lineser?   rV   s       r!   _runz/Mem0MemoryProvider.queue_prefetch.<locals>._run   s}   <))++..v}} ..00<	 0= 0 0    SUU'UUUE, S S04		9R9RE9R9R9R0R0R-S S S S S S S S S S S S S S S$$&&&&& < < <$$&&&7;;;;;;;;;<s<   A,C /%B C  B$$C 'B$(C 
D/D  DTzmem0-prefetchtargetdaemonr8   )r}   rH   ThreadrQ   start)rV   r?   r   r   s   ``  r!   queue_prefetchz!Mem0MemoryProvider.queue_prefetch   ss      "" 	F	< 	< 	< 	< 	< 	<$ !* 0TP_ ` ` `##%%%%%r#   user_contentassistant_contentc               &                                      rdS  fd} j        r4 j                                        r j                            d           t	          j        |dd           _         j                                         dS )zESend the turn to Mem0 for server-side fact extraction (non-blocking).Nc                 <   	                                  } ddddg} | j        |fi                                                                   d S # t          $ r:}                                 t                              d|           Y d }~d S d }~ww xY w)Nuserrolecontent	assistantzMem0 sync failed: %s)rx   addr   r   r.   r   r   r   )r   messagesr   r   rV   r   s      r!   _syncz+Mem0MemoryProvider.sync_turn.<locals>._sync  s    
:))++#==(5FGG 
8==t':':'<'<===$$&&&&& : : :$$&&&5q999999999:s   AA 
B!/BB      @r   Tz	mem0-syncr   )r}   rR   r   r   rH   r   r   )rV   r   r   r   r   s   ```  r!   	sync_turnzMem0MemoryProvider.sync_turn  s      "" 	F	: 	: 	: 	: 	: 	: 	:  	0!2!;!;!=!= 	0""3"///%,E$[YYY!!!!!r#   List[Dict[str, Any]]c                *    t           t          t          gS )N)PROFILE_SCHEMASEARCH_SCHEMACONCLUDE_SCHEMArU   s    r!   get_tool_schemasz#Mem0MemoryProvider.get_tool_schemas)  s    ??r#   	tool_nameargsr   c                   |                                  rt          j        ddi          S 	 |                                 }n3# t          $ r&}t          t          |                    cY d }~S d }~ww xY w|dk    r	 |                     |                    | 	                                                    }| 
                                 |st          j        ddi          S d |D             }t          j        d                    |          t          |          d	          S # t          $ r0}|                                  t          d
|           cY d }~S d }~ww xY w|dk    rF|                    dd          }|st          d          S |                    dd          }	t          t!          |                    dd                    d          }
	 |                     |                    || 	                                |	|
                    }| 
                                 |st          j        ddi          S d |D             }t          j        |t          |          d          S # t          $ r0}|                                  t          d|           cY d }~S d }~ww xY w|dk    r|                    dd          }|st          d          S 	  |j        d|dgfi |                                 ddi | 
                                 t          j        ddi          S # t          $ r0}|                                  t          d |           cY d }~S d }~ww xY wt          d!|           S )"Nerrorz[Mem0 API temporarily unavailable (multiple consecutive failures). Will retry automatically.r3   )r   r   zNo memories stored yet.c                d    g | ]-}|                     d           |                     d d          .S r   r   )r   ms     r!   r   z7Mem0MemoryProvider.handle_tool_call.<locals>.<listcomp>=  s5    RRR!%%//Rx,,RRRr#   r   )r   countzFailed to fetch profile: r;   r?   r   z!Missing required parameter: queryr   Fr@   
   2   r   zNo relevant memories found.c                h    g | ]/}|                     d d          |                     dd          d0S )r   r   scorer   )r   r   r   r   s     r!   r   z7Mem0MemoryProvider.handle_tool_call.<locals>.<listcomp>S  s>    fffYZAEE(B$7$7!%%QRBSBSTTfffr#   )r   r   zSearch failed: rA   rB   z&Missing required parameter: conclusionr   r   inferzFact stored.zFailed to store: zUnknown tool: )r}   r)   re   rx   r.   r   rX   r   get_allr   r   r   lenr   r'   minintr   r   r   )rV   r   r   r   r   r   memoriesr   r?   r   r@   r   r-   rB   s                 r!   handle_tool_callz#Mem0MemoryProvider.handle_tool_call,  s2     "" 	:v   	&%%''FF 	& 	& 	&c!ff%%%%%%%%	& &&	C//tGYGYG[G[0\0\]]$$&&& M:x1J&KLLLRRhRRRzTYYu-=-=E

"S"STTT C C C$$&&&!"Aa"A"ABBBBBBBBC -''HHWb))E G!"EFFFXXh..FDHHWb1122B77E9..v}} ..00!	 0= 0 0   $$&&& Q:x1N&OPPPff^efffzec%jj"I"IJJJ 9 9 9$$&&&!"7A"7"7888888889 /)),33J L!"JKKK
;
$<<= ))++      
 $$&&&z8^"<=== ; ; ;$$&&&!"9a"9"9::::::::; 6966777s   A 
A1A,&A1,A1;A&D% "AD% %
E/%EEEA)I2 /I2 2
J,<%J'!J,'J,AL/ /
M)9%M$M)$M)c                    | j         | j        fD ].}|r*|                                r|                    d           /| j        5  d | _        d d d            d S # 1 swxY w Y   d S )Nr   r   )rQ   rR   r   r   rJ   rG   )rV   ts     r!   shutdownzMem0MemoryProvider.shutdownk  s    '):; 	$ 	$A $QZZ\\ $s### 	  	 DL	  	  	  	  	  	  	  	  	  	  	  	  	  	  	  	  	  	 s   AA!AN)r   rX   )r   r[   )r   rX   r   r   )r   r   )r   r   r   r   )r?   rX   r   rX   r   rX   )r?   rX   r   rX   r   r   )r   rX   r   rX   r   rX   r   r   )r   r   )r   rX   r   r   r   rX   r   r   )__name__
__module____qualname____doc__rW   propertyr8   r^   ri   rs   rx   r}   r   r   r   r   r   staticmethodr   r   r   r   r   r   r   r   r   r#   r!   rD   rD   w   s       OO' ' '     X( ( ( (? ? ?
 
 

Z 
Z 
Z   ' ' '  8 8 8 8* * * *F F F F    \
 
 
 
 9; + + + + + + ?A & & & & & &2 Y[ " " " " " "2@ @ @ @=8 =8 =8 =8~           r#   rD   r   c                H    |                      t                                 dS )z*Register Mem0 as a memory provider plugin.N)register_memory_providerrD   )ctxs    r!   registerr   s  s#      !3!5!566666r#   )r   r   r   )r   
__future__r   r)   loggingr%   rH   r{   typingr   r   r   agent.memory_providerr   tools.registryr   	getLoggerr   r   rz   r   r2   r   r   r   rD   r   r   r#   r!   <module>r      s    # " " " " "   				      " " " " " " " " " " 0 0 0 0 0 0 % % % % % %		8	$	$      D 	J $22FF  	D &7LMM(9kll'8]^^
 

 I  $ 	C 8<PQQ
 "N  (y  y  y  y  y  y  y  y x7 7 7 7 7 7r#   