
    $j&;              !          d Z ddlZddlZddlZddlmZ ddlmZmZ ddlm	Z	m
Z
 e	rddlmZ ddlmZ d	d
lmZ  ej        e          Zde
deee
f         dz  fdZ	 	 	 	 	 d5dddddededee         dedee         dz  dedddee         dz  deee
f         fdZ	 	 	 	 	 	 	 	 	 d6dddeded d!d"edee         dz  deddd#edz  d$ed%ed&edz  d'edz  deee
f         fd(Z	 	 	 	 	 	 	 	 	 	 d7dddeded d!d"edee         dz  deddd-ed.ed/ee         dz  d0ed&edz  d'edz  deee
f         fd1Zddded2ee         d3edeee
f         f
d4ZdS )8a  
Tool implementations for the reflect agent.

Implements hierarchical retrieval:
1. search_mental_models - User-curated stored reflect responses (highest quality)
2. search_observations - Consolidated knowledge with freshness
3. recall - Raw facts as ground truth
    N)replace)datetimetimezone)TYPE_CHECKINGAny)
Connection   )RequestContext   )MemoryEngineretain_paramsreturnc                    t          | t                    r,	 t          j        |           } n# t          j        $ r Y dS w xY wt          | t
                    sdS |                     d          }t          |t
                    r|ndS )z=Return document metadata stored under retain_params.metadata.Nmetadata)
isinstancestrjsonloadsJSONDecodeErrordictget)r   r   s     j/home/rurouni/.hermes/hermes-agent/venv/lib/python3.11/site-packages/hindsight_api/engine/reflect/tools.py%_document_metadata_from_retain_paramsr      s    -%% 	 J}55MM# 	 	 	44	 mT** t  ,,H!(D11;88t;s   , ??   anymemory_enginer   connr   bank_idqueryquery_embeddingmax_resultstags
tags_match
tag_groupszlist | Noneexclude_idsc
                 Z  K   ddl m}
 ddlm}m} d}|t          |          |g}d}|r/ ||||          \  }}}|d| z  }|                    |           |r- |||          \  }}}|d| z  }|                    |           |	r#|d| d	z  }|                    |	           |d
z  } |j        d |
d           d| dg|R   d{V }g }|D ]}|d         }|r'|j	         |
                    t          j                  }|                     |||           d{V }|rdnd}|                    t          |d                   |d         |d         |d         pg t          |d         d          |r|                                nd||d           |t!          |          |dS )a3  
    Search user-curated mental models by semantic similarity.

    Mental models are high-quality, manually created summaries about specific topics.
    They should be searched FIRST as they represent the most reliable synthesized knowledge.

    Args:
        conn: Database connection
        bank_id: Bank identifier
        query: Search query (for logging/tracing)
        query_embedding: Pre-computed embedding for semantic search
        max_results: Maximum number of mental models to return
        tags: Optional tags to filter mental models
        tags_match: How to match tags - "any" (OR), "all" (AND)
        exclude_ids: Optional list of mental model IDs to exclude (e.g., when refreshing a mental model)

    Returns:
        Dict with matching mental models including content and freshness info
    r   fq_table)build_tag_groups_where_clausebuild_tags_where_clause    )param_offsetmatch z AND id != ALL($z	::text[])   z
        SELECT
            id, name, content,
            tags, created_at, last_refreshed_at, trigger,
            1 - (embedding <=> $2::vector) as relevance
        FROM mental_modelsz6
        WHERE bank_id = $1 AND embedding IS NOT NULL zD
        ORDER BY embedding <=> $2::vector
        LIMIT $3
        Nlast_refreshed_at)tzinfoz1new in-scope memories ingested since last refreshidnamecontentr"   	relevance)r4   r5   r6   r"   r7   
updated_atis_stalestaleness_reason)r   countr1   )r   r(   search.tagsr)   r*   r   extendappendfetchr3   r   r   utccompute_mental_model_is_staleround	isoformatlen)r   r   r   r   r    r!   r"   r#   r$   r%   r(   r)   r*   filtersparams
next_param
tag_clause
tag_paramsgroups_clausegroups_paramsrowsr1   rowr2   r9   r:   s                             r   tool_search_mental_modelsrN   )   s     > )(((((TTTTTTTT G #o"6"6DFJ  "-D-DTXbjt-u-u-u*
J
#z###j!!! %3P3PQ[]g3h3h0}j&}&&&m$$$ ;j;;;;k"""a
 		
 h''		 		 7>		 		 		 
        D M 
 
 34 	O!2!9!A 1 9 9 9 N N 'DDT7TWXXXXXXXXRZdNN`d#d)nnFy>F)r"3{#3Q77?PZ/99;;;VZ$$4	 		
 	
 	
 	
 ]##&        request_contextr
   
max_tokenslast_consolidated_atpending_consolidationsource_facts_max_tokenscreated_aftercreated_beforec                 f  K   |
dk    }i }|r|
dk    r|
|d<   t          |d          } | j        d||dg|d|||||||ddd	| d
{V }|	dk    }|	dk    rd}n|	dk     rd}nd}|t          |j                  d |j        D             d |j        pi                                 D             ||dS )a  
    Search consolidated observations using recall.

    Observations are auto-generated from memories. Returns freshness info
    so the agent knows if it should also verify with recall().

    Args:
        memory_engine: Memory engine instance
        bank_id: Bank identifier
        query: Search query
        request_context: Request context for authentication
        max_tokens: Maximum tokens for results (default 5000)
        tags: Optional tags to filter observations
        tags_match: How to match tags - "any" (OR), "all" (AND)
        last_consolidated_at: When consolidation last ran (for staleness check)
        pending_consolidation: Number of memories waiting to be consolidated
        source_facts_max_tokens: Token budget for source facts (-1 = disabled, 0+ = enabled with limit)

    Returns:
        Dict with matching observations including freshness info and source memories
    rQ   r   max_source_facts_tokensTinternalobservationFr0   )r   r   	fact_typerS   enable_tracerR   r"   r#   r$   include_source_factsrW   rX   _connection_budget_quietN
up_to_date
   slightly_stalestalec                 6    g | ]}|                                 S  
model_dump.0ms     r   
<listcomp>z,tool_search_observations.<locals>.<listcomp>   s     @@@A@@@rO   c                 >    i | ]\  }}||                                 S rh   ri   rl   kvs      r   
<dictcomp>z,tool_search_observations.<locals>.<dictcomp>   s&    [[[tq!ALLNN[[[rO   )r   r;   observationssource_factsr9   	freshnessrh   )r   recall_asyncrD   resultsru   items)r   r   r   rR   rS   r"   r#   r$   rT   rU   rV   rW   rX   r`   recall_kwargsinternal_ctxresultr9   rv   s                      r   tool_search_observationsr}      sR     H 3b8$&M K 7! ; ;3J/0 ?T:::L-=-  /$1#%         F$ %q(H!! 				#	#$			 V^$$@@@@@[[8K8Qr7X7X7Z7Z[[[  rO      r0     Tconnection_budgetmax_chunk_tokens
fact_typesinclude_chunksc                   K   d |
pddgD             }t          |d          }|                     ||||d|||||||d||	           d{V }|d	 |j        D             d
 |j        pi                                 D             dS )a
  
    Search memories using TEMPR retrieval.

    This is the ground truth - raw facts and experiences.
    Use when mental models/observations don't exist, are stale, or need verification.

    Args:
        memory_engine: Memory engine instance
        bank_id: Bank identifier
        query: Search query
        request_context: Request context for authentication
        max_tokens: Maximum tokens for results (default 2048)
        tags: Filter by tags (includes untagged memories)
        tags_match: How to match tags - "any" (OR), "all" (AND), or "exact"
        connection_budget: Max DB connections for this recall (default 1 for internal ops)
        max_chunk_tokens: Maximum tokens for raw source chunk text (default 1000)
        fact_types: Optional filter for fact types to retrieve. Defaults to ["experience", "world"].
        include_chunks: Whether to fetch raw chunk text alongside facts (default True).

    Returns:
        Dict with list of matching memories including raw chunk text (when include_chunks)
    c                     g | ]}|d v |	S ))world
experiencerh   )rl   fts     r   rn   ztool_recall.<locals>.<listcomp>  s$    nnnrPRVmPmPmPmPmPmrO   r   r   Tr[   F)r   r   r^   rS   r_   rR   r"   r#   r$   rW   rX   ra   rb   r   r   Nc                 6    g | ]}|                                 S rh   ri   rk   s     r   rn   ztool_recall.<locals>.<listcomp>  s     <<<Q\\^^<<<rO   c                 >    i | ]\  }}||                                 S rh   ri   rp   s      r   rs   ztool_recall.<locals>.<dictcomp>  s&    OOOA1allnnOOOrO   )r   memorieschunks)r   rw   rx   r   ry   )r   r   r   rR   rS   r"   r#   r$   r   r   r   r   rW   rX   recall_fact_typer{   r|   s                    r   tool_recallr      s      N onj&K\74Knnn?T:::L --"$#%,%) .        F& <<V^<<<OO&-2E21L1L1N1NOOO  rO   
memory_idsdepthc                 j  K   ddl m} |sddiS g }i }|D ]B}	 |                    t          j        |                     +# t
          $ r d| ||<   Y ?w xY w|sd|dS |                     d |d	           d
||           d{V }d |D             }	d |D             }
t                      }t                      }i }|
rG|                     d |d           d|
           d{V }d |D             }|dk    rd |D             }|dk    r0|D ]-}|d         s#|d         r|                    |d                    .i }t          ||z            }|r6|                     d |d           d||           d{V }d |D             }g }t          ||          D ]\  }}||v r|                    |||         d           )|	                    |          }|s|                    |d| d           \|t          |d                   |d         |d         |d         d d!}|d         r|d         |v r~||d                  }|d         |d"         |d#         |d         d$|d%<   |dk    rG|d         |v r=||d                  }|d         |d&         t          |d'                   |d'         d(|d<   nU|d         rM|dk    rG|d         |v r=||d                  }|d         |d&         t          |d'                   |d'         d(|d<   |                    |           |t          |          d)S )*aN  
    Expand multiple memories to get chunk or document context.

    Args:
        conn: Database connection
        bank_id: Bank identifier
        memory_ids: List of memory unit IDs
        depth: "chunk" or "document"

    Returns:
        Dict with results array, each containing memory, chunk, and optionally document data
    r   r'   errorz,memory_ids is required and must not be emptyzInvalid memory_id format: zNo valid memory IDs provided)r   detailszQ
        SELECT id, text, chunk_id, document_id, fact_type, context
        FROM memory_unitsz5
        WHERE id = ANY($1) AND bank_id = $2
        Nc                      i | ]}|d          |S r4   rh   rl   rM   s     r   rs   ztool_expand.<locals>.<dictcomp>O  s    555S#d)S555rO   c                 .    g | ]}|d          
|d          S chunk_idrh   rk   s     r   rn   ztool_expand.<locals>.<listcomp>R  s%    BBB1AjMB:BBBrO   zT
            SELECT chunk_id, chunk_text, chunk_index, document_id
            FROM r   z2
            WHERE chunk_id = ANY($1)
            c                      i | ]}|d          |S r   rh   r   s     r   rs   ztool_expand.<locals>.<dictcomp>a  s    <<<cS_c<<<rO   documentc                 .    h | ]}|d          
|d          S )document_idrh   )rl   cs     r   	<setcomp>ztool_expand.<locals>.<setcomp>c  s'    "X"X"XqGW"X1]#3"X"X"XrO   r   r   zF
            SELECT id, original_text, retain_params
            FROM 	documentsz=
            WHERE id = ANY($1) AND bank_id = $2
            c                      i | ]}|d          |S r   rh   r   s     r   rs   ztool_expand.<locals>.<dictcomp>x  s    222c3t9c222rO   )	memory_idr   zMemory not found: r4   textr^   context)r4   r   typer   )r   memory
chunk_textchunk_index)r4   r   indexr   chunkoriginal_textr   )r4   	full_textr   r   )rx   r;   )r   r(   r>   uuidUUID
ValueErrorr?   setaddlistzipr   r   r   rD   )r   r   r   r   r(   valid_uuidserrorsmidr   
memory_map	chunk_idsdoc_ids_from_chunksdoc_ids_direct	chunk_mapr   rm   doc_mapall_doc_idsdocsrx   mem_uuidr   itemr   docs                            r   tool_expandr   "  s     $ )((((( IGHH $&KF = =	=ty~~.... 	= 	= 	=<s<<F3KKK	=  L7FKKK ZZ	h~&&	 	 	
 	       H 65H555J CBBBBI$'EE"uuN !#I Yzz(8$$  
 
 
 
 
 
 
 
 
 =<V<<<	J"X"XV"X"X"X 
 	5 	5AZ= 5Q}%5 5""1]#3444 !G*^;<<K 
3ZZ(;''  
 
 
 
 
 
 
 
 
 32T222 %'GZ55 0 0X&==NNvc{CCDDD)) 	NN7QC7Q7QRRSSS &,''v{+!),	  
  
 * 	&"4	"A"AfZ01EJ'l+}-$]3	 DM 
""u]';w'F'FeM23d)!$_!5 Ec/FZ [ [%(%9	$ $Z  M" 	u
':':vm?TX_?_?_&/0C$i 1A#oBVWW!$_!5	   D 	tW666s   'A  AA)r   Nr   NN)	rP   Nr   NNr   rQ   NN)
r~   Nr   Nr0   r   NTNN)__doc__r   loggingr   dataclassesr   r   r   typingr   r   asyncpgr   api.httpr
   r   r   	getLogger__name__loggerr   r   r   r   floatintrN   r}   boolr   r   rh   rO   r   <module>r      s             ' ' ' ' ' ' ' ' % % % % % % % % -""""""******,,,,,,		8	$	$< <c3hRVAV < < < <* ! $$(b b!b
b b 	b
 %[b b s)d
b b b cT!b 
#s(^b b b bT ! $,0!"#%%)&*O O!OO O &	O
 O s)d
O O O #T/O O !O d?O tOO 
#s(^O O O On ! $ #'%)&*? ?!?? ? &	?
 ? s)d
? ? ? ? ? S	D ? ? d?? tO? 
#s(^? ? ? ?DL7
L7L7 S	L7 	L7
 
#s(^L7 L7 L7 L7 L7 L7rO   