
    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m	Z	 ddl
m
Z
 ddlmZmZ ddlmZ erddlmZ  ej        e          Z e            Ze G d	 d
                      Z G d d          ZdS )z9Honcho-based session management for conversation history.    )annotationsN)	dataclassfield)datetime)AnyTYPE_CHECKING)get_honcho_client)Honchoc                      e Zd ZU dZded<   ded<   ded<   ded<    ee          Zded	<    eej	                  Z
d
ed<    eej	                  Zd
ed<    ee          Zded<   ddZdddZddZdS ) HonchoSessionz
    A conversation session backed by Honcho.

    Provides a local message cache that syncs to Honcho's
    AI-native memory system for user modeling.
    strkeyuser_peer_idassistant_peer_idhoncho_session_id)default_factorylist[dict[str, Any]]messagesr   
created_at
updated_atdict[str, Any]metadatarolecontentkwargsr   returnNonec                    ||t          j                                                    d|}| j                            |           t          j                    | _        dS )z!Add a message to the local cache.)r   r   	timestampN)r   now	isoformatr   appendr   )selfr   r   r   msgs        B/home/piyush/.hermes/hermes-agent/plugins/memory/honcho/session.pyadd_messagezHonchoSession.add_message*   s^     !1133
 
 	
 	S!!!",..    2   max_messagesintc                x    t          | j                  |k    r| j        | d         n| j        }d |D             S )z$Get message history for LLM context.Nc                0    g | ]}|d          |d         dS )r   r   r   r    .0ms     r%   
<listcomp>z-HonchoSession.get_history.<locals>.<listcomp><   s(    MMM6q|<<MMMr'   )lenr   )r#   r)   recents      r%   get_historyzHonchoSession.get_history5   sO     4=!!L00 M<-..)) 	
 NMfMMMMr'   c                D    g | _         t          j                    | _        dS )z"Clear all messages in the session.N)r   r   r    r   r#   s    r%   clearzHonchoSession.clear>   s    ",..r'   N)r   r   r   r   r   r   r   r   )r(   )r)   r*   r   r   r   r   )__name__
__module____qualname____doc____annotations__r   listr   r   r    r   r   dictr   r&   r5   r8   r.   r'   r%   r   r      s          HHH%*U4%@%@%@H@@@@ 5>>>J>>>> 5>>>J>>>>$uT:::H::::	) 	) 	) 	)N N N N N) ) ) ) ) )r'   r   c                     e Zd ZdZ	 	 	 	 dZd[dZed\d            Zd]dZd^dZd_dZ	d`dZ
dadZdbd!Zdcd"Zdbd#Zdbd$Zddd%Zd`d&Zd'Zded(Z	 	 dfdgd.Zdhdid0Zdjd3Zdkd4Zdhdld5Zdmd8Zednd:            Zdod<Zedpd?            Zdd@dqdBZ	 dhdd@drdEZdsdtdFZ dudGZ!dvdIZ"dsdwdJZ#	 	 dxdydNZ$dsdzdPZ%dsd{dRZ&dsd|dTZ'd}d~dWZ(dkdXZ)ddYZ*dS )HonchoSessionManagerz
    Manages conversation sessions using Honcho.

    Runs alongside hermes' existing SQLite state and file-based memory,
    adding persistent cross-session user modeling via Honcho's AI-native memory.
    NhonchoHoncho | Nonecontext_tokens
int | Noneconfig
Any | Noneruntime_user_peer_name
str | Nonec                   || _         || _        || _        || _        i | _        t          j                    | _        i | _        i | _	        |r|j
        nd}|| _        d| _        i | _        t          j                    | _        |r|j        nd| _        |r|j        nd| _        |r|j        nd| _        |r|j        nd| _        |r|j        nd| _        |r|j        nd| _        |r|j        nd| _        |r|j        nd| _        |r|j         nd| _!        |r|j"        nd| _#        d	| _$        d	| _%        |dk    rTtM          j'                    | _$        t          j(        | j)        d
d          | _%        | j%        *                                 d	S d	S )a  
        Initialize the session manager.

        Args:
            honcho: Optional Honcho client. If not provided, uses the singleton.
            context_tokens: Max tokens for context() calls (None = Honcho default).
            config: HonchoClientConfig from global config (provides peer_name, ai_peer,
                    write_frequency, observation, etc.).
            runtime_user_peer_name: Gateway user identity for per-user memory scoping.
        asyncr   lowTiX  directionalia  i'  Nzhoncho-async-writertargetnamedaemon)+_honcho_context_tokens_config_runtime_user_peer_name_cache	threadingRLock_cache_lock_peers_cache_sessions_cachewrite_frequency_write_frequency_turn_counter_context_cacheLock_prefetch_cache_lockdialectic_reasoning_level_dialectic_reasoning_leveldialectic_dynamic_dialectic_dynamicdialectic_max_chars_dialectic_max_charsobservation_mode_observation_modeuser_observe_me_user_observe_meuser_observe_others_user_observe_othersai_observe_me_ai_observe_meai_observe_others_ai_observe_othersmessage_max_chars_message_max_charsdialectic_max_input_chars_dialectic_max_input_chars_async_queue_async_threadqueueQueueThread_async_writer_loopstart)r#   rC   rE   rG   rI   r]   s         r%   __init__zHonchoSessionManager.__init__L   s   " -'=$02$?,,,./1 6<H611 /"# 02$-N$4$4!06AF,,E 	' )/8F$$D 	 +19F&&c 	! (.@F##= 	 AG&Pf&<&<DHN*X&*D*DTX!<B$LF$8$8DJ(T(@(@PT(.9F$$E 	 17AF,,E 	'
 156:g%% %D!*!1.*" " "D
 $$&&&&& &%r'   r   r
   c                D    | j         t                      | _         | j         S )z.Get the Honcho client, initializing if needed.)rS   r	   r7   s    r%   rC   zHonchoSessionManager.honcho   s!     <,..DL|r'   peer_idr   r   c                   | j         5  || j        v r| j        |         cddd           S 	 ddd           n# 1 swxY w Y   | j                            |          }| j         5  || j        |<   ddd           n# 1 swxY w Y   |S )z
        Get or create a Honcho peer.

        Peers are lazy -- no API call until first use.
        Observation settings are controlled per-session via SessionPeerConfig.
        N)rZ   r[   rC   peer)r#   r   r   s      r%   _get_or_create_peerz(HonchoSessionManager._get_or_create_peer   s-     	2 	2$+++(1	2 	2 	2 	2 	2 	2 	2 	2+	2 	2 	2 	2 	2 	2 	2 	2 	2 	2 	2 	2 	2 	2 	2 {(( 	. 	.)-Dg&	. 	. 	. 	. 	. 	. 	. 	. 	. 	. 	. 	. 	. 	. 	.s   8<<$A;;A?A?
session_id	user_peerassistant_peertuple[Any, list]c                   | j         5  || j        v r6t                              d|           | j        |         g fcddd           S 	 ddd           n# 1 swxY w Y   | j                            |          }	 ddlm}  || j        | j	                  } || j
        | j                  }|                    ||f||fg           	 |                    |          }|                    |          }	|j        |j        | _        |j        |j        | _	        |	j        |	j        | _
        |	j        |	j        | _        t                              d| j        | j	        | j
        | j                   n2# t           $ r%}
t                              d|
           Y d}
~
nd}
~
ww xY wn3# t           $ r&}
t                              d||
           Y d}
~
nd}
~
ww xY wg }	 |                    d	| j        
          }|j        pg }|rat+          |          dk    rNd |D             }|r@|t-          |          k    r-t                              d|           t-          |d           }|r*t                              d|t+          |                     nt                              d|           n3# t           $ r&}
t                              d||
           Y d}
~
nd}
~
ww xY w|| j        |<   ||fS )z
        Get or create a Honcho session with peers configured.

        Returns:
            Tuple of (honcho_session, existing_messages).
        z(Honcho session '%s' retrieved from cacheNr   )SessionPeerConfig)
observe_meobserve_otherszPHoncho observation synced from server: user(me=%s,others=%s) ai(me=%s,others=%s)z=Honcho get_peer_configuration failed (using local config): %sz4Honcho session '%s' add_peers failed (non-fatal): %sT)summarytokens   c                *    g | ]}|j         	|j         S r.   )r   r/   s     r%   r2   zFHonchoSessionManager._get_or_create_honcho_session.<locals>.<listcomp>   s!    VVVqValVVVr'   zEHoncho messages not chronologically ordered for session '%s', sortingc                (    | j         pt          j        S N)r   r   min)r1   s    r%   <lambda>zDHonchoSessionManager._get_or_create_honcho_session.<locals>.<lambda>   s    al&Bhl r'   )r   z4Honcho session '%s' retrieved (%d existing messages)z!Honcho session '%s' created (new)z8Honcho session '%s' loaded (failed to fetch context: %s))rZ   r\   loggerdebugrC   sessionhoncho.sessionr   rl   rn   rp   rr   	add_peersget_peer_configurationr   r   	ExceptionwarningcontextrT   r   r3   sortedinfo)r#   r   r   r   r   r   user_config	ai_configserver_user	server_aieexisting_messagesctx
timestampss                 r%   _get_or_create_honcho_sessionz2HonchoSessionManager._get_or_create_honcho_session   s%     	< 	<T111GTTT+J7;	< 	< 	< 	< 	< 	< 	< 	<1	< 	< 	< 	< 	< 	< 	< 	< 	< 	< 	< 	< 	< 	< 	<
 +%%j11'	888888++0#8  K *).#6  I
 	;7.)9TUVVVa%<<YGG#::>JJ	)5,7,BD)-90;0JD-'3*3*>D'+7.7.FD+f)4+D')@   
  a a a\^_````````a 	 	 	NNFA       	 	//$t7K/LLC # 2 ! 
S):%;%;a%?%?VV4EVVV
 *z0B0B"B"BNN_"   )/)BB) ) )%
 ! MJ$5 6 6   
 ?LLL 	 	 	NNJA       	 ,3Z()))sn   3AAA;AF' B(E4 3F' 4
F#>FF' F##F' '
G1GGCJ- -
K7KKid_strc                .    t          j        dd|          S )z9Sanitize an ID to match Honcho's pattern: ^[a-zA-Z0-9_-]+z[^a-zA-Z0-9_-]-)resub)r#   r   s     r%   _sanitize_idz!HonchoSessionManager._sanitize_id
  s    v'f555r'   r   r   c                   | j         5  || j        v r4t                              d|           | j        |         cddd           S 	 ddd           n# 1 swxY w Y   | j        duo:t          t          | j        dd                    ot          | j        dd          du }| j        r|s|                     | j                  }n| j        r,| j        j	        r |                     | j        j	                  }nk|
                    dd          }t          |          dk    r|d	         nd
}t          |          dk    r|d         n|}|                     d| d|           }|                     | j        r| j        j        nd          }|                     |          }|                     |          }	|                     |          }
|                     ||	|
          \  }}g }|D ]P}|j        |k    rdnd}|                    ||j        |j        r|j                                        nddd           Qt)          |||||          }| j         5  || j        |<   ddd           n# 1 swxY w Y   |S )z
        Get an existing session or create a new one.

        Args:
            key: Session key (usually channel:chat_id).

        Returns:
            The session.
        zLocal session cache hit: %sN	peer_namepin_peer_nameFT:r   r   defaultzuser-r   zhermes-assistant	assistantuser )r   r   r   _synced)r   r   r   r   r   )rZ   rW   r   r   rU   boolgetattrrV   r   r   splitr3   ai_peerr   r   r   r"   r   r   r!   r   )r#   r   r   r   partschannelchat_idr   r   r   r   honcho_sessionr   local_messagesr$   r   r   s                    r%   get_or_createz"HonchoSessionManager.get_or_create  sm     	( 	(dk!!:C@@@{3'	( 	( 	( 	( 	( 	( 	( 	(!	( 	( 	( 	( 	( 	( 	( 	( 	( 	( 	( 	( 	( 	( 	(( L$ FWT\;==>>Fou==E 	
 ' 	J 	J,,T-IJJLL\ 	Jdl4 	J,,T\-CDDLLIIc1%%E"%e**q..eAhhiG"%e**q..eAhhcG,,-HW-H-Hw-H-HIIL --$(LHDL  6H
 

 !--c22,,\::	112CDD,0,N,Ny.-
 -
)) $ 	 	C"%+1B"B"B;;D!!;;>>QS^55777r	# #      %//#
 
 
  	' 	'&DK	' 	' 	' 	' 	' 	' 	' 	' 	' 	' 	' 	' 	' 	' 	's#   1AAAI,,I03I0r   r   c                   |j         sdS |                     |j                  }|                     |j                  }| j                            |j                  }|s|                     |j        ||          \  }}d |j         D             }|sdS g }|D ]@}|d         dk    r|n|}	|                    |		                    |d                              A	 |
                    |           |D ]}d|d<   t                              dt          |          |j                   | j        5  || j        |j        <   ddd           n# 1 swxY w Y   dS # t"          $ r^}
|D ]}d	|d<   t                              d
|
           | j        5  || j        |j        <   ddd           n# 1 swxY w Y   Y d}
~
d	S d}
~
ww xY w)z:Internal: write unsynced messages to Honcho synchronously.Tc                <    g | ]}|                     d           |S )r   getr/   s     r%   r2   z7HonchoSessionManager._flush_session.<locals>.<listcomp>k  s)    LLLa155;K;KLLLLr'   r   r   r   r   z#Synced %d messages to Honcho for %sNFz%Failed to sync messages to Honcho: %s)r   r   r   r   r\   r   r   r   r"   messageadd_messagesr   r   r3   r   rZ   rW   r   error)r#   r   r   r   r   _new_messageshoncho_messagesr$   r   r   s              r%   _flush_sessionz#HonchoSessionManager._flush_session]  s    	4,,W-ABB	11'2KLL-11'2KLL 	 $ B B)9n! !NA ML7#3LLL 	4 	A 	AC #Fv 5 599>D""4<<I#?#?@@@@	''888# & &!%ILL>O@T@TV]Vabbb! 3 3+2GK(3 3 3 3 3 3 3 3 3 3 3 3 3 3 34 	 	 	# ' '!&ILL@!DDD! 3 3+2GK(3 3 3 3 3 3 3 3 3 3 3 3 3 3 355555	sa   AE -E	=E 	EE EE 
F> ,F9F(F9(F,	,F9/F,	0F99F>r   c                   	 	 | j                             d          }|t          u rdS d}	 |                     |          }n# t          $ r}d}|}Y d}~nd}~ww xY w|r_|t
                              d|           nt
                              d           ddl}|                    d	           	 |                     |          }n2# t          $ r%}t
          	                    d
|           Y d}~d}~ww xY w|st
          	                    d           nC# t          j        $ r Y (t          $ r%}t
          	                    d|           Y d}~nd}~ww xY wZ)z7Background daemon thread: drains the async write queue.T   timeoutNFz,Honcho async write failed, retrying once: %sz(Honcho async write failed, retrying oncer      z3Honcho async write retry failed, dropping batch: %sz/Honcho async write retry failed, dropping batchzHoncho async writer error: %s)rw   r   _ASYNC_SHUTDOWNr   r   r   r   timesleepr   ry   Empty)r#   itemfirst_errorsuccessr   _timeretry_successe2s           r%   r|   z'HonchoSessionManager._async_writer_loop  s   #	A"A(,,Q,77?**E04$"11$77GG  $ $ $#G"#KKKKKK$  *NN#QS^____NN#MNNN$$$$A$($7$7$=$=MM    LL!VXZ[[[HHHH % TLL!RSSS;    A A A<a@@@@@@@@AE#	As|   $D D A D 
AAD AD  AD 2C D 
C7C2-D 2C77D E)	E2EEc                \   | xj         dz  c_         | j        }|dk    r%| j        | j                            |           dS dS |dk    r|                     |           dS |dk    rdS t          |t                    r+|dk    r'| j         |z  dk    r|                     |           dS dS dS dS )u`  Save messages to Honcho, respecting write_frequency.

        write_frequency modes:
          "async"   — enqueue for background thread (zero blocking, zero token cost)
          "turn"    — flush synchronously every turn
          "session" — defer until flush_session() is called explicitly
          N (int)   — flush every N turns
        r   rL   Nturnr   r   )r_   r^   rw   putr   
isinstancer*   )r#   r   wfs      r%   savezHonchoSessionManager.save  s     	a"== ,!%%g..... -,6\\(((((9__DC   	-R!VV!B&!++##G,,,,,	- 	-VV++r'   c                N   | j         5  t          | j                                                  }ddd           n# 1 swxY w Y   |D ]P}	 |                     |           # t
          $ r+}t                              d|j        |           Y d}~Id}~ww xY w| j	        | j	        
                                sl	 | j	                                        }|t          ur|                     |           n# t          j        $ r Y dS w xY w| j	        
                                hdS dS dS )zFlush all pending unsynced messages for all cached sessions.

        Called at session end for "session" write_frequency, or to force
        a sync before process exit regardless of mode.
        Nz!Honcho flush_all error for %s: %s)rZ   r?   rW   valuesr   r   r   r   r   rw   empty
get_nowaitr   ry   r   )r#   sessionsr   r   r   s        r%   	flush_allzHonchoSessionManager.flush_all  s     	2 	2DK..0011H	2 	2 	2 	2 	2 	2 	2 	2 	2 	2 	2 	2 	2 	2 	2 	R 	RGR##G,,,, R R R@'+qQQQQQQQQR ('--// ,7799D?22++D111{   EE '--//    )( s7   ';??A!!
B+!BB:7C2 2DDc                    | j         W| j        R|                                  | j                             t                     | j                            d           dS dS dS )z-Gracefully shut down the async writer thread.N
   r   )rw   rx   r   r   r   joinr7   s    r%   shutdownzHonchoSessionManager.shutdown  sh    (T-?-KNN!!/222##B#///// )(-K-Kr'   c                    | j         5  || j        v r| j        |= 	 ddd           dS 	 ddd           n# 1 swxY w Y   dS )z"Delete a session from local cache.NTF)rZ   rW   )r#   r   s     r%   deletezHonchoSessionManager.delete  s     	 	dk!!K$	 	 	 	 	 	 	 	!	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 us   599c                   ddl }| j        5  | j                            |d          }|r | j                            |j        d           t          |                                           }| d| }|                     |          }|| j        |<   ddd           n# 1 swxY w Y   t          	                    d||j                   |S )z
        Create a new session, preserving the old one for user modeling.

        Creates a fresh session with a new ID while keeping the old
        session's data in Honcho for continued user modeling.
        r   Nr   z'Created new session for %s (honcho: %s))
r   rZ   rW   popr\   r   r*   r   r   r   )r#   r   r   old_sessionr   new_keyr   s          r%   new_sessionz HonchoSessionManager.new_session  s    	  	' 	'+//#t44K N$(()FMMM DIIKK((I**y**G ((11G  'DK	' 	' 	' 	' 	' 	' 	' 	' 	' 	' 	' 	' 	' 	' 	'  	=sGD]^^^s   BBB!$B!)minimalrM   mediumhighmaxc                    | j         S )z.Return the configured default reasoning level.)rd   r7   s    r%   _default_reasoning_levelz-HonchoSessionManager._default_reasoning_level  s    ..r'   r   session_keyqueryreasoning_levelr   c                X   | j                             |          }|sdS |                     ||          }|dS t          |          | j        k    r)|d| j                                     dd          d         }| j        r|r|}n|                                 }	 | j        rZ| 	                    |j
                  }||j
        k    r|                    ||          pd}	nI|                    |||          pd}	n.| 	                    |          }
|
                    ||          pd}	|	rK| j        rDt          |	          | j        k    r,|	d| j                                     dd          d         dz   }	|	S # t          $ r&}t                              d	|           Y d}~dS d}~ww xY w)
u5  
        Query Honcho's dialectic endpoint about a peer.

        Runs an LLM on Honcho's backend against the target peer's full
        representation. Higher latency than context() — callers run this in
        a background thread (see HonchoMemoryProvider) to avoid blocking.

        Args:
            session_key: The session key to query against.
            query: Natural language question.
            reasoning_level: Override the configured default (dialecticReasoningLevel).
                             Only honored when dialecticDynamic is true.
                             If None or dialecticDynamic is false, uses the configured default.
            peer: Which peer to query — "user" (default) or "ai".

        Returns:
            Honcho's synthesized answer, or empty string on failure.
        r   N r   r   )r   )rP   r   u    …z!Honcho dialectic query failed: %s)rW   r   _resolve_peer_idr3   rv   rsplitrf   r   rr   r   r   chatrh   r   r   r   )r#   r   r   r   r   r   target_peer_idlevelai_peer_objresulttarget_peerr   s               r%   dialectic_queryz$HonchoSessionManager.dialectic_query  s   . +//+.. 	2..w==!2 u::777:4::;BB3JJ1ME" 	4 	4#EE1133E	& N"66w7PQQ!W%>>>(--eU-KKQrFF(---(- .    	 F #66~FF$))%)GGM2  W$3 WFdF_8_8_ :!: :;BB3JJ1MPVVM 	 	 	NN>BBB22222	s   CE9 9
F)F$$F)user_messagec                p      fd}t          j        |dd          }|                                 dS )z
        Fire get_prefetch_context in a background thread, caching the result.

        Non-blocking. Consumed next turn via pop_context_result(). This avoids
        a synchronous HTTP round-trip blocking every response.
        c                 h                                   } | r                    |            d S d S r   )get_prefetch_contextset_context_result)r  r#   r   r  s    r%   _runz3HonchoSessionManager.prefetch_context.<locals>._runX  sF    ..{LIIF =''V<<<<<= =r'   zhoncho-context-prefetchTrO   N)rX   r{   r}   )r#   r   r  r  ts   ```  r%   prefetch_contextz%HonchoSessionManager.prefetch_contextQ  sT    	= 	= 	= 	= 	= 	= 	=
 D/HQUVVV						r'   r  dict[str, str]c                b    |sdS | j         5  || j        |<   ddd           dS # 1 swxY w Y   dS )z7Store a prefetched context result in a thread-safe way.N)rb   r`   )r#   r   r  s      r%   r
  z'HonchoSessionManager.set_context_result`  s     	F& 	6 	6/5D,	6 	6 	6 	6 	6 	6 	6 	6 	6 	6 	6 	6 	6 	6 	6 	6 	6 	6s   $((c                z    | j         5  | j                            |i           cddd           S # 1 swxY w Y   dS )z
        Return and clear the cached context result for this session.

        Returns empty dict if no result is ready yet (first turn).
        N)rb   r`   r   )r#   r   s     r%   pop_context_resultz'HonchoSessionManager.pop_context_resultg  s     & 	< 	<&**;;;	< 	< 	< 	< 	< 	< 	< 	< 	< 	< 	< 	< 	< 	< 	< 	< 	< 	<s   044c                r   | j                             |          }|si S i }	 | j                            |j                  }|rB|                    d          }|j        r%t          |j        dd          r|j        j        |d<   n2# t          $ r%}t          
                    d|           Y d}~nd}~ww xY w	 |                     |j        |pd|j                  }|d         |d<   d	                    |d
                   |d
<   n2# t          $ r%}t                              d|           Y d}~nd}~ww xY w	 |                     |j        |j                  }	|	d         |d<   d	                    |	d
                   |d<   n2# t          $ r%}t          
                    d|           Y d}~nd}~ww xY w|S )a  
        Pre-fetch user and AI peer context from Honcho.

        Fetches peer_representation and peer_card for both peers, plus the
        session summary when available. When user_message is provided, it is
        passed as search_query to the peer context call so Honcho returns
        conclusions relevant to the session topic rather than the full
        observation dump.

        Args:
            session_key: The session key to get context for.
            user_message: Optional first user message used as search_query for
                          topic-relevant context retrieval.

        Returns:
            Dictionary with 'representation', 'card', 'ai_representation',
            'ai_card', and optionally 'summary' keys.
        T)r   r   Nr   z/Failed to fetch session summary from Honcho: %ssearch_queryrP   representation
cardz,Failed to fetch user context from Honcho: %srP   ai_representationai_cardz/Failed to fetch AI peer context from Honcho: %s)rW   r   r\   r   r   r   r   r   r   r   r   _fetch_peer_contextr   r   r   r   )
r#   r   r  r   r  r   r   r   user_ctxai_ctxs
             r%   r	  z)HonchoSessionManager.get_prefetch_contextp  s)   & +//+.. 	I!#	O!155g6OPPN <$,,T,::; <73;	4#H#H <(+(;F9% 	O 	O 	OLLJANNNNNNNN	O	N//0DS_Sgcgpw  qE/  F  FH'/0@'AF#$!YYx'788F6NN 	N 	N 	NNNI1MMMMMMMM	N	O--g.GPWPi-jjF*01A*BF&' $		&. 9 9F9 	O 	O 	OLLJANNNNNNNN	O sJ   A#B 
B5B00B59AD 
D6D11D6:A
F 
F4F//F4r   r   c                   | j                             |          }|st                              d|           dS | j                            |j                  }|st                              d|           dS |                     |j                  }|                     ||          }|r|d                             d          nd}	 |	                    d|df|d	t          |          d
|           t                              dt          |          |           dS # t          $ r'}t                              d||           Y d}~dS d}~ww xY w)a{  
        Upload local session history to Honcho as a file.

        Used when Honcho activates mid-conversation to preserve prior context.

        Args:
            session_key: The session key (e.g., "telegram:123456").
            messages: Local messages (dicts with role, content, timestamp).

        Returns:
            True if upload succeeded, False otherwise.
        z4No local session cached for '%s', skipping migrationFz5No Honcho session cached for '%s', skipping migrationr   r   Nzprior_history.txt
text/plainlocal_jsonl)sourcecount)filer   r   r   z+Migrated %d local messages to Honcho for %sTz3Failed to upload local history to Honcho for %s: %s)rW   r   r   r   r\   r   r   r   _format_migration_transcriptupload_filer3   r   r   r   )	r#   r   r   r   r   r   content_bytesfirst_tsr   s	            r%   migrate_local_historyz*HonchoSessionManager.migrate_local_history  sm    +//+.. 	NNQS^___5-11'2KLL 	NNRT_```5,,W-ABB	99+xPP3;E8A;??;///	&&)=,G$1CMMJJ#	 '    KKEs8}}Vabbb4 	 	 	LLNP[]^___55555	s   AD 
E)EEbytesc                ,   d |D             }|r|d          d|d          nd}dddd	d
dddd|  dt          |           dd| ddg}|D ]c}|                    dd          }|                    dd          }|                    d          pd}|                    d| d| d|            d|                    d           |                    d           |                    d           d                    |                              d          S )zBFormat local messages as an XML transcript for Honcho file upload.c                :    g | ]}|                     d d          S )r   r   r   r/   s     r%   r2   zEHonchoSessionManager._format_migration_transcript.<locals>.<listcomp>  s&    ???aeeK,,???r'   r   z to unknownz<prior_conversation_history>z	<context>zQThis conversation history occurred BEFORE the Honcho memory system was activated.zQThese messages are the preceding elements of this conversation session and shouldzPbe treated as foundational context for all subsequent interactions. The user andzCassistant have already established rapport through these exchanges.z
</context>r   z<transcript session_key="z" message_count=""z           time_range="z">r   ?r   r   [z] z: z</transcript>z</prior_conversation_history>r  utf-8)r3   r   r"   r   encode)	r   r   r   
time_rangelinesr$   tsr   r   s	            r%   r$  z1HonchoSessionManager._format_migration_transcript  s]    @?h???
?IX
1;;:b>;;;y
 +__^QVVVc(mmVVV4j444
  	6 	6Cc**B7769--Dggi((.BGLL4R444447445555R_%%%4555yy&&w///r'   
memory_dirc           	        ddl m}  ||          }|                                sdS | j                            |          }|st
                              d|           dS | j                            |j                  }|st
                              d|           dS | 	                    |j
                  }| 	                    |j                  }d}	ddd|d	fd
dd|d	fddd|dfg}
|
D ]\  }}}}}||z  }|                                s"|                    d                                          }|sMd| d| d}	 |                    ||                    d          df|d||d           t
                              d|||           d}	# t"          $ r&}t
                              d||           Y d}~d}~ww xY w|	S )a  
        Upload MEMORY.md and USER.md to Honcho as files.

        Used when Honcho activates on an instance that already has locally
        consolidated memory. Backwards compatible -- skips if files don't exist.

        Args:
            session_key: The session key to associate files with.
            memory_dir: Path to the memories directory (~/.hermes/memories/).

        Returns:
            True if at least one file was uploaded, False otherwise.
        r   )PathFz;No local session cached for '%s', skipping memory migrationz<No Honcho session cached for '%s', skipping memory migrationz	MEMORY.mdzconsolidated_memory.mdz%Long-term agent notes and preferencesr   zUSER.mdzuser_profile.mdzUser profile and preferenceszSOUL.mdzagent_soul.mdz(Agent persona and identity configurationair1  )encodingzo<prior_memory_file>
<context>
This file was consolidated from local conversations BEFORE Honcho was activated.
z;. Treat as foundational context for this user.
</context>

z
</prior_memory_file>
r  local_memory)r!  original_filer  )r#  r   r   z&Uploaded %s to Honcho for %s (%s peer)Tz!Failed to upload %s to Honcho: %sN)pathlibr8  existsrW   r   r   r   r\   r   r   r   r   	read_textstripr%  r2  r   r   r   )r#   r   r6  r8  memory_pathr   r   r   r   uploadedfilesfilenameupload_namedescriptionr  target_kindfilepathr   wrappedr   s                       r%   migrate_memory_filesz)HonchoSessionManager.migrate_memory_files  s    	!     d:&&!!## 	5+//+.. 	NNXZefff5-11'2KLL 	NNY[fggg5,,W-ABB	11'2KLL (7 !. :
0 MR %	O %	OHHk;["X-H??$$ (('(::@@BBG * * * * * * O**%w~~g'>'>M$"0)1'2  +    <	     O O O@(ANNNNNNNNO s   AF
GF??Gr  	list[str]c                l    | sg S t          | t                    rd | D             S t          |           gS )z<Normalize Honcho card payloads into a plain list of strings.c                0    g | ]}|t          |          S r.   )r   )r0   r   s     r%   r2   z8HonchoSessionManager._normalize_card.<locals>.<listcomp>X  s#    777$$7CII777r'   )r   r?   r   )r  s    r%   _normalize_cardz$HonchoSessionManager._normalize_cardR  sE      	IdD!! 	877$7777D		{r'   r  rP   c               \   |                      |          }t          |dd          }t          |          r+|                     | ||          n	 |                      S t          |dd          }t          |          r+|                     | ||          n	 |                      S g S )zFetch a peer card directly from the peer object.

        This avoids relying on session.context(), which can return an empty
        peer_card for per-session messaging sessions even when the peer itself
        has a populated card.
        get_cardNr  r  )r   r   callablerN  )r#   r   rP   r   getterlegacy_getters         r%   _fetch_peer_cardz%HonchoSessionManager._fetch_peer_card[  s     ''00z400F 	c''ASf(=(=(=(=Y_Y_YaYabbbfd33M"" 	q''HZV(D(D(D(D`m`m`o`oppp	r'   r  r   c                  |                      |          }d}g }	 i }|||d<   |||d<   |r |j        di |n|                                }t          |dd          pt          |dd          pd}|                     t          |dd                    }n3# t          $ r&}	t
                              d||	           Y d}	~	nd}	~	ww xY w|sc	 ||                    |	          n|                                pd}n3# t          $ r&}	t
                              d
||	           Y d}	~	nd}	~	ww xY w|sL	 |                     ||	          }n3# t          $ r&}	t
                              d||	           Y d}	~	nd}	~	ww xY w||dS )z=Fetch representation + peer card directly from a peer object.r   NrP   r  r  peer_representation	peer_cardz)Direct peer.context() failed for '%s': %sr  z0Direct peer.representation() failed for '%s': %sz*Direct peer card fetch failed for '%s': %sr  r  r.   )	r   r   r   rN  r   r   r   r  rT  )
r#   r   r  rP   r   r  r  context_kwargsr   r   s
             r%   r  z(HonchoSessionManager._fetch_peer_contextm  s0    ''00	R-/N!+1x('1=~.4BV,$,00000C-t44 3 5t<< 
 ''[$(G(GHHDD 	R 	R 	RLLDgqQQQQQQQQ	R  	]]:@:LD''v'666RVReReRgRg"   ] ] ]OQXZ[\\\\\\\\]  	WW,,WV,DD W W WI7TUVVVVVVVVW #1$???sH   A;B 
C!CC.C< <
D,D''D,2E
 

E:E55E:c                   | j                             |          }|si S | j                            |j                  }|s6|                     ||          }||j        }|                     ||          S 	 |                     ||          }|                    d||dk    r|j        n|j                  }i }|j	        r|j	        j
        |d<   |j        r
|j        |d<   |j        rd                    |j                  |d	<   |j        r|j        d
d         }d |D             |d<   |S # t          $ r'}	t                               d|	           i cY d}	~	S d}	~	ww xY w)zFetch full session context from Honcho including summary.

        Uses the session-level context() API which returns summary,
        peer_representation, peer_card, and messages.
        Nr  Tr   )r   peer_targetpeer_perspectiver   r  r  r  ic                T    g | ]%}t          |d d          |j        pddd         d&S )r   r-  r   Ni  r-   )r   r   r/   s     r%   r2   z<HonchoSessionManager.get_session_context.<locals>.<listcomp>  sO     - - - %Q	9==19?XZ\`]`\`Jabb- - -r'   recent_messagesz Session context fetch failed: %s)rW   r   r\   r   r   r   r  r   r   r   r   rV  rW  r   r   r   r   r   )
r#   r   r   r   r   r   r   r  r4   r   s
             r%   get_session_contextz(HonchoSessionManager.get_session_context  s    +//+.. 	I-11'2KLL 	E++GT::G!.++GG+DDD	++GT::G ((#9=!5!5WMf )  C &(F { 8$'K$7y! & C+.+B'(} :!%3=!9!9v | cdd+- -#- - -()
 M 	 	 	LL;Q???IIIIII	s   7B3D+ +
E5EEEc                    |pd                                 }|s|j        S |                     |          }||                     d          k    r|j        S ||                     d          k    r|j        S |S )zResolve a peer alias or explicit peer ID to a concrete Honcho peer ID.

        Always returns a non-empty string: either a known peer ID or a
        sanitized version of the caller-supplied alias/ID.
        r   r9  )r@  r   r   r   )r#   r   r   	candidate
normalizeds        r%   r   z%HonchoSessionManager._resolve_peer_id  s     ^V**,,	 	(''&&y11
**62222''**40000,,r'   tuple[str, str | None]c                    |                      ||          }||j        k    r|j        |j        fS | j        r	|j        |fS |dfS )zHResolve observer and target peer IDs for context/search/profile queries.N)r   r   rr   )r#   r   r   r   s       r%   _resolve_observer_targetz-HonchoSessionManager._resolve_observer_target  s\     ..w==W666,g.GGG" 	=,n<<t##r'   c                   | j                             |          }|sg S 	 |                     ||          \  }}|                     ||          S # t          $ r'}t
                              d|           g cY d}~S d}~ww xY w)u   
        Fetch a peer card — a curated list of key facts.

        Fast, no LLM reasoning. Returns raw structured facts Honcho has
        inferred about the target peer (name, role, preferences, patterns).
        Empty list if unavailable.
        r  z)Failed to fetch peer card from Honcho: %sN)rW   r   re  rT  r   r   r   )r#   r   r   r   observer_peer_idr   r   s          r%   get_peer_cardz"HonchoSessionManager.get_peer_card  s     +//+.. 	I	/3/L/LWVZ/[/[,n(()9.(QQQ 	 	 	LLDaHHHIIIIII	s   /A 
BA<6B<B   
max_tokensr*   c                   | j                             |          }|sdS 	 |                     ||          \  }}|                     |||          }g }	|d         r|	                    |d                    |d         pg }
|
r2|	                    d                    d |
D                                  d                    |	          S # t          $ r&}t                              d|           Y d	}~dS d	}~ww xY w)
ue  
        Semantic search over Honcho session context.

        Returns raw excerpts ranked by relevance to the query. No LLM
        reasoning — cheaper and faster than dialectic_query. Good for
        factual lookups where the model will do its own synthesis.

        Args:
            session_key: Session to search against.
            query: Search query for semantic matching.
            max_tokens: Token budget for returned content.
            peer: Peer alias or explicit peer ID to search about.

        Returns:
            Relevant context excerpts as a string, or empty string if none.
        r   r  r  r  r  c              3      K   | ]	}d | V  
dS )z- Nr.   )r0   fs     r%   	<genexpr>z6HonchoSessionManager.search_context.<locals>.<genexpr>)  s(      &>&>AxAxx&>&>&>&>&>&>r'   z

z Honcho search_context failed: %sN)	rW   r   re  r  r"   r   r   r   r   )r#   r   r   rj  r   r   rg  rP   r   r   r  r   s               r%   search_contextz#HonchoSessionManager.search_context  s+   . +//+.. 	2	'+'D'DWd'S'S$f** " +  C
 E#$ 4S!12333v;$"D @TYY&>&>&>&>&>>>???;;u%%% 	 	 	LL;Q???22222	s   B(C	 	
C9C44C9r   c                h   |r|                                 sdS | j                            |          }|st                              d|           dS 	 |                     ||          }|t                              d||           dS ||j        k    r5|                     |j                  }|                    |j                  }na| j	        r0|                     |j                  }|                    |          }n*|                     |          }|                    |          }|
                    |                                 |j        dg           t                              d|||dd                    dS # t          $ r&}	t                              d	|	           Y d}	~	dS d}	~	ww xY w)
u$  Write a conclusion about a target peer back to Honcho.

        Conclusions are facts a peer observes about another peer or itself —
        preferences, corrections, clarifications, and project context.
        They feed into the target peer's card and representation.

        Args:
            session_key: Session to associate the conclusion with.
            content: The conclusion text.
            peer: Peer alias or explicit peer ID. "user" is the default alias.

        Returns:
            True on success, False on failure.
        Fz/No session cached for '%s', skipping conclusionNz7Could not resolve conclusion peer '%s' for session '%s')r   r   z&Created conclusion about %s for %s: %sP   TzFailed to create conclusion: %s)r@  rW   r   r   r   r   r   r   conclusions_ofrr   creater   r   r   r   )
r#   r   r   r   r   r   r   conclusions_scoper  r   s
             r%   create_conclusionz&HonchoSessionManager.create_conclusion/  s     	gmmoo 	5+//+.. 	NNLkZZZ5	!227DAAN%XZ^`klllu!:::!%!9!9':S!T!T$2$A$A'B[$\$\!!( O!%!9!9':S!T!T$2$A$A.$Q$Q!!"66~FF$/$>$>~$N$N!$$"==??%7' ' &    KK@.R]_fgjhjgj_klll4 	 	 	LL:A>>>55555	s   4F 	C6F 
F1F,,F1conclusion_idc                |   | j                             |          }|sdS 	 |                     ||          }||j        k    r5|                     |j                  }|                    |j                  }na| j        r0|                     |j                  }|                    |          }n*|                     |          }|                    |          }|                    |           t          	                    d||           dS # t          $ r'}	t                              d||	           Y d}	~	dS d}	~	ww xY w)a1  Delete a conclusion by ID. Use only for PII removal.

        Args:
            session_key: Session key for peer resolution.
            conclusion_id: The conclusion ID to delete.
            peer: Peer alias or explicit peer ID.

        Returns:
            True on success, False on failure.
        FzDeleted conclusion %s for %sTz"Failed to delete conclusion %s: %sN)rW   r   r   r   r   rr  rr   r   r   r   r   r   )
r#   r   rv  r   r   r   observerscoper  r   s
             r%   delete_conclusionz&HonchoSessionManager.delete_conclusion`  sH    +//+.. 	5	!227DAAN!:::33G4MNN //0IJJ( C33G4MNN //??"66~FF#22>BBLL'''KK6{SSS4 	 	 	LL=}aPPP55555	s   C(D
 

D;D66D;list[str] | Nonec                   | j                             |          }|sdS 	 |                     ||          }|t                              d||           dS |                     |          }|                    |          }t                              d|t          |                     |S # t          $ r&}t          
                    d|           Y d}~dS d}~ww xY w)a  Update a peer's card.

        Args:
            session_key: Session key for peer resolution.
            card: New peer card as list of fact strings.
            peer: Peer alias or explicit peer ID.

        Returns:
            Updated card on success, None on failure.
        Nz=Could not resolve peer '%s' for set_peer_card in session '%s'z#Updated peer card for %s (%d facts)zFailed to set peer card: %s)rW   r   r   r   r   r   set_cardr   r3   r   r   )	r#   r   r  r   r   r   peer_objr  r   s	            r%   set_peer_cardz"HonchoSessionManager.set_peer_card  s     +//+.. 	4	++GT::G^`dfqrrrt//88H&&t,,FKK=wD		RRRM 	 	 	LL6:::44444	s   4B+ AB+ +
C5CCmanualr!  c                   |r|                                 sdS | j                            |          }|st                              d|           dS |                     |j                  }| j                            |j                  }|st                              d|           dS 	 d| d|                                  d}|	                    |
                    |          g           t                              d||           dS # t          $ r&}t                              d	|           Y d
}~dS d
}~ww xY w)a6  
        Seed the AI peer's Honcho representation from text content.

        Useful for priming AI identity from SOUL.md, exported chats, or
        any structured description. The content is sent as an assistant
        peer message so Honcho's reasoning model can incorporate it.

        Args:
            session_key: The session key to associate with.
            content: The identity/persona content to seed.
            source: Metadata tag for the source (e.g. "soul_md", "export").

        Returns:
            True on success, False on failure.
        Fz,No session cached for '%s', skipping AI seedz3No Honcho session cached for '%s', skipping AI seedz<ai_identity_seed>
<source>z</source>

z
</ai_identity_seed>z$Seeded AI identity from '%s' into %sTzFailed to seed AI identity: %sN)r@  rW   r   r   r   r   r   r\   r   r   r   r   r   r   )	r#   r   r   r!  r   r   r   rI  r   s	            r%   seed_ai_identityz%HonchoSessionManager.seed_ai_identity  sc      	gmmoo 	5+//+.. 	NNI;WWW511'2KLL-11'2KLL 	NNPR]^^^5	'!' ' ==??' ' '  '')?)?)H)H(IJJJKK>TTT4 	 	 	LL91===55555	s   +A D 
D=D88D=c                B   | j                             |          }|sdddS 	 |                     |j        |j                  }|d         pdd                    |d                   dS # t
          $ r*}t                              d|           dddcY d}~S d}~ww xY w)	z
        Fetch the AI peer's current Honcho representation.

        Returns:
            Dict with 'representation' and 'card' keys, empty strings if unavailable.
        r   rX  r  r  r  r  z%Failed to fetch AI representation: %sN)rW   r   r  r   r   r   r   r   )r#   r   r   r   r   s        r%   get_ai_representationz*HonchoSessionManager.get_ai_representation  s     +//+.. 	6&("555	6**7+DWMf*ggC"%&6"7"=2		#f+..    	6 	6 	6LL@!DDD&("55555555	6s   AA* *
B4BBBc                H    d | j                                         D             S )zList all cached sessions.c                    g | ]N}|j         |j                                        |j                                        t	          |j                  d OS ))r   r   r   message_count)r   r   r!   r   r3   r   )r0   ss     r%   r2   z6HonchoSessionManager.list_sessions.<locals>.<listcomp>  sc     
 
 
  ul4466l4466!$QZ	 
 
 
r'   )rW   r   r7   s    r%   list_sessionsz"HonchoSessionManager.list_sessions  s3    
 
 [''))
 
 
 	
r'   )NNNN)rC   rD   rE   rF   rG   rH   rI   rJ   )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   r9   )r   r   r   r   )r   r   r   r   )r   r   )Nr   )
r   r   r   r   r   rJ   r   r   r   r   r   )r   r   r  rJ   r   r   )r   r   r  r  r   r   )r   r   r   r  )r   r   r  rJ   r   r  )r   r   r   r   r   r   )r   r   r   r   r   r)  )r   r   r6  r   r   r   )r  r   r   rK  )r   r   rP   rJ   r   rK  )r   r   r  rJ   rP   rJ   r   r   )r   )r   r   r   r   r   r   )r   r   r   rJ   r   r   )r   r   r   rJ   r   rc  )r   r   r   r   r   rK  )ri  r   )
r   r   r   r   rj  r*   r   r   r   r   )r   r   r   r   r   r   r   r   )r   r   rv  r   r   r   r   r   )r   r   r  rK  r   r   r   r{  )r  )r   r   r   r   r!  r   r   r   )r   r   )+r:   r;   r<   r=   r~   propertyrC   r   r   r   r   r   r|   r   r   r   r   r   _REASONING_LEVELSr   r  r  r
  r  r	  r(  staticmethodr$  rJ  rN  rT  r  r_  r   re  rh  ro  ru  rz  r  r  r  r  r.   r'   r%   rB   rB   D   s         !%%)!-1G' G' G' G' G'R    X    \* \* \* \*|6 6 6 6M M M M^% % % %N%A %A %A %AN- - - -0   00 0 0 0      @ D/ / / / '+? ? ? ? ?B    6 6 6 6< < < <5 5 5 5 5n' ' ' 'R 0 0 0 \0<a a a aF    \ FJ      * $(*@
 "*@ *@ *@ *@ *@ *@X1 1 1 1 1f   $$ $ $ $     . , , , , ,\/ / / / /b    @    6+ + + + +Z6 6 6 6*

 

 

 

 

 

r'   rB   )r=   
__future__r   ry   r   loggingrX   dataclassesr   r   r   typingr   r   plugins.memory.honcho.clientr	   rC   r
   	getLoggerr:   r   objectr   r   rB   r.   r'   r%   <module>r     sB   ? ? " " " " " "  				      ( ( ( ( ( ( ( (       % % % % % % % % : : : : : : 		8	$	$ &(( () () () () () () () ()Vc
 c
 c
 c
 c
 c
 c
 c
 c
 c
r'   