
    yjF                     
   d dl Z d dlZd dlmZ d dlmZ d dlmZ d dlm	Z	m
Z
mZmZmZmZ d dlmZ d dlmZ d dlmZ d d	lm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 m!Z! d dl"m#Z# d dl$m%Z%m&Z& d dl'm(Z(m)Z) d dl*m+Z+ d dl,m-Z-m.Z.m/Z/ d dl0m1Z1 d dl2m3Z3  ej4        e5          Z6 e	ddg          Z7e78                    deej9                  e e)d                    g           ed           e
dd          efde:dej;        dz  d efd!            Z<e78                    d"ej9        #           ed           e
dd$           e e)                      efd%ede:d&ej=        d'e(d ef
d(            Z>e7?                    d)ej9         e e)dd*+                    g           ed           ed           e
dd,          efde:d*e:d&ej@        d efd-            ZAe78                    d.eejB                  e e)dd*+                    g           ed           ed           e
dd/          efde:d*e:dejC        dz  d efd0            ZDe78                    d1d2d3d4ejE        F                                ii d5ii e e)dd*+                    g6           ed           ed           e
d          fde:d*e:dejG        fd7            ZHe78                    d8ejI         e e)dd*+                    g           ed           ed           e
dd9          fde:d*e:dejJ        fd:            ZKe7L                    d;ejM         e e)dd*+                    g           ed           edd<           edd=          efde:d*e:d>e:dz  d efd?            ZNe7?                    d;ejM         e e)dd*+                    g           ed           edd<           e
dd@           eddA          efde:d*e:dBejO        d>e:dz  d ef
dC            ZPe7L                    dDejQ         e e)dd*+                    g           ed           edd<           eddE           eddF           eddGdHdIJ           eddKdLdMJ           edNdOP           eddGdHdQJ          ef	de:d*e:d>e:dz  dRe:dz  dSeRdz  dTeSdz  dUeTdVeRdz  d efdW            ZUe78                    dXeVejW                  e e)dd*+                    g           ed           ed           e
ddY          fde:d*e:dZejX        fd[            ZYdS )\    N)AsyncIterator)suppress)perf_counter)	APIRouterBodyDependsPathQueryResponse)StreamingResponse)Page)	apaginate)AsyncSession)crudschemas)settings)db
tracked_db)agentic_chatagentic_chat_stream)embedding_client)AuthenticationExceptionResourceNotFoundException)	JWTParamsrequire_auth)prometheus_metrics)EmbeddingCallPurposeGetContextEventemit)search)embedding_call_purposez /workspaces/{workspace_id}/peerspeers)prefixtagsz/listworkspace_id)workspace_name)response_modeldependencies.z$Filtering options for the peers list)descriptionoptionsr   c                    K   d}|rt          |d          r|j        }|i k    rd}t          |t          j        | |           d{V            d{V S )z?Get all Peers for a Workspace, paginated with optional filters.Nfilters)r&   r,   )hasattrr,   r   r   	get_peers)r%   r*   r   filter_params       9/DATA/AppData/hermes/projects/honcho/src/routers/peers.pyr.   r.   !   s       L  77I..  2L
nL,OOOOOOOOO             )r'   zPeer creation parametersresponsepeer
jwt_paramsc                   K   |j         s!|j        |j        |k    rt          d          |j        r.|j         s&|j        |j        |j        k    rt          d          n"|j        st          d          |j        |_        t          j        |||g           d{V } |j                     d{V  |                                 d{V  |j	        rdnd| _
        |j        d         S )z
    Get a Peer by ID or create a new Peer with the given ID.

    If peer_id is provided as a query parameter, it uses that (must match JWT workspace_id).
    Otherwise, it uses the peer_id from the JWT.
    NzUnauthorized access to resourcez+Peer ID not found in query parameter or JWTr&   r"         r   )adwr   namepr   get_or_create_peerscommitpost_commitcreatedstatus_coderesource)r3   r%   r4   r5   r   results         r0   get_or_create_peerrE   :   s8     $ = IZ\5*,,:V:V%&GHHHy !} 	M!9jldi>W>W)*KLLL | 	Y)*WXXXL	+
<v        F ")++




"(.933cH?1r1   z
/{peer_id}peer_id)r&   	peer_namezUpdated peer parametersc                 F   K   t          j        || ||           d{V }|S )z.Update a Peer's metadata and/or configuration.)r&   rG   r4   N)r   update_peer)r%   rF   r4   r   updated_peers        r0   rI   rI   `   sN       )
<7        L r1   z/{peer_id}/sessionsz'Filtering options for the sessions listc                    K   d}|rt          |d          r|j        }|i k    rd}t          |t          j        | ||           d{V            d{V S )z=Get all Sessions for a Peer, paginated with optional filters.Nr,   )r&   rG   r,   )r-   r,   r   r   get_sessions_for_peer)r%   rF   r*   r   r/   s        r0   rL   rL   t   s        L  77I..  2L
(' 
 
 
 	
 	
 	
 	
 	
 	
        r1   z/{peer_id}/chatr9   contentschema)zapplication/jsontext/event-stream)	responsesr(   c                   K   t          d          4 d{V }t          j        || t          j        |          g           d{V }|                                 d{V  ddd          d{V  n# 1 d{V swxY w Y   |                                 d{V  |j        rdt          t                   dt          t                   fd}t          j        j        rt          j        | |j                   t!           |t#          | |j        |j        ||j        |j        n||j        	                    d
          S t+          | |j        |j        ||j        |j        n||j        	           d{V }t          j        j        rt          j        | |j                   t          j        |r|nd          S )z
    Query a Peer's representation using natural language. Performs agentic search and reasoning to comprehensively
    answer the query based on all latent knowledge gathered about the peer from their messages and conclusions.
    zpeers.chat.get_or_create_peerN)r<   r7   chunksreturnc                   K   | 2 3 d{V }dt          j        d|idd           dW V  (6 dt          j        ddi           dW V  dS )	zFormat chunks as SSE events.Nzdata: rM   F)deltadonez

rV   T)jsondumps)rR   chunks     r0   format_sse_streamzchat.<locals>.format_sse_stream   s        & ^ ^ ^ ^ ^ ^ ^e]tzY4FPU*V*VWW]]]]]]]]  &;4:vtn55;;;;;;;;;s   -)r&   reasoning_level)r&   session_namequeryobserverobservedr[   rO   )
media_type)rM   )r   r   r>   r   
PeerCreater?   r@   streamr   strr   METRICSENABLEDr   record_dialectic_callr[   r   r   
session_idr]   targetr   DialecticResponse)r%   rF   r*   peer_dbpeers_resultrZ   r3   s          r0   chatrl      s     4 9::       g!5'%73334
 
 
 
 
 
 
 
 

 nn                           
"
"
$
$$$$$$$$~ 
	<!#&	<3	< 	< 	< 	< # 	4+ ' 7   
 !##/!(!3!-$/6~/IW^^w$+$;  	 	 +
 
 
 	
 "#'m $+>#=7/	 	 	 	 	 	 	 	 	H  
0'#3	
 	
 	
 	

 $-KXXtLLLLs   AA66
B B z/{peer_id}/representationz+Options for getting the peer representationc                   K   	 d}|j         rt          t                    5  t          t          j        j        | d          5  t          j        |j                    d{V }ddd           n# 1 swxY w Y   ddd           n# 1 swxY w Y   t          j
        | ||j        |j        n||j        |j         ||j        |j        |j        |j        nd|j        |j        nt"          j        j        d           d{V }t)          j        |                                          S # t.          $ rB}t0                              d| dt5          |                      t7          d	          |d}~ww xY w)
a  Get a curated subset of a Peer's Representation. A Representation is always a subset of the total
    knowledge about the Peer. The subset can be scoped and filtered in various ways.


    If a session_id is provided in the body, we get the Representation of the Peer scoped to that Session.
    If a target is provided, we get the Representation of the target from the perspective of the Peer.
    If no target is provided, we get the omniscient Honcho Representation of the Peer.
    Napir&   parent_categoryF
r^   r_   r\   include_semantic_query	embeddingsemantic_search_top_ksemantic_search_max_distanceinclude_most_derivedmax_observationsrp   )representationz&Failed to get representation for peer : zPeer or session not found)search_queryr   	Exceptionr!   r   SEARCH_MEMORYvaluer   embedr   get_working_representationrh   rg   search_top_ksearch_max_distanceinclude_most_frequentmax_conclusionsr   DERIVER'WORKING_REPRESENTATION_MAX_OBSERVATIONSr   RepresentationResponseformat_as_markdown
ValueErrorloggerwarningrc   r   )r%   rF   r*   rs   rx   es         r0   get_representationr      sk     ,$L(,	 		O##O O&(6<#/$)  O O #3"89M"N"NNNNNNN	O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O  $>'.~'AW^^w +#*#7")"6)0)D,8 ")!>!>&2 %44!I! 
  
  
 
 
 
 
 
 
" -)<<>>
 
 
 	
  L L LSSS3q66SSTTT'(CDD!KLs_   D* "B A/#B/A3	3B6A3	7B:D* B

D* B
BD* *
E64=E11E6z/{peer_id}/cardzID of the observer peerz~Optional target peer to retrieve a card for, from the observer's perspective. If not provided, returns the observer's own cardrh   c                 x   K   ||n|}t          j        || ||           d{V }t          j        |          S )zGet a peer card for a specific peer relationship.

    Returns the peer card that the observer peer has for the target peer if it exists.
    If no target is specified, returns the observer's own peer card.
    Nr^   r_   	peer_card)r   get_peer_cardr   PeerCardResponse)r%   rF   rh   r   r_   r   s         r0   r   r   *  sj      ,  +vvH(
L7X        I #i8888r1   zPeer card data to setzvOptional target peer to set a card for, from the observer's perspective. If not provided, sets the observer's own cardpeer_card_datac                    K   ||n|}t          j        || |j        ||           d{V  t          j        |j                  S )zSet a peer card for a specific peer relationship.

    Sets the peer card that the observer peer has for the target peer.
    If no target is specified, sets the observer's own peer card.
    N)r   r^   r_   r   )r   set_peer_cardr   r   r   )r%   rF   r   rh   r   r_   s         r0   r   r   H  sy      2  +vvH


 *          #n.FGGGGr1   z/{peer_id}/contextzOptional target peer to get context for, from the observer's perspective. If not provided, returns the observer's own context (self-observation)zJOptional query to curate the representation around semantic search results   d   zcOnly used if `search_query` is provided. Number of semantic-search-retrieved conclusions to include)geler)   g        g      ?z_Only used if `search_query` is provided. Maximum distance for semantically relevant conclusionsTzFWhether to include the most frequent conclusions in the representation)defaultr)   z>Maximum number of conclusions to include in the representationrz   r   r   r   r   c	                 x  K   ||n|}	t                      }
	 d}|rt          t                    5  t          t          j        j        | d          5  t          j        |           d{V }ddd           n# 1 swxY w Y   ddd           n# 1 swxY w Y   t          j
        | ||	d|||||||nt          j        j        d           d{V }t          j        || ||	           d{V }t          j        ||	|                                |          }t%          t'          | d||	t)          |j                  |du|du||||t                      |
z
  dz  	                     |S # t,          $ rB}t.                              d
| dt3          |                      t5          d          |d}~ww xY w)a  
    Get context for a peer, including their representation and peer card.

    This endpoint returns a curated subset of the representation and peer card for a peer.
    If a target is specified, returns the context for the target from the
    observer peer's perspective. If no target is specified, returns the
    peer's own context (self-observation).

    This is useful for getting all the context needed about a peer without
    making multiple API calls.
    Nrn   ro   rq   r   )rF   	target_idrx   r   r4   i  )r&   context_scoperG   target_namehas_representationhas_peer_cardsearch_query_providedr   r   r   r   total_duration_mszFailed to get context for peer ry   zPeer not found)r   r   r{   r!   r   r|   r}   r   r~   r   r   r   r   r   r   r   PeerContextr   r   r   boolrx   r   r   r   rc   r   )r%   rF   rh   rz   r   r   r   r   r   r_   context_startedrs   rx   r   r3   r   s                   r0   get_peer_contextr   n  s     l  +vvH"nnO<A(,	 		G##G G&(6<#/$)  G G #3"8"F"FFFFFFF	G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G  $>#/".)<!6* -_!I! 
  
  
 
 
 
 
 
 
" ,w
 
 
 
 
 
 
 
 
	 &)<<>>	
 
 
 	+$!$#'(?#@#@'t3&2$&>)$7&; /#/>>O#Ct"K  	
 	
 	
   A A ALLLCFFLLMMM'(899q@As_   E- "BA9-B9A=	=B A=	BE- BE- BCE- -
F97=F44F9z/{peer_id}/searchzQMessage search parameters. Use `limit` to control the number of results returned.bodyc                 p   K   |j         pi }| |d<   ||d<   t          |j        ||j                   d{V S )zBSearch a Peer's messages, optionally filtered by various criteria.r%   rF   )r,   limitN)r,   r    r]   r   )r%   rF   r   r,   s       r0   search_peerr     sS      " l bG*GN GI
G4:FFFFFFFFFFr1   )ZrW   loggingcollections.abcr   
contextlibr   timer   fastapir   r   r   r	   r
   r   fastapi.responsesr   fastapi_paginationr   !fastapi_pagination.ext.sqlalchemyr   sqlalchemy.ext.asyncior   srcr   r   
src.configr   src.dependenciesr   r   src.dialectic.chatr   r   src.embedding_clientr   src.exceptionsr   r   src.securityr   r   src.telemetryr   src.telemetry.eventsr   r   r   src.utils.searchr    src.utils.typesr!   	getLogger__name__r   routerpostPeerrc   PeerGetr.   ra   rE   put
PeerUpdaterI   Session
SessionGetrL   ri   model_json_schemaDialecticOptionsrl   r   PeerRepresentationGetr   getr   r   PeerCardSetr   r   intfloatr   r   listMessageMessageSearchOptionsr    r1   r0   <module>r      s
     ) ) ) ) ) )             C C C C C C C C C C C C C C C C / / / / / / # # # # # # 7 7 7 7 7 7 / / / / / /               + + + + + + + + @ @ @ @ @ @ @ @ 1 1 1 1 1 1 M M M M M M M M 0 0 0 0 0 0 0 0 , , , , , , L L L L L L L L L L # # # # # # 2 2 2 2 2 2		8	$	$	-

 
 
 %',,nEEEFFG    S		&*d@' ' '  _t#
 	   
( <    S		#tC5OPPP#GLLNN33  
 	
 	  	 D <NiPPPQQ    S		499#tC5NOOO	
 


 

 		
 
 
 
 (NiPPPQQ    S		499)-C* * *   $& 	   4 g7IIKK% &(	 
	 	NiPPPQQ   " S		499(,S		EM EMEMEM %EM EM EM!  EMP 1NiPPPQQ    S		499-1TF. . .3L 3L3L3L *3L 3L 3L 3Ll +NiPPPQQ    S		4)BCCC U   9 999 $J9 	9 9 9 9. +NiPPPQQ    S		4)BCCC*.$0+ + +  M   H HHH 'H $JH 	H H H H> &NiPPPQQ    S		4)BCCC g    %u`       %uy	      ).u	) ) ) #(%\# # # #(%T	# # # CnA nAnAnA $JnA *nA *nA" #nA.  /nA6 4Z7nAB 	CnA nA nA nAb (NiPPPQQ    S		499)-g* * *G GGG 
&G G G G G Gr1   