
    `gj?i             
         U 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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mZmZ ddlmZ ddlmZ ddlmZ dd	lmZ  ej4                  e      Zd
ZdZdZdZ dZ!dZ"h dZ#dddddddddd	Z$dQdZ%dZ&dRdZ'dSdZ(dTdZ)i Z*d e+d!<    ejX                         Z-dUd"Z.	 	 dV	 	 	 dWd#Z/	 dX	 	 	 dYd$Z0da1d%e+d&<   da2d'e+d(<    ejX                         Z3 e4       Z5dZd)Z6e fd[d*Z7d+d,d-d.d/d0d.d1d0d2d3d.id4d5d6d7gd8d9Z8d:d;d-d<d.d=d0id<gd8d9Z9d>d?d-d<d.d@d0id<gd8d9Z:d\dAZ;d]dBZ<h dCZ=d^dDZ>d_dEZ?d`dFZ@dadGZAddHdbdIZBdcdJZCddHdddKZDdedLZEdfdMZF G dN dOe      ZGdTdPZHy)gua  Hindsight memory plugin — MemoryProvider interface.

Long-term memory with knowledge graph, entity resolution, and multi-strategy
retrieval. Supports cloud (API key) and local modes.

Configurable request timeout via HINDSIGHT_TIMEOUT env var or config.json.
Configurable embedded daemon idle timeout via HINDSIGHT_IDLE_TIMEOUT env var
or config.json idle_timeout.

Original PR #1811 by benfrank241, adapted to MemoryProvider ABC.

Config via environment variables:
  HINDSIGHT_API_KEY                — API key for Hindsight Cloud
  HINDSIGHT_BANK_ID                — memory bank identifier (default: hermes)
  HINDSIGHT_BUDGET                 — recall budget: low/mid/high (default: mid)
  HINDSIGHT_API_URL                — API endpoint
  HINDSIGHT_MODE                   — cloud or local (default: cloud)
  HINDSIGHT_TIMEOUT                — API request timeout in seconds (default: 120)
  HINDSIGHT_IDLE_TIMEOUT           — embedded daemon idle timeout seconds; 0 disables shutdown (default: 300)
  HINDSIGHT_EMBED_PORT_HEALTH_GRACE_TIMEOUT — seconds to wait for a slow embedded daemon /health before treating it as stale (default: 30; set via config.json port_health_grace_timeout)
  HINDSIGHT_RETAIN_TAGS            — comma-separated tags attached to retained memories
  HINDSIGHT_RETAIN_OBSERVATION_SCOPES — observation scoping for retained memories: per_tag/combined/all_combinations, or a JSON list of tag-lists for custom scopes
  HINDSIGHT_RETAIN_SOURCE          — metadata source value attached to retained memories
  HINDSIGHT_RETAIN_USER_PREFIX     — label used before user turns in retained transcripts
  HINDSIGHT_RETAIN_ASSISTANT_PREFIX — label used before assistant turns in retained transcripts

Or via $HERMES_HOME/hindsight/config.json (profile-scoped), falling back to
~/.hindsight/config.json (legacy, shared) for backward compatibility.
    )annotationsN)datetimetimezone)AnyDictList)MemoryProvider)get_hermes_home)
tool_error)cfg_getz"https://api.hindsight.vectorize.iozhttp://localhost:8888z0.6.1x   i,  z0.5.0>   lowmidhighgpt-4o-minizclaude-haiku-4-5zgemini-2.5-flashzopenai/gpt-oss-120bzqwen/qwen3.5-9bzMiniMax-M2.7z
gemma3:12bzlocal-modelzyour-model-name	openai	anthropicgeminigroq
openrouterminimaxollamalmstudioopenai_compatiblec                    | | dk(  r|S 	 t        |       S # t        t        f$ r t        j	                  d| |       |cY S w xY w)zAParse an integer config/env value, falling back on invalid input. z6Invalid integer Hindsight setting %r; using default %s)int	TypeError
ValueErrorloggerwarning)valuedefaults     T/root/.hermes/venv/lib/python3.12/site-packages/plugins/memory/hindsight/__init__.py_parse_int_settingr&   O   sM    }5zz" OQVX_`s   
 (A A)HINDSIGHT_EMBED_PORT_HEALTH_GRACE_TIMEOUTc                6   | j                  d      }||dk(  ry	 t        |      }|dk  rt        j                  d|       yt        j                  j                  t        t        |             y# t        t        f$ r t        j                  d|       Y yw xY w)an  Export the embedded-daemon health grace timeout to the process env.

    Must run BEFORE ``hindsight_embed.daemon_embed_manager`` is imported,
    because the package reads the env var into a module-level constant at
    import time. We only set it when the user configured a value AND the
    env var isn't already set, so an explicit env override always wins.
    port_health_grace_timeoutNr   z9Invalid Hindsight port_health_grace_timeout %r; ignoring.r   z:Negative Hindsight port_health_grace_timeout %r; ignoring.)getfloatr   r    r!   r"   osenviron
setdefault_PORT_HEALTH_GRACE_ENVrepr)configrawsecondss      r%   !_export_port_health_grace_timeoutr4   d   s     **0
1C
{cRi* {H#	
 	JJ0$w-@ z" G	
 		s   A0 0%BBc                     	 t        j                  d       t        j                  d       y# t        $ r} dt        |       fcY d} ~ S d} ~ ww xY w)aB  Return whether local embedded Hindsight imports cleanly.

    On older CPUs, importing the local Hindsight stack can raise a runtime
    error from NumPy before the daemon starts. Treat that as "unavailable"
    so Hermes can degrade gracefully instead of repeatedly trying to start
    a broken local memory backend.
    	hindsightz$hindsight_embed.daemon_embed_manager)TNFN)	importlibimport_module	Exceptionstr)excs    r%   _check_local_runtimer<      sE    , FG c#hs   *- 	AAAAc                     	 ddl m}   | dd       y# t        $ r Y yt        $ r}t        t	        |            |d}~ww xY w)z>Install the Hindsight cloud client lazily before importing it.r   ensurememory.hindsightFpromptN)tools.lazy_depsr?   ImportErrorr9   r:   )_lazy_ensurer;   s     r%   _ensure_cloud_client_dependencyrF      sA    -:'6  -#c(#,-s    	A A ;A zDict[str, bool]_append_capability_cachec                V    | sy	 ddl m}  ||        ||      k\  S # t        $ r Y yw xY w)uJ   Return True if *actual* ≥ *required* (semver). False on missing/invalid.Fr   Version)packaging.versionrJ   r9   )actualrequiredrJ   s      r%   _meets_minimum_versionrN      s6    -v'("333 s    	((c                X   ddl }ddl}| sy| j                  d      dz   }|j                  j	                  |      }|r|j                  dd|        	 |j                  j                  ||      5 }|j                         j                  dd	
      }ddd       t        j                        }t        |t              sy|j!                  d      xs |j!                  d      }
|
rt#        |
      S dS # 1 sw Y   bxY w# t        $ r!}	t        j                  d||	       Y d}	~	yd}	~	ww xY w)u)  GET ``<api_url>/version`` and return the version string (or None on failure).

    Hindsight's `/version` endpoint returns ``{"version": "0.5.6", ...}``.
    Any failure (timeout, 404, malformed JSON, missing key) → None, which
    the caller treats as "legacy API, no update_mode support".
    r   N/z/versionAuthorizationzBearer timeoututf-8replace)errorsz*Hindsight /version probe failed for %s: %sversionapi_version)urllib.errorurllib.requestrstriprequestRequest
add_headerurlopenreaddecodejsonloadsr9   r!   debug
isinstancedictr*   r:   )api_urlapi_keyrS   urlliburlreqresppayloaddatar;   rW   s              r%   _fetch_hindsight_api_versionro      s    
..


*C
..
 
 
%C''(;<^^##C#9 	DTiik(((CG	Dzz'" dD!hhy!<TXXm%<G"3w<,,	D 	D  A3Ls0   C? 0"C3C? 3C<8C? ?	D)D$$D)c                   | syt         5  | t        v rt        |    cddd       S 	 ddd       t        | |      }t        |t              }t         5  t        j                  |       }|
|t        | <   n|}ddd       |s#t        j                  d| |t        t               |S t        j                  d| |       |S # 1 sw Y   xY w# 1 sw Y   SxY w)u   Cached capability check for ``update_mode='append'`` on *api_url*.

    Probes once per URL per process. Returns False on any probe failure —
    that's the safe default: a per-process unique ``document_id`` and no
    ``update_mode`` keeps the resume-overwrite fix (#6654) intact.
    FNu  Hindsight API at %s reports version %r, older than %s. Falling back to per-process document_id — retains across processes/sessions create separate documents instead of appending to a session-scoped one. Upgrade Hindsight to %s+ to enable update_mode='append' deduplication.z9Hindsight API %s version %s supports update_mode='append')	_append_capability_lockrG   ro   rN   #_MIN_VERSION_FOR_UPDATE_MODE_APPENDr*   r!   r"   rd   )rg   rh   rW   	supportedcacheds        r%   &_check_api_supports_update_mode_appendru      s     	  5..+G45 5.5 +7G<G&w0STI	  )--g6>09$W-I @
 WA/	
  	Pg	'35 5
 s   B:$C:CCz asyncio.AbstractEventLoop | None_loopzthreading.Thread | None_loop_threadc                    t         5  t        #t        j                         rt        cddd       S t        j                         ad } t        j                  | dd      at        j                          t        cddd       S # 1 sw Y   yxY w)z>Return a long-lived event loop running on a background thread.Nc                 ^    t        j                  t               t        j                          y N)asyncioset_event_looprv   run_forever     r%   _runz_get_loop.<locals>._run	  s    ""5)r   Tzhindsight-looptargetdaemonname)	
_loop_lockrv   
is_runningr{   new_event_loop	threadingThreadrw   start)r   s    r%   	_get_loopr     su     
 !1!1!3  &&(	  !''tDGWX  s    BABBc                r    ddl m} t               } || |      }|t        d      |j	                  |      S )z8Schedule *coro* on the shared loop and block until done.r   )safe_schedule_threadsafezHindsight loop unavailablerR   )agent.async_utilsr   r   RuntimeErrorresult)cororS   r   loopfutures        r%   	_run_syncr     s:    :;D%dD1F~788===))r   hindsight_retainzStore information to long-term memory. Hindsight automatically extracts structured facts, resolves entities, and indexes for retrieval.objectstringzThe information to store.)typedescriptionz9Short label (e.g. 'user preference', 'project decision').arrayr   zDOptional per-call tags to merge with configured default retain tags.)r   itemsr   )contentcontexttagsr   )r   
propertiesrM   )r   r   
parametershindsight_recallzSearch long-term memory. Returns memories ranked by relevance using semantic search, keyword matching, entity graph traversal, and reranking.queryzWhat to search for.hindsight_reflectzSynthesize a reasoned answer from long-term memories. Unlike recall, this reasons across all stored memories to produce a coherent response.zThe question to reflect on.c                 `   ddl m}  t               dz  dz  }|j                         r&	 t	        j
                  |j                  d            S | j                         dz  dz  }|j                         r&	 t	        j
                  |j                  d            S t        j                  j                  dd	      t        j                  j                  d
d      t        t        j                  j                  d      t              t        t        j                  j                  d      t              t        j                  j                  dd      t        j                  j                  dd      t        j                  j                  dd      t        j                  j                  dd      t        j                  j                  dd      dt        j                  j                  dd      t        j                  j                  dd      ddid
S # t        $ r Y w xY w# t        $ r Y w xY w)zLoad config from profile-scoped path, legacy path, or env vars.

    Resolution order:
      1. $HERMES_HOME/hindsight/config.json  (profile-scoped)
      2. ~/.hindsight/config.json             (legacy, shared)
      3. Environment variables
    r   Pathr6   config.jsonrT   encoding
.hindsightHINDSIGHT_MODEcloudHINDSIGHT_API_KEYr   HINDSIGHT_TIMEOUTHINDSIGHT_IDLE_TIMEOUTHINDSIGHT_RETAIN_TAGS#HINDSIGHT_RETAIN_OBSERVATION_SCOPESHINDSIGHT_RETAIN_SOURCEHINDSIGHT_RETAIN_USER_PREFIXUser!HINDSIGHT_RETAIN_ASSISTANT_PREFIX	AssistanthermesHINDSIGHT_BANK_IDHINDSIGHT_BUDGETr   T)bankIdbudgetenabled)
modeapiKeyrS   idle_timeoutretain_tagsobservation_scopesretain_sourceretain_user_prefixretain_assistant_prefixbanks)pathlibr   r
   existsrb   rc   	read_textr9   homer,   r-   r*   r&   _DEFAULT_TIMEOUT_DEFAULT_IDLE_TIMEOUT)r   profile_pathlegacy_paths      r%   _load_configr   ]  s     #${2]BL	::l44g4FGG
 ))+,}<K	::k33W3EFF
 

/9**..!4b9%bjjnn5H&IK[\*2::>>:R+SUjkzz~~&=rB jjnn-RTVW(A2F jjnn-KVT#%::>>2UWb#c**..)<hG**..);UC
   		  		s#   $H 4$H  	HH 	H-,H-c                
   | g S t        | t              r| }nt        | t              rr| j                         }|sg S |j	                  d      r;	 t        j                  |      }t        |t              r|}n'|j                  d      }n|j                  d      }n| g}g }t               }|D ]D  }t        |      j                         }|r||v r#|j                  |       |j                  |       F |S # t        $ r d}Y w xY w)zCNormalize tag config/tool values to a deduplicated list of strings.N[,)re   listr:   strip
startswithrb   rc   r9   splitsetaddappend)r#   	raw_itemstextparsed
normalizedseenitemtags           r%   _normalize_retain_tagsr     s    }	 %		E3	{{}I??3D) &$'"	 JJsO	

3IG	J5D $ioocTk# '  s   C4 4DD>   per_tagcombinedall_combinationsc                0   | yt        | t              rP| j                         }|sy|t        v r|S |j	                  d      r!	 t        j                  |      }t        |      S yt        | t        t        f      rt        d | D              r5| D cg c]#  }|j                         s|j                         % }}|r|gS dS g }| D ]  }t        |t        t        f      rU|D cg c]5  }t        |      j                         st        |      j                         7 }}|s\|j                  |       nt        |t              s|j                         s|j                  |j                         g        |xs dS y# t        $ r Y yw xY wc c}w c c}w )u5  Normalize an observation_scopes config value to a Hindsight-accepted form.

    Returns one of:
      * ``None`` — nothing configured; Hindsight applies its ``combined`` default.
      * a keyword string — ``"per_tag"`` / ``"combined"`` / ``"all_combinations"``.
      * ``list[list[str]]`` — custom scopes, one inner list per consolidation pass.

    Accepts a keyword string, a JSON-encoded list, a flat list of tags (treated as
    a single scope), or a list of tag-lists. Anything unrecognized yields ``None``
    so we never send an invalid payload.
    Nr   c              3  <   K   | ]  }t        |t                y wrz   )re   r:   ).0entrys     r%   	<genexpr>z0_normalize_observation_scopes.<locals>.<genexpr>  s     9%z%%9s   )re   r:   r   _OBSERVATION_SCOPE_KEYWORDSr   rb   rc   r9   _normalize_observation_scopesr   tupleallr   )r#   r   r   r   innerscopesr   s          r%   r   r     s`    }%{{}..K??3D) 188%$'959905GuU[[]GEG#E7--"$ 	/E%$/5:Occ#hnn>NS)OOMM%(E3'EKKMu{{}o.	/ ~)   H
 Ps*   E? F'F#FF?	F
Fc                     t        j                  t        j                        j	                  d      j                  dd      S )zHReturn current UTC timestamp in ISO-8601 with milliseconds and Z suffix.milliseconds)timespecz+00:00Z)r   nowr   utc	isoformatrU   r~   r   r%   _utc_timestampr     s2    <<%///HPPQY[^__r   c                D    | j                  dd      }t        |xs d      S )zBReturn the Hindsight embedded profile name for this Hermes config.profiler   )r*   r:   )r1   r   s     r%   _embedded_profile_namer     s"    jjH-Gw"(##r   c                   | j                         si S i }| j                  d      j                         D ]P  }|r|j                  d      sd|vr|j	                  dd      \  }}|j                         ||j                         <   R |S )zEParse a simple KEY=VALUE env file, ignoring comments and blank lines.rT   r   #=   )r   r   
splitlinesr   r   r   )pathvalueslinekeyr#   s        r%   _load_simple_envr    s    ;;=	F0;;= ,ts+s$ZZQ'
U#kkmsyy{	,
 Mr   llm_api_keyc                  |}|F| j                  d      xs3 | j                  d      xs  t        j                  j                  dd      }| j                  dd      }| j                  dd      }| j                  d      xs  t        j                  j                  dd      }|d	v rd
n|}t        |      t        |xs d      t        |      dd}|rt        |      |d<   | j                  d      | j                  d      nt        j                  j                  d      }|!|dk7  rt        t	        |t
                    |d<   |S )zKBuild the profile-scoped env file that standalone hindsight-embed consumes.	llmApiKeyr  HINDSIGHT_LLM_API_KEYr   llm_provider	llm_modelllm_base_urlHINDSIGHT_API_LLM_BASE_URL>   r   r   r   info)HINDSIGHT_API_LLM_PROVIDERHINDSIGHT_API_LLM_API_KEYHINDSIGHT_API_LLM_MODELHINDSIGHT_API_LOG_LEVELr   r   #HINDSIGHT_EMBED_DAEMON_IDLE_TIMEOUT)r*   r,   r-   r:   r&   r   )	r1   r  current_keycurrent_providercurrent_modelcurrent_base_urldaemon_provider
env_valuesr   s	            r%   _build_embedded_profile_envr    sG   KJJ{# ;zz-(;zz~~5r: 	 zz."5JJ{B/Mzz.1eRZZ^^D`bd5e #36Y"Yh_oO '*/&:%():%;#&}#5#)	J 367G3H
/0 ::n%1 	

>"ZZ^^45 
 LB$6<?|-BC=

89 r   c                X    ddl m} |j                         dz  dz  t        |        dz  S )Nr   r   r   profiles.env)r   r   r   r   )r1   r   s     r%   _embedded_profile_env_pathr  !  s/    99;%
28Nv8V7WW[5\\\r   c                   t        |       }|j                  j                  dd       t        | |      }|j	                  dj                  d |j                         D              d       |S )zGWrite the profile-scoped env file that standalone hindsight-embed uses.Tparentsexist_okr  r   c              3  2   K   | ]  \  }}| d | d  yw)r   
Nr~   )r   r  r#   s      r%   r   z4_materialize_embedded_profile_env.<locals>.<genexpr>-  s!     HzsE3%qr"H   rT   r   )r  parentmkdirr  
write_textjoinr   )r1   r  profile_envr  s       r%   !_materialize_embedded_profile_envr*  '  sj    ,V4KTD9,VMJ
HZ5E5E5GHH   r   c                    | syg }d}t        |       D ]F  }|j                         s
|dk(  s|dk(  r|j                  |       d}1|r4|j                  d       d}H dj                  |      j	                  d      S )zSanitize a bank_id_template placeholder value.

    Bank IDs should be safe for URL paths and filesystem use. Replaces any
    character that isn't alphanumeric, dash, or underscore with a dash, and
    collapses runs of dashes.
    r   F-_T-_)r:   isalnumr   r(  r   )r#   out	prev_dashchs       r%   _sanitize_bank_segmentr3  2  sz     
CI%j !::<29c	JJrNI

3 	! 773<d##r   c                   | s|S |j                         D ci c]  \  }}|t        |       }}}	  | j                  di |}d|v r|j                  dd      }d|v rd|v r|j                  dd      }d|v r|j                  d      }|xs |S c c}}w # t        t        f$ r$}t
        j                  d| ||       |cY d}~S d}~ww xY w)	u  Resolve a bank_id template string with the given placeholders.

    Supported placeholders (each is sanitized before substitution):
      {profile}   — active Hermes profile name (from agent_identity)
      {workspace} — Hermes workspace name (from agent_workspace)
      {platform}  — "cli", "telegram", "discord", etc.
      {user}      — platform user id (gateway sessions)
      {session}   — current session id

    Missing/empty placeholders are rendered as the empty string and then
    collapsed — e.g. ``hermes-{user}`` with no user becomes ``hermes``.

    If the template is empty, resolution falls back to *fallback*.
    Returns the sanitized bank id.
    u5   Invalid bank_id_template %r: %s — using fallback %rNz--r,  __r-  r.  r~   )	r   r3  formatKeyError
IndexErrorr!   r"   rU   r   )templatefallbackplaceholderskv	sanitizedrenderedr;   s           r%   _resolve_bank_id_templater@  H  s      :F:L:L:NO$!Q*1--OIO"8??/Y/
 (
##D#. (

(
##D#. (
~~d#Hx P j! Nh	0s"   BB C
&C?C
C
c                  F   e Zd ZdZd%dZd Zed&d       Zd'dZd Z	d(dZ
d Zd	 Zd
 Zd)dZd*dZd*dZd*dZd*dZd Zd&dZd+dZd,dZd&dZddd-dZddd.dZd/dZd0dZdddddd	 	 	 	 	 	 	 	 	 	 	 	 	 d1dZddd2dZd3dZd4d Zdd!d"	 	 	 	 	 	 	 d5d#Z d*d$Z!y)6HindsightMemoryProviderzMHindsight long-term memory with knowledge graph and multi-strategy retrieval.c                p    	 ddl m} |j                         dz  }t        |      gS # t        $ r g cY S w xY w)zHindsight's legacy shared config and embedded-mode profile env
        files live under ~/.hindsight (see _load_config / line ~509).r   r   r   )r   r   r   r:   r9   )selfr   
legacy_dirs      r%   backup_pathsz$HindsightMemoryProvider.backup_pathsp  s;    	$|3J
O$$ 	I	s   $' 55c                   d | _         d | _        t        | _        d| _        d| _        d| _        d| _        d| _        d| _	        g | _
        d| _        d| _        d| _        d| _        d| _        d| _        d| _        d| _        d| _        d| _        d| _        d| _        d	| _        d | _        t2        | _        t6        | _        d| _        t=        j>                         | _         d | _!        tE        jF                         | _$        d | _%        t=        jL                         | _'        d
| _(        d | _)        d| _*        d| _+        d| _,        d | _-        d | _.        d| _/        d| _0        d| _1        d| _2        d| _3        d	| _4        g | _5        d	| _6        d| _7        d| _8        dg| _9        d| _:        d| _;        d| _<        d | _=        d| _>        y )Nr   r   r   r   hybridrecallr   r   r   FanyTr   .conversation between Hermes Agent and the User   observation   )?_config_api_key_DEFAULT_API_URL_api_url_bank_id_budget_mode_llm_base_url_memory_mode_prefetch_method_retain_tags_retain_source_retain_user_prefix_retain_assistant_prefix	_platform_user_id
_user_name_chat_id
_chat_name
_chat_type
_thread_id_agent_identity_agent_workspace_turn_index_clientr   _timeoutr   _idle_timeout_prefetch_resultr   Lock_prefetch_lock_prefetch_threadqueueQueue_retain_queue_writer_threadEvent_shutting_down_atexit_registered_sync_thread_session_id_parent_session_id_document_id_tags_recall_tags_recall_tags_match_auto_retain_retain_every_n_turns_retain_async_retain_context_turn_counter_session_turns_last_retained_turn_count_auto_recall_recall_max_tokens_recall_types_recall_prompt_preamble_recall_max_input_chars_bank_mission_bank_retain_mission_bank_id_templaterD  s    r%   __init__z HindsightMemoryProvider.__init__z  s   ( 
$ (') #) (3%! "(2 "'nn. $
 +0++-7;'oo/"' !"$ (,
.2"' !%&"!O)+ *+& !"& *7')$'*$  04!!#r   c                     y)Nr6   r~   r  s    r%   r   zHindsightMemoryProvider.name  s    r   c                   	 t               }|j                  dd      }|dv rt               \  }}|S |dk(  ryt        |j                  d      xs3 |j                  d      xs  t        j
                  j                  dd	            }t        |j                  d
      xs  t        j
                  j                  dd	            }|xs |S # t        $ r Y yw xY w)Nr   r   >   locallocal_embeddedlocal_externalTr   rh   r   r   rg   HINDSIGHT_API_URLF)r   r*   r<   boolr,   r-   r9   )rD  cfgr   	availabler-  has_keyhas_urls          r%   is_availablez$HindsightMemoryProvider.is_available  s    	.C7767+D2235	1  ''! ;779%;::>>"5r:G
 3779-X@SUW1XYG%g% 		s   .C C BC 	CCc                &   ddl }ddlm}  ||      dz  }|j                  dd       |dz  }i }|j	                         r!	  |j
                  |j                               }|j                  |       ddl	m
}  |||d	
       y# t        $ r Y .w xY w)z3Write config to $HERMES_HOME/hindsight/config.json.r   Nr   r6   Tr  r   )atomic_json_writei  )r   )rb   r   r   r&  r   rc   r   r9   updateutilsr  )	rD  r   hermes_homerb   r   
config_dirconfig_pathexistingr  s	            r%   save_configz#HindsightMemoryProvider.save_config  s     +&4
5 =0%4::k&;&;&=> 	++xe<	  s    B 	BBc           	        ddl }ddl}ddl}ddlm} ddlm} ddlm} ddl	m
}	m}
m} t        d       t        | j                  t               r| j                  n	t#               }t        |t               si }g d}g d	}|j%                  d
      }||v r|j'                  |      nd} |
d|||	      }||	k(  r |        y||   }t!        |      }||d
<   i }dt(         }d}|dk(  r|g}n|dk(  r|g}n|g}d}|dk(  rt+        t,        j/                               }|D cg c]  }|dt,        |    f }}|j%                  d      }||v r|j'                  |      nd} |
d|||	      }||	k(  r |        y||   }||d<   t        d       |j1                  d      }|s6t        d       t        d|j2                   ddj5                  |              n@	 |j7                  |ddd|j2                  ddg|z   dd d|j8                  !       t        d"       |d%k(  rzt        d&       t<        j>                  j%                  d'd      }!|!rtA        |!      d(kD  rd)|!d*d  nd+}"|jB                  jE                  d,|" d-       |jB                  jG                          |jH                  jK                         r |d      n'|jH                  jM                         jO                         }#n|jB                  jE                  d.       |jB                  jG                          |jH                  jK                         r |d      n'|jH                  jM                         jO                         }#|#r|#|d'<   tQ        d/tR         d0      jO                         }$|$r\|$|d1<   nU|dk(  rtQ        d2tT         d0      jO                         }$|$xs tT        |d1<   |jB                  jE                  d3       |jB                  jG                          |jH                  jK                         r |d      n'|jH                  jM                         jO                         }#|#r|#|d'<   n|d4k(  rE|j%                  d5d      }%d6}&|%r	|&d7|% d8z  }&|&d9z  }&tQ        |&      jO                         }$|$r|$|d5<   n
|d:k(  rd;|d5<   t,        j%                  |d<      }'|j%                  d=      xs |'}(tQ        d>|( d0      jO                         }$|$xs |(|d=<   |jB                  jE                  d?       |jB                  jG                          |jH                  jK                         r |d      n'|jH                  jM                         jO                         })|)r|)|d@<   nm ||      dAz  }*d}+|*jW                         rK|*jY                         j[                         D ]*  },|,j]                  dB      s|,j_                  dCdD      dD   }+ n |+|d@<   |ja                  dEdF       |ja                  dGdH       |j%                  dI      }-|-|-ntb        }.|.|dI<   te        |.      |dJ<   |dk(  r.|j%                  dK      }/|/|/ntf        }0|0|dK<   te        |0      |dL<   dM|dN   dO<    ||       | j                  ||       |r= ||      dAz  }*|*jh                  jk                  ddP       g }1|*jW                         r|*jY                         j[                         }1tm               }2g }3|1D ]~  },dC|,v r4|,j]                  dQ      s#|,j_                  dCdD      d   jO                         nd}4|4r/|4|v r+|3jo                  |4 dC||4           |2jq                  |4       n|3jo                  |,        |js                         D ]   \  }5}6|5|2vs|3jo                  |5 dC|6        " |*ju                  dRj5                  |3      dRz          |dk(  rt!        |      }7 ||      dMz  dSz  }8	 tw        jx                  |8jY                  dTU            }7|j%                  d@d      }9|9s$t{         ||      dAz        j%                  d@d      }9|9s$t{        t}        |7            j%                  dVd      }9t        |7|9xs dW       t        dX| dY       |rt        dZ       t        d[       yc c}w # t:        $ rC} t        d#|         t        d$|j2                   ddj5                  |              Y d} ~ d} ~ ww xY w# t:        $ r Y w xY w)\uL   Custom setup wizard — installs only the deps needed for the selected mode.r   Nr   )r  )masked_secret_prompt)
_CANCELLED_curses_select_print_cancelled_setupz!
  Configuring Hindsight memory:
r   r  r  ))Cloudz8Hindsight Cloud API (lightweight, just needs an API key))zLocal Embeddedz7Run Hindsight locally (downloads ~200MB, needs LLM key))zLocal Externalz)Connect to an existing Hindsight instancer   z  Select mode)r$   cancel_returnshindsight-client>=zhindsight-allr  r  r   zdefault model: r	  z  Select LLM providerz
  Checking dependencies...uvuR     ⚠ uv not found — install it: curl -LsSf https://astral.sh/uv/install.sh | shz-  Then run manually: uv pip install --python  pipinstall--python--quiet	--upgradeTr   checkrS   capture_outputstdinu     ✓ Dependencies up to dateu     ⚠ Install failed: z(  Run manually: uv pip install --python r   z9
  Get your API key at https://ui.hindsight.vectorize.io
r      z...r   z  API key (current: z, blank to keep): z  API key: z  API URL [z]: rg   z  Hindsight API URL [z%  API key (optional, blank to skip): r   r  z5  LLM endpoint URL (e.g. http://192.168.1.10:8080/v1)z []: r   zhttps://openrouter.ai/api/v1r   r
  z  LLM model [z  LLM API key: r  r  zHINDSIGHT_LLM_API_KEY=r   r   bank_idr   recall_budgetr   rS   r   r   r   r6   memoryproviderr  r   r#  r   rT   r   r  r  u$   
  ✓ Hindsight memory configured (z mode)z  API keys saved to .envz$
  Start a new session to activate.
)@
subprocessshutilsysr   r   hermes_cli.configr  hermes_cli.secret_promptr  hermes_cli.memory_setupr  r  r  printre   rO  rf   r   r*   index_MIN_CLIENT_VERSIONr   _PROVIDER_DEFAULT_MODELSkeyswhich
executabler(  runDEVNULLr9   r,   r-   lenstdoutwriteflushr  isattyreadliner   inputrQ  _DEFAULT_LOCAL_URLr   r   r   r   r   r.   r   r:   r   r%  r&  r   r   r   r   r'  rb   rc   r  r  r*  ):rD  r  r1   r  r  r  r   r  r  r  r  r  existing_configmode_values
mode_itemsexisting_modemode_default_idxmode_idxr   provider_config
env_writes	cloud_dep	local_depdeps_to_installr	  providers_listp	llm_itemsexisting_llm_providerllm_default_idxllm_idxuv_patheexisting_keymaskedrh   valexisting_base_urlrB   provider_default_modelr  llm_keyenv_pathexisting_llm_keyr  existing_timeouttimeout_valexisting_idle_timeoutidle_timeout_valexisting_linesupdated_keys	new_lines	key_matchr<  r=  materialized_configr  r  s:                                                             r%   
post_setupz"HindsightMemoryProvider.post_setup  s7	    1A^^34*4T\\4*H$,,ln/40 O D


 (++F3?LP[?[;,,];ab!/:GWhrsz!"$8$ $_ 5"&
 ))<(=>	#	##(kO%%(kO(kO##!":"?"?"ABN ( o&>q&A%BCDI  %4$7$7$G!MbftMtn223HIz{O$'')	G *$&()'2L.:ON+,-,,t$fgA#..AQQRSVS[S[\kSlRmno	oeY
CNNIWbcfuuD$,,  
 56 7?OP::>>*=rBL69,6G!6K3|BC012QV

  #7x?Q!RS

  "69ii6F6F6H.r2ciiN`N`NbNhNhNj

  /

  "69ii6F6F6H.r2ciiN`N`NbNhNhNj29
./+&6%7s;<BBDC-0	*%%/0B/C3GHNNPC),)B0BOI&JJDEJJ25))2B2B2D*2.#))J\J\J^JdJdJfG29
./ 22$3$7$7$K!P$#4"5Q77F$Fm))+69ON3-2P/%=%A%A,P]%^"+//<V@VM-c:;AACC+.+?-OK(JJ./JJ25))2B2B2D*2.#))J\J\J^JdJdJfG6=
23,v5#% ??$ ( 2 2 4 ? ? A "??+CD/3zz#q/A!/D,!" 7G
23 	""9h7""?E: +..y9*:*F&L\%0	"*-k*:
&'##$3$7$7$G!8M8Y4_t.>ON+367G3HJ/0'2x$F+6K(61HOO!!$!>N !)!3!3!5!@!@!B5LI& +=@D[QUQ`Q`adQeDJJsA.q1779ko	j!8$$	{!Jy4I3J%KL $$Y/$$T*+ #((* 11L($$s!A3Z01 		) 4t ;<##"&"7{+k9MIK&*jj1F1FPW1F1X&Y# %..)@"EK.tK/@6/IJNNOfhjk./IJ]/^_cc/
 .#'/4
 	5dV6BC,-67E>  o.qc23@@PPQRURZRZ[jRkQlmnno^  s0   b+?b0 /%c? 0	c<98c77c<?	d
dc                >   g dddg ddddt         ddidd	d
dddddidddt        ddidd	dddddiddddg dddidddddddddddd ddidd!d"d#dt        d$ddid%d&d'd(d)d*d+dd)d,d-d.d/d0d.d1d2d3g d4dd5d6d7g d8dd9d:d;d;d<gdd=d>dd)d?d@dd)dAdBdd)dCdDdEd)dFdGdHd)dIdJdd)dKdLdMg dNddOdPdQd)dRdSdd)dTdUdd)dVdWdXd)dYdZdd)d[d\d]d)d^d_d`d)dadbdcd)ddded.dfdgt        d)dhdit        ddiddjdkdddidS )lNr   zConnection moder   r  )r  r   r$   choicesrg   zHindsight Cloud API URL)r  r   r$   whenrh   zHindsight Cloud API keyTr   z!https://ui.hindsight.vectorize.io)r  r   secretenv_varrj   r  zHindsight API URLr  zAPI key (optional))r  r   r  r  r  r	  zLLM providerr   r   r  )r  r   r$   r  r  r  z/Endpoint URL (e.g. http://192.168.1.10:8080/v1)r   r   )r   r	  r  z,LLM API key (optional for openai_compatible)r  r
  z	LLM modelr   )fieldmap)r  r   r$   default_fromr  r  zAMemory bank name (static fallback when bank_id_template is unset)r   )r  r   r$   bank_id_templatezOptional template to derive bank_id dynamically. Placeholders: {profile}, {workspace}, {platform}, {user}, {session}. Example: hermes-{profile}bank_missionz/Mission/purpose description for the memory bank)r  r   bank_retain_missionz-Custom extraction prompt for memory retentionr  zRecall thoroughnessr   )r   r   r   memory_modezMemory integration moderH  )rH  r   toolsrecall_prefetch_methodzAuto-recall methodrI  reflectr   z;Default tags applied to retained memories (comma-separated)r   u(  How observations are scoped during consolidation: 'combined' (default — one pass over all tags), 'per_tag' (one isolated observation per tag), 'all_combinations' (every tag subset — expensive), or a JSON list of tag-lists for explicit custom scopes. Empty uses Hindsight's 'combined' default.r   z3Metadata source value attached to retained memoriesr   z4Label used before user turns in retained transcriptsr   r   z9Label used before assistant turns in retained transcriptsr   recall_tagsz8Tags to filter when searching memories (comma-separated)recall_tags_matchzTag matching mode for recallrJ  )rJ  r   
any_strict
all_strictrecall_typesu  Fact types to surface on recall — applies to both auto-recall and the hindsight_recall tool (comma-separated or list). Defaults to observation-only — observations are Hindsight's consolidated, deduplicated, evidence-grounded knowledge layer; raw world/experience facts are the supporting evidence observations already summarize. Set to e.g. 'observation,world,experience' to also include raw facts.rM  auto_recallz.Automatically recall memories before each turnauto_retainz'Automatically retain conversation turnsretain_every_n_turnsz%Retain every N turns (1 = every turn)r   retain_asyncz5Process retain asynchronously on the Hindsight serverretain_contextz#Context label for retained memoriesrK  recall_max_tokensz!Maximum tokens for recall resultsrL  recall_max_input_charsz*Maximum input query length for auto-recallrN  recall_prompt_preamblez0Custom preamble for recalled memories in contextrS   zAPI request timeout in secondsr   zBEmbedded daemon idle timeout in seconds (0 disables auto-shutdown)r)   zSeconds to wait for a slow daemon /health before treating it as stale (raise on busy/low-resource hosts; blank uses the 30s default))rQ  r  r  r   r   r  s    r%   get_config_schemaz)HindsightMemoryProvider.get_config_schema  s)   '
+<  ^K  L'
 .GTdouw~n  A'
 .GSWdw  Ad  ou  w~  n  @	'
 .AN`kq  tD  kE  F'
 .Bd_r  ~D  FV  }W  X'
 #>h  dQ  \b  dt  [u  v'
 #3dqs  GW  i|  ~}  ~'
 "2`lp  ~U  `f  hx  _y  z'
  q  Ia  hb  ms  uE  lF  G'
 .q  G  H'
 '  8I  VX  Y'
 #3de'
  *:ij!'
" $4IV[h~#'
$ "2KX`  nL  M%'
& -=Q^ft|  H  tI  J''
( "2o|~)'
* )  :d  qs  t+'
, $4ivxy-'
. )9o  }C  D/'
0 .>y  GR  S1'
2 "2ly{|3'
4 (8Vch  v`  a5'
6 #  4H  Ub  c7'
8 "2bost9'
: "2[hlm;'
< +;bopq='
> #2ivz{?'
@ %5Z  hX  YA'
B (8[hlmC'
D -=ivyzE'
F -=opG'
H .N[klI'
J #3w  EZ  ek  m}  d~  K'
L 0  AG  TV  ag  iy  `z  {M'
 '	
r   c           	        | j                   | j                  dk(  rt               \  }}|st        d|rd| z         dz         	 ddlm}  |dd	
       ddl	m
} d |_        | j                  j                  dd      }|dv rd}t        j                  d| j                  j                  dd      |       t!        | j                  j                  dd      || j                  j                  d      xs= | j                  j                  d      xs  t"        j$                  j                  dd      | j                  j                  dd            }| j&                  r| j&                  |d<   t)        | j                  j                  d      | j                  j                  d      n)t"        j$                  j                  d| j*                        t,              }|| _        ||d<    |d i || _         | j                   S t/                ddlm}	 | j4                  xs t6        }
| j8                  t;        |
      d}| j<                  r| j<                  |d<   t        j                  d| j8                  t?        | j<                        |d           |	d i || _         | j                   S # t        $ r Y ^t        $ r}t        t        |            d}~ww xY w)!z:Return the cached Hindsight client (created once, reused).Nr  z&Hindsight local runtime is unavailabler  r   r   r>   r@   FrA   )HindsightEmbeddedc                     y rz   r~   r  s    r%   <lambda>z5HindsightMemoryProvider._get_client.<locals>.<lambda>  s    r   r	  >   r   r   r   z;Creating HindsightEmbedded client (profile=%s, provider=%s)r   r   r  r  r  r
  )r   r	  r  r
  r  r   r   )	Hindsight)base_urlrS   rh   z@Creating Hindsight cloud client (url=%s, has_key=%s, timeout=%s)rS   r~   ) rg  rU  r<   r   rC   r?   rD   r9   r:   r6   r  __del__rO  r*   r!   rd   rf   r,   r-   rV  r&   ri  r   rF   hindsight_clientr  rh  r   rR  r+   rP  r  )rD  r  reasonrE   _er  r	  kwargsr   r  rS   s              r%   _get_clientz#HindsightMemoryProvider._get_client  s   <<zz--$8$:!	6 &@,2Rx=< 8:< /F !3EB
 8,=!)#||//C#FF#+LZ!\\--iBLR LL,,YA!- $ 0 0 =  !PAQAQR_A`  !Pdfdndndrdr  tK  MO  eP"ll..{B?	 %%-1-?-?F>*1||''7C LL$$^4(@$BTBTU)	  &2")5~&0:6: || 016--;+;&*mmgO==(,F9%_!]]D,?	ART(262||M #   /%c"g../s   	J+ +	K7K?KKc                0    t        || j                        S )z@Schedule *coro* on the shared loop using the configured timeout.rR   )r   rh  )rD  r   s     r%   r   z!HindsightMemoryProvider._run_sync)  s    t}}55r   c                    | j                   dk7  ryt        |      j                   d| j                         t	        fddD              S )z:Return True for stale embedded-daemon connection failures.r  Fr  c              3  &   K   | ]  }|v  
 y wrz   r~   )r   markerr   s     r%   r   zRHindsightMemoryProvider._is_retriable_embedded_connection_error.<locals>.<genexpr>2  s      
 dN
s   )zcannot connect to hostzconnection refusedzconnect call failedclientconnectorerror)rU  r   __name__lowerrJ  )rD  r;   r   s     @r%   '_is_retriable_embedded_connection_errorz?HindsightMemoryProvider._is_retriable_embedded_connection_error-  sS    ::))s)$$%Ru-335 

 
 	
r   c                    | j                   }||j                         ry| j                  j                          t	        j
                  | j                  dd      }|| _         || _        |j                          y)zLazy-start the single retain-writer thread.

        We don't start the writer in initialize() so providers that never
        retain (e.g. tools-only mode) don't pay for an idle thread.
        NTzhindsight-writerr   )	rq  is_alivers  clearr   r   _writer_loopru  r   )rD  threads     r%   _ensure_writerz&HindsightMemoryProvider._ensure_writer<  sq     $$&//"3 	!!#!!$$#

 % #r   c                   	 	 | j                   j                  d      }	 |t        u r	 | j                   j                          y	  |        | j                   j                          e# t        j                  $ r | j                  j                         rY yY w xY w# t        $ r"}t        j                  d|d       Y d}~vd}~ww xY w# | j                   j                          w xY w)zDrain the retain queue serially. Exits on sentinel.

        Each job() is wrapped so a single failure can't kill the writer.
        task_done() always fires so queue.join() works in tests.
        Tg      ?rR   NzHindsight retain failed: %sexc_info)rp  r*   rn  Emptyrs  is_set_WRITER_SENTINEL	task_doner9   r!   r"   )rD  jobr;   s      r%   r.  z$HindsightMemoryProvider._writer_loopS  s     ((,,S,9
/** "",,.VE "",,.  ;; &&--/ ! VNN#@#PTNUUV "",,.s@   A' C
 B '-BB	C%C=C
 CC
 
C&c                j    | j                   ryd| _         t        j                  | j                         y)a?  Register an idempotent atexit hook to drain the writer.

        Without this, a CLI exit that doesn't go through MemoryManager.
        shutdown_all() would leave in-flight retain jobs racing interpreter
        teardown, producing "cannot schedule new futures" warnings and
        unclosed aiohttp sessions.
        NT)rt  atexitregister_atexit_shutdownr  s    r%   _register_atexitz(HindsightMemoryProvider._register_atexitj  s*     """&--.r   c                    | j                   j                         ry 	 | j                          y # t        $ r }t        j                  d|       Y d }~y d }~ww xY w)Nz$Hindsight atexit shutdown failed: %s)rs  r5  shutdownr9   r!   rd   )rD  r;   s     r%   r<  z(HindsightMemoryProvider._atexit_shutdownw  sJ    %%'	FMMO 	FLL?EE	Fs   . 	AAAc                8   | j                         }	 | j                   ||            S # t        $ rg}| j                  |      s t        j                  d|       d| _        | j                         }|| _        | j                   ||            cY d}~S d}~ww xY w)zKRun an async Hindsight client operation, retrying once after idle shutdown.zVHindsight embedded daemon appears unreachable; recreating client and retrying once: %sN)r"  r   r9   r*  r!   r  rg  )rD  	operationclientr;   s       r%   _run_hindsight_operationz0HindsightMemoryProvider._run_hindsight_operation  s    !!#	5>>)F"344 
	5??DKKh  DL%%'F!DL>>)F"344
	5s   ) 	BABBBc                    | j                   dk(  r0| j                  $t        | j                  dd      }|rt        |      S | j                  xs dS )zReturn the URL to probe /version on.

        For local_embedded the daemon is on a per-profile dynamic port,
        so we prefer the running client's URL when available; otherwise
        fall back to the configured api_url.
        r  Nrj   r   )rU  rg  getattrr:   rR  )rD  rj   s     r%   
_probe_urlz"HindsightMemoryProvider._probe_url  sG     ::))dll.F$,,t4C3x}}""r   c                    | j                   s|dfS t        | j                         | j                        r| j                   dfS |dfS )u  Pick (document_id, update_mode) based on live API capability.

        On Hindsight ≥ 0.5.0 the API supports ``update_mode='append'``,
        which lets us reuse a stable session-scoped ``document_id`` across
        process lifecycles without overwriting prior turns. On older APIs
        we fall back to *fallback_document_id* (the per-process unique
        ``f"{session_id}-{start_ts}"`` minted at initialize / switch time)
        and don't pass ``update_mode`` at all — that's the only way the
        resume-overwrite fix (#6654) keeps working on legacy servers.

        Probe is cached at module level per API URL, so this is one HTTP
        round-trip per (process, api_url) pair regardless of how many
        retains fire.
        Nr   )rv  ru   rF  rP  )rD  fallback_document_ids     r%   _resolve_retain_targetz.HindsightMemoryProvider._resolve_retain_target  sI     '--1$//2CT]]S##X--#T))r   c                    t        |xs d      j                          _        t        |j                  dd      xs d      j                          _        t        j                         j                  d      } j                   d|  _        	 ddl	m
} ddlm}  |d      } ||       |t              k  rt        j                  d	|t               dd l}dd l}dd l}	|j'                  d
      }
|
rU	 |j)                  |
ddd|	j*                  dddt         gddd|j,                         t        j/                  dt               nt        j                  dt               t3                _        t        |j                  d      xs d      j                          _        t        |j                  d      xs d      j                          _        t        |j                  d      xs d      j                          _        t        |j                  d      xs d      j                          _        t        |j                  d      xs d      j                          _        t        |j                  d      xs d      j                          _         t        |j                  d      xs d      j                          _!        t        |j                  d      xs d      j                          _"        t        |j                  d      xs d      j                          _#        d _$        g  _%        d _&         j4                  j                  d d!       _'        tQ         j4                  j                  d"       j4                  j                  d"      ntR        jT                  j                  d#      tV               _,        tQ         j4                  j                  d$       j4                  j                  d$      ntR        jT                  j                  d%      tZ               _.         jN                  d&k(  rd' _'         jN                  d'k(  rBt_         j4                         ta               \  }}|st        j                  d(|       d) _'        y  j4                  j                  d*      xs=  j4                  j                  d+      xs  tR        jT                  j                  d,d       _1         jN                  d-v rtd        ntf        } j4                  j                  d.      xs  tR        jT                  j                  d/|       _4         j4                  j                  d0d       _5        tm         j4                  d1d2i 3      } j4                  j                  d4      xs |j                  d5d2      } j4                  j                  d6d      xs d _7        tq         jn                  | jD                   jF                   j6                   j8                   j                  7       _9         j4                  j                  d8      xs/  j4                  j                  d9      xs |j                  d9d:      }|tt        v r|nd: _;         j4                  j                  d;d<      }|d=v r|nd< _<         j4                  j                  d>      xs  j4                  j                  d?d@      }|dAv r|nd@ _=         j4                  j                  dBd       _>         j4                  j                  dC      xs d  _?        t         j4                  j                  dD      xs  tR        jT                  j                  dEd             _A         j                  xs d  _B        t         j4                  j                  dF      xs  tR        jT                  j                  dGd             _D         j4                  j                  dH      xs d  _E         j4                  j                  dIdJ       _F        t         j4                  j                  dK      xs  tR        jT                  j                  dLd            j                          _G        t         j4                  j                  dM      xs  tR        jT                  j                  dNdO            j                         xs dO _H        t         j4                  j                  dP      xs  tR        jT                  j                  dQdR            j                         xs dR _I         j4                  j                  dSd       _J        t        dTt         j4                  j                  dUdT                   _M         j4                  j                  dVdW       _N         j4                  j                  dXd       _O        t         j4                  j                  dYdZ             _P         j4                  j                  d[      }|	d\g _Q        nit        |t               rD|j                  d]      D cg c]#  }|j                         s|j                         % c} _Q        nt        |      xs d\g _Q         j4                  j                  d^d       _U        t         j4                  j                  d_d`             _V         j4                  j                  dad       _W        db}	 ddl	m
}  |d      }t        j/                  dc jN                   jh                   jr                   jv                   jx                   jz                  |        jn                  rWt        j                  dd jn                   jD                   jF                   j6                   j8                   jr                         t        j                  de j                   j                   j                   j                   j                   j                   j                   j                   j                  
        jN                  d'k(  rt        tR        df      rRtS        j                         dk(  r;dg}t        j                  |       	 t        dh| 	j                  di       d) _'        y  fdj}t        j                  |ddkl      }|j                          y y # t0        $ r&}t        j                  d|t               Y d }~d }~ww xY w# t0        $ r Y w xY wc c}w # t0        $ r Y &w xY w# t0        $ r
 Y d) _'        y w xY w)mNr   parent_session_id%Y%m%d_%H%M%S_%fr,  r   )rW   rI   zhindsight-clientzBhindsight-client %s is outdated (need >=%s), attempting upgrade...r  r  r  r  r  r  r  Tr   r  z!hindsight-client upgraded to >=%szCAuto-upgrade failed: %s. Run: uv pip install 'hindsight-client>=%s'z5uv not found. Run: pip install 'hindsight-client>=%s'platformuser_id	user_namechat_id	chat_name	chat_type	thread_idagent_identityagent_workspacer   r   rS   r   r   r   r  r  zKHindsight local mode disabled because its runtime could not be imported: %sdisabledr   rh   r   >   r  r  rg   r  r  r   r   )r$   r  r   r  )r:  r   	workspacerM  usersessionr  r   r   r  rH  >   r  rH  r   r  prefetch_methodrI  >   rI  r  r  r  r   r   r   r   r	  r
  rJ  r   r   r   r   r   r   r   r   r  r   r  r  rK  r  r  rL  r  rM  r   r  r  rN  r  unknownzmHindsight initialized: mode=%s, api_url=%s, bank=%s, budget=%s, memory_mode=%s, prefetch_method=%s, client=%sz`Hindsight bank resolved from template %r: profile=%s workspace=%s platform=%s user=%s -> bank=%szHindsight config: auto_retain=%s, auto_recall=%s, retain_every_n=%d, retain_async=%s, retain_context=%s, recall_max_tokens=%d, recall_max_input_chars=%d, tags=%s, recall_tags=%sgeteuidzHindsight local_embedded mode cannot run as root (PostgreSQL initdb refuses root). Skipping the embedded memory daemon. Run Hermes as a non-root user, or switch to cloud / local_external mode via 'hermes memory setup'.u     ⚠ )filer  c                    dd l } t               dz  }|j                  dd       |dz  }	 dd lm} ddlm}  |t        |dd	      d
      |_        j                         }j                  j                  dd      }t        j                        }t        j                        }t        |      }	|	|k7  }
|
rst        j                        }|j                   j#                  |      rCt        |dd	      5 }|j%                  d       d d d        |j                   j'                  |       |j)                          t        |dd	      5 }|j%                  d       d d d        y # 1 sw Y   ]xY w# 1 sw Y   y xY w# t*        $ rZ}t        |dd	      5 }|j%                  d| d       | j-                  |       d d d        n# 1 sw Y   nxY wY d }~y Y d }~y d }~ww xY w)Nr   logsTr  zhindsight-embed.log)ConsolearT   r   F)r]  force_terminalr   r   z+
=== Config changed, restarting daemon ===
z%
=== Daemon started successfully ===
z
=== Daemon startup failed: z ===
)r]  )	tracebackr
   r&  $hindsight_embed.daemon_embed_managerdaemon_embed_managerrich.consoler`  openconsoler"  rO  r*   r  r  r  r*  _managerr   r  stop_ensure_startedr9   	print_exc)rc  log_dirlog_pathdemr`  rB  r   r)  expected_envsavedconfig_changedfr  rD  s                r%   _start_daemonz9HindsightMemoryProvider.initialize.<locals>._start_daemonz  s    )+f4dT:"%:: 4 G4")tHcG/Tej"kCK!--/F"ll..y(CG
 #=T\\"JK#>t||#LL,[9E%*l%:N%&G&U!??55g>!%hg!F Y! !(W XY"OO009**,hg> K! IJK KY Y
K K  4hg> 4!"?s& IJ!+++34 4 4 4 44sg   CE? 9E'AE? E3E? 'E0,E? 3E<8E? <E? ?	G"G(G>	GG	GG"zhindsight-daemon-startr   )`r:   r   rv  r*   rw  r   r   strftimerx  importlib.metadatarW   rK   rJ   r  r!   r"   r  r  r  r  r  r  r  r  r9   r   rO  r]  r^  r_  r`  ra  rb  rc  rd  re  rf  r  r  rU  r&   r,   r-   r   rh  r   ri  r4   r<   rP  r  rQ  rR  rV  r   r  r@  rS  _VALID_BUDGETSrT  rW  rX  r  r  r   rY  ry  r   _observation_scopesrz  r{  rZ  r[  r\  r|  maxr   r}  r  r  r  r  re   r   r   r  r  r~  rd   hasattrr\  r  stderrr   r   r   )rD  
session_idr!  start_tspkg_versionrJ   	installedr  r  r  r  r  r  r  default_urlr   static_bank_idr   r  rZ  configured_typest_client_versionmsgrt  s   `                        r%   
initializez"HindsightMemoryProvider.initialize  s
   z/R0668"%fjj1Db&I&OR"P"V"V"X <<>**+=>#//0(<	A1#$67Iy!G,?$@@c(*=?! ,,t,
?"$eY
CNN&7IJ]I^5_a"&D","4"4	 '  $GI\]
 NN#Z\op $~VZZ
39r:@@BFJJy17R8>>@fjj5;<BBDFJJy17R8>>@fjj5;<BBDfjj5;<BBDfjj5;<BBD"6::.>#?#E2FLLN #FJJ/@$A$GR H N N P )*&\\%%fg6
*+/<<+;+;I+F+RDLLY'XZXbXbXfXfgzX{
 0040@0@0P0\DLL^,bdblblbpbp  rJ  cK!

 :: )DJ::)) .dll; 4 6Iva (
((2|dll6F6Fy6Q|UWU_U_UcUcdwy{U|,0JJ:^,^(dt((3grzz~~FY[f7g!\\--nbAgxD)))4U		(H8U!%!1!12Db!I!OR1""#((++^^$$
 !!/2ndll6F6Fx6PnTYT]T]^fhmTn!'>!9vull&&}h?+6:X+XK^f,,**+CDuHXHXYjltHu3BF[3[ai "\\--nbA$(LL$4$45J$K$St! 3LL]+ ;zz~~5r:
 &&.$
#@LL12 Izz~~CRH$
  !LL,,];Ct"&,,"2"23F"N!LL_-^@Y[]1^

%' 	 $'LL12lbjjnnEcek6l$

%'$ 	  ),LL67{2::>>Jmoz;{)

%')!  	%
 !LL,,]DA%(C0@0@AWYZ0[,\%]"#||//0@Brs !LL,,]DA"%dll&6&67JD&Q"R  <<++N;#"/D(#.5E5K5KC5P!^TUT[T[T]!'')!^D!%&6!7!JM?D'+||'7'78PRT'U$'*4<<+;+;<TVY+Z'[$!\\--ndC#	A)*<=O 	  DZZt||TM^M^`d`u`u  xG	H!!LL{//1E1EtG\G\G 	 D&&(9(94;U;U'')=)=t?V?VX\XtXtZZ!2!2		4 ::)) r9%"**,!*;P  s#F3%.szzF (
%4N   dIabAGGIC *] % ?'l'(*=? ??
  		Z "_  		J ! '
sn   A#t 4As' t t)'t)t. t> '	t0tt tt 	t&%t&.	t;:t;>	uuc                    | j                   dk(  rd| j                   d| j                   dS | j                   dk(  rd| j                   d| j                   dS d| j                   d| j                   d	S )
Nr   z0# Hindsight Memory
Active (context mode). Bank: z
, budget: z<.
Relevant memories are automatically injected into context.r  z.# Hindsight Memory
Active (tools mode). Bank: zc.
Use hindsight_recall to search, hindsight_reflect for synthesis, hindsight_retain to store facts.z!# Hindsight Memory
Active. Bank: z.
Relevant memories are automatically injected into context. Use hindsight_recall to search, hindsight_reflect for synthesis, hindsight_retain to store facts.)rW  rS  rT  r  s    r%   system_prompt_blockz+HindsightMemoryProvider.system_prompt_block  s    	)004j WMN
 '..2mm_Jt||n U34!]]O:dll^ D/0	
r   r   )r|  c                  | j                   rK| j                   j                         r1t        j                  d       | j                   j	                  d       | j
                  5  | j                  }d| _        d d d        st        j                  d       yt        j                  dt        |             | j                  xs d}| d| S # 1 sw Y   WxY w)	Nz3Prefetch: waiting for background thread to complete      @rR   r   zPrefetch: no results availablez'Prefetch: returning %d chars of contextz# Hindsight Memory (persistent cross-session context)
Use this to answer questions about the user and prior sessions. Do not call tools to look up information that is already present here.z

)	rm  r,  r!   rd   r(  rl  rj  r  r  )rD  r   r|  r   headers        r%   prefetchz HindsightMemoryProvider.prefetch  s      T%:%:%C%C%ELLNO!!&&s&3   	'**F$&D!	' LL9:>FL-- 
U 	
 fX&&	' 	's   $CCc                    j                   dk(  rt        j                  d       y  j                  st        j                  d       y  j                  j                         rt        j                  d       y  j                  r't               j                  kD  rd  j                    fd}t        j                  |dd       _
         j                  j                          y )	Nr  z#Prefetch: skipped (tools-only mode)z(Prefetch: skipped (auto_recall disabled)z!Prefetch: skipped (shutting down)c                    	 j                   dk(  rQt        j                  dj                  t	                     j                  fd      } | j                  xs d}nj                  j                  j                  dj                  rj                  d<   j                  d<   j                  rj                  d<   t        j                  d	j                  t	              j                         j                  fd
      } | j                  rt	        | j                        nd}t        j                  d|       | j                  r"dj                  d | j                  D              nd}|rj                  5  |_        d d d        y y # 1 sw Y   y xY w# t         $ r"}t        j                  d|d       Y d }~y d }~ww xY w)Nr  z1Prefetch: calling reflect (bank=%s, query_len=%d)c                T    | j                  j                  j                        S N)r  r   r   areflectrS  rT  rB  r   rD  s    r%   r  zFHindsightMemoryProvider.queue_prefetch.<locals>._run.<locals>.<lambda>  s5    `d`m`muz  DH  DP  DP  IQ r   r   r  r   r   
max_tokensr   
tags_matchtypesz;Prefetch: calling recall (bank=%s, query_len=%d, budget=%s)c                (     | j                   di S Nr~   arecallrB  recall_kwargss    r%   r  zFHindsightMemoryProvider.queue_prefetch.<locals>._run.<locals>.<lambda>  s    HgYfHg r   r   z$Prefetch: recall returned %d resultsr#  c              3  T   K   | ]   }|j                   sd |j                     " yw)z- N)r   )r   rs     r%   r   zGHindsightMemoryProvider.queue_prefetch.<locals>._run.<locals>.<genexpr>  s      $SqAFFr!&&]$Ss   ((zHindsight prefetch failed: %sTr2  )rX  r!   rd   rS  r  rC  r   rT  r  rz  r{  r  resultsr(  rl  rj  r9   )rl   r   num_resultsr  r  r   rD  s       @r%   r   z4HindsightMemoryProvider.queue_prefetch.<locals>._run  s   P((I5LL!TVZVcVcehineop88  :Q  RD99?D $(==5"&,,d>U>U+M ((040A0Af-6:6M6Ml3))151C1Cg.LL!^!%E
DLLJ889ghD7;||#dll"3KLL!GUW[WcWc499$SDLL$SSikD,, 504-5 5 5 5 P<a$OOPs6   F
F, F F,  F)%F, )F, ,	G5GGTzhindsight-prefetchr   )rW  r!   rd   r  rs  r5  r  r  r   r   rm  r   )rD  r   r|  r   s   ``  r%   queue_prefetchz&HindsightMemoryProvider.queue_prefetch  s    'LL>?  LLCD%%'LL<=''CJ9U9U,U74778E	P8 !* 0 0TPd e##%r   c                    t        j                  t        j                        j	                         }d| j
                   d| |dd| j                   d| |dgS )NrX  r  )roler   	timestamp	assistant)r   r   r   r   r   r[  r\  )rD  user_contentassistant_contentr   s       r%   _build_turn_messagesz,HindsightMemoryProvider._build_turn_messages  sm    ll8<<(224 "667r,H  $";;<B?P>QR 
 	
r   c               b   t               t        |      t        |      d}| j                  r| j                  |d<   | j                  r| j                  |d<   | j                  r| j                  |d<   | j
                  r| j
                  |d<   | j                  r| j                  |d<   | j                  r| j                  |d<   | j                  r| j                  |d<   | j                  r| j                  |d	<   | j                  r| j                  |d
<   | j                  r| j                  |d<   |S )N)retained_atmessage_count
turn_indexsourcer|  rM  rN  rO  rP  rQ  rR  rS  rT  )r   r:   rZ  rv  r]  r^  r_  r`  ra  rb  rc  rd  )rD  r  r  metadatas       r%   _build_metadataz'HindsightMemoryProvider._build_metadata  s   )+ /j/$

 !%!4!4HX%)%5%5H\">>#'>>HZ =="&--HY??$(OOH[!=="&--HY??$(OOH[!??$(OOH[!??$(OOH[!)-)=)=H%&r   N)r   document_idr  r   r  c               H   | j                   ||xs | j                  d| j                        d}|||d<   |r||d<   |||d<   t        | j                        }t        |      D ]  }	|	|vs|j                  |	        |r||d<   | j                  r| j                  |d<   |S )	Nr   r  r  )r  r   r  r   r  r  r   r   )rS  r  rf  r   rY  r   rx  )
rD  r   r   r  r  r   r  r!  merged_tagsr   s
             r%   _build_retain_kwargsz,HindsightMemoryProvider._build_retain_kwargs$  s     }} fD$8$8qUYUeUe$8$f"

  'F9$/F=!#%1F>",T->->?)$/ 	(C+%""3'	( (F6N##+/+C+CF'(r   c               b   	
  j                   st        j                  d       y j                  j	                         rt        j                  d       y|rt        |      j                          _        t        j                   j                  ||      d      } j                  j                  |        xj                  dz  c_         j                   _         j                   j                  z  dk7  rSt        j                  d j                   j                   j                   j                   j                  z  z
  z          y j!                   j"                        \  	d	k(  r1 j                   j$                  d }|s+t        j                  d
       yt'         j                        }t        j                  dt)        |      t)         j                        t+        d |D                     ddj-                  |      z   dz   g 
 j                  r
j                  d j                           j.                  r
j                  d j.                           j1                  t)        |      dz   j                        t)        |       j2                   j4                   j6                  d	
 f
d} j9                           j;                           j<                  j?                  |       d	k(  rt)         j                         _        yy)ue  Enqueue a retain for the current turn. Non-blocking.

        The actual aretain_batch runs on a single long-lived writer thread
        that drains an in-memory queue. Once shutdown() has been called,
        further sync_turn() calls are dropped — this prevents post-exit
        retains from reaching aiohttp after interpreter shutdown begins.
        z)sync_turn: skipped (auto_retain disabled)Nz"sync_turn: skipped (shutting down)F)ensure_asciir   r   z4sync_turn: buffered turn %d (will retain at turn %d)r   z@sync_turn: skipped append retain; no new turns since last retainz2sync_turn: retaining %d/%d turns, payload %d charsc              3  2   K   | ]  }t        |        y wrz   )r  )r   r  s     r%   r   z4HindsightMemoryProvider.sync_turn.<locals>.<genexpr>o  s     9AQ9r$  r   r   r  session:parent:   r  c            
     0  
  	j                  xs d         j                  dd         j                  dd        

 d<   t        j                  d
t	                     	j                   fd       t        j                  d       y )Nr   r  r   r  r  update_modezRHindsight retain: bank=%s, doc=%s, mode=%s, async=%s, content_len=%d, num_turns=%dc                0    | j                  g      S N)r  r   r  r  )aretain_batch)rB  r  r  r   retain_async_flags    r%   r  zGHindsightMemoryProvider.sync_turn.<locals>._do_retain.<locals>.<lambda>  s%    v33#& +!2	  4   r   zHindsight retain succeeded)r  popr!   rd   r  rC  )r   r  r   r  lineage_tagsmetadata_snapshot	num_turnsr  r  rD  r  s   @r%   
_do_retainz5HindsightMemoryProvider.sync_turn.<locals>._do_retain  s    ,,&*!)T	 - D HHY%HH^T*&&1]#LLm +{<MsSZ|]fh)) LL56r   returnNone) r|  r!   rd   rs  r5  r:   r   rv  rb   dumpsr  r  r   r  rf  r}  rI  rx  r  r   r  sumr(  rw  r  rS  r~  r  r0  r=  rp  put)rD  r  r  r|  turnturns_to_retainr  r  r   r  r  r  r  r  r  r  s   `      @@@@@@@@@r%   	sync_turnz!HindsightMemoryProvider.sync_turnC  s      LLDE%%'LL=>":446Dzz$33LBSTchi""4(a-- : ::a?LLO++T-?-?4C]C]`d`r`ruy  vP  vP  aP  DP  .QR#'#>#>t?P?P#Q [ (""11$2P2P2QRO"_`"4#6#67OI)3t/B/B+C999	; 11C7"$(4+;+;*< =>""'$*A*A)B CD !00o.2'' 1 
 (	-- ..--	7 	7. 	z* ("-01D1D-ED* #r   c                F    | j                   dk(  rg S t        t        t        gS )Nr   )rW  RETAIN_SCHEMARECALL_SCHEMAREFLECT_SCHEMAr  s    r%   get_tool_schemasz(HindsightMemoryProvider.get_tool_schemas  s"    	)I}n==r   c                    |dk(  r|j                  dd      }|st        d      S |j                  d      }	  j                  |||j                  d            j                  dd        j                  d	d        t        j                  d
 j                  t        |      |        j                   fd       t        j                  d       t        j                  ddi      S |dk(  r|j                  dd      st        d      S 	  j                   j                   j                  d j                  r j                  d<    j                   d<    j"                  r j"                  d<   t        j                  d j                  t               j                          j                  fd      }|j$                  rt        |j$                        nd}t        j                  d|       |j$                  st        j                  ddi      S t'        |j$                  d      D 	
cg c]  \  }	}
|	 d|
j(                    }}	}
t        j                  dd j+                  |      i      S |d#k(  r|j                  dd      st        d      S 	 t        j                  d$ j                  t               j                          j                   fd%      }t        j                  d&t        |j(                  xs d             t        j                  d|j(                  xs di      S t        d)|       S # t        $ r0}t        j                  d|d       t        d|       cY d }~S d }~ww xY wc c}
}	w # t        $ r0}t        j                  d!|d       t        d"|       cY d }~S d }~ww xY w# t        $ r0}t        j                  d'|d       t        d(|       cY d }~S d }~ww xY w)*Nr   r   r   z#Missing required parameter: contentr   r   )r   r   r  r  z:Tool hindsight_retain: bank=%s, content_len=%d, context=%sc                @    | j                  j                  g      S )N)r  r   )r  rS  )rB  r   rD  s    r%   r  z:HindsightMemoryProvider.handle_tool_call.<locals>.<lambda>  s    6#7#7VZU[#7#\ r   zTool hindsight_retain: successr   zMemory stored successfully.zhindsight_retain failed: %sTr2  zFailed to store memory: r   r   z!Missing required parameter: queryr  r  r  z7Tool hindsight_recall: bank=%s, query_len=%d, budget=%sc                (     | j                   di S r  r  r  s    r%   r  z:HindsightMemoryProvider.handle_tool_call.<locals>.<lambda>  s    NFNNDcUbDc r   r   z!Tool hindsight_recall: %d resultszNo relevant memories found.r   z. r#  zhindsight_recall failed: %szFailed to search memory: r   z8Tool hindsight_reflect: bank=%s, query_len=%d, budget=%sc                T    | j                  j                  j                        S r  r  r  s    r%   r  z:HindsightMemoryProvider.handle_tool_call.<locals>.<lambda>  s$    6?? $U4<< $3 $ r   z'Tool hindsight_reflect: response_len=%dzhindsight_reflect failed: %szFailed to reflect: zUnknown tool: )r*   r   r  r  r!   rd   rS  r  rC  rb   r  r9   r"   rT  r  rz  r{  r  r  	enumerater   r(  )rD  	tool_nameargsr!  r   r   r  rl   r  ir  linesr   r   r  s   `           @@@r%   handle_tool_callz(HindsightMemoryProvider.handle_tool_call  s   **hhy"-G!"GHHhhy)GB00#&) 1  D).Y!]]CL'C--\ =>zz8-J"KLL
 ,,HHWb)E!"EFFC#}}u"&"9"9' $$,0,=,=M&)262I2IM,/%%-1-?-?M'*V!]]CJF445cd37<<c$,,/Q@+N||::x1N&OPP6?a6PQdaA3b)QQzz8TYYu-=">??
 --HHWb)E!"EFF=W!]]CJF44
 FDIIOY[H\]zz8TYY-W:W"XYY
 N9+677c  B<a$O!$<QC"@AAB2 R C<a$O!$=aS"ABBC$  ==q4P!$7s";<<=st   B2M DN #N <N(N %BO 	N%N=NNN 	O
%O?O
O
	P%P;PPF)rK  resetc                   t        |xs d      j                         }|sy j                  rt         j                         j                  } j
                  } j                  } j                  t              dz  |      g |rj                  d|        |rj                  d|        ddj                        z   d	z    j                   j                        \   fd
}	 j                  j                         s; j                           j!                           j"                  j%                  |	        j&                  r6 j&                  j)                         r j&                  j                  d        j*                  5  d _        ddd       |rt        |      j                          _        | _        t/        j0                         j3                  d      }
 j                   d|
  _        g  _        d _        d _        d _        t8        j;                  d j                   j
                  | j                         y# 1 sw Y   xY w)u  Refresh cached per-session state when the agent rotates session_id.

        Fires on /resume, /branch, /reset, /new, and context compression.
        Without this hook, initialize()-cached state (``_session_id``,
        ``_document_id``, ``_session_turns``, ``_turn_counter``) would keep
        pointing at the previous session and writes would land in the wrong
        document. See hermes-agent#6672.

        Always update ``_session_id`` so metadata and tags on subsequent
        retains reflect the active session. Always mint a fresh
        ``_document_id`` so the new session's retain doesn't overwrite the
        old session's document on vectorize-io/hindsight#1303. Always clear
        the accumulated batch buffers (``_session_turns``, ``_turn_counter``,
        ``_turn_index``) — even for /resume and /branch, the new session's
        batching must start from zero so an in-flight retain doesn't flush
        under the wrong ``_document_id``.

        Before clearing, flush any buffered turns under the *old*
        ``_document_id``. Users who set ``retain_every_n_turns > 1`` would
        otherwise silently lose whatever's in ``_session_turns`` at the
        moment of switch — the same data-loss class as the shutdown race,
        just at a different lifecycle event.

        Also wait for any in-flight prefetch from the old session and drop
        its cached result; otherwise the new session's first ``prefetch()``
        could read stale recall text from before the switch.

        ``parent_session_id`` is recorded for lineage tags on future retains.
        ``reset`` is accepted but not needed for Hindsight's state model —
        buffer clearing is correct for every session switch, not only /reset.
        r   Nr  r  r  r  r   r   r  c            	        	 j                  j                  xs d       j                  dd        j                  dd        d<   t        j	                  dj
                  t                     j                  fd       y # t        $ r"} t        j                  d| d	       Y d } ~ y d } ~ ww xY w)
Nr  r  r  r  zAHindsight flush-on-switch: bank=%s, doc=%s, mode=%s, num_turns=%dc                X    | j                  j                  gj                        S r  )r  rS  r~  )rB  r   old_document_idrD  s    r%   r  zKHindsightMemoryProvider.on_session_switch.<locals>._flush.<locals>.<lambda>F  s/    v';';$(MM#'&(7)-););	 (< ( r   z$Hindsight flush-on-switch failed: %sTr2  )
r  r  r  r!   rd   rS  r  rC  r9   r"   )	r  r   old_contentr  old_lineage_tagsold_metadata	old_turnsold_update_moderD  s	    @r%   _flushz9HindsightMemoryProvider.on_session_switch.<locals>._flush5  s    ]44# $ 4 4!--5	 5 D HHY-HH^T2&2.=]+LL[Y 11 ! ]NN#I1W[N\\]s   BB 	C B;;C r  rR   rL  r,  r   zEHindsight on_session_switch: new_session=%s parent=%s reset=%s doc=%s)r:   r   r  r   rv  rw  rf  r  r  r   r(  rI  rx  rs  r5  r0  r=  rp  r  rm  r,  rl  rj  r   r   ru  r  r  r!   rd   )rD  new_session_idrK  r  r!  new_idold_session_idold_parent_session_idold_turn_indexr  r}  r  r  r  r  r  r  s   `          @@@@@@r%   on_session_switchz)HindsightMemoryProvider.on_session_switch  s=   N ^)r*002
 T001I!--N$($;$;!!--N//!)nq0) 0 L +- ''(>2B(CD$ '''2G1H(IJ 33c9K
 04/J/J!!0,O_] ]B &&--/##%%%'""&&v.   T%:%:%C%C%E!!&&s&3   	'$&D!	' &)*;&<&B&B&DD#!<<>**+=>#//0(< )*&Sd55ud>O>O	
	' 	's   I""I+c                   t         j                  d       | j                  j                          | j                  }||j                         rp	 | j                  j                  t               |j                  d       |j                         r.t         j                  d| j                  j                                | j                  r6| j                  j                         r| j                  j                  d       | j                  	 | j                  dk(  rlt!        | j                  dd       }|7t#        |d      r+t%        |j'                                	 d | j                  _        	 | j                  j)                          n)| j%                  | j                  j'                                d | _        y y # t        $ r Y Xw xY w# t        $ r Y iw xY w# t*        $ r Y 3w xY w# t        $ r Y Bw xY w)	NzDHindsight shutdown: stopping writer + waiting for background threadsg      $@rR   zIHindsight writer did not stop within 10s; abandoning %d pending retain(s)      @r  rg  aclose)r!   rd   rs  r   rq  r,  rp  r  r6  r9   r(  r"   qsizerm  rg  rU  rE  rz  r   r  closer   )rD  writerinner_clients      r%   r?  z HindsightMemoryProvider.shutdownq  s   [\ 	! $$&//"3""&&'78 KKK% 6&&,,.
   T%:%:%C%C%E!!&&s&3<<#::!11 $+4<<D#IL#/GL(4S!,"5"5"78!37DLL0**, NN4<<#6#6#89  DL1 $  2  ) ! ! (   sg   F: AG( G
 -G *G( :	GG
	GG( GG( 	G%"G( $G%%G( (	G43G4)r  	List[str]r  r:   )r  r  )r  r:   r1   rf   r  r  )r;   r9   r  r  r  )rH  r:   r  ztuple[str, str | None])r|  r:   r  r  )r   r:   r|  r:   r  r:   )r   r:   r|  r:   r  r  )r  r:   r  r:   r  zList[Dict[str, str]])r  r   r  r   r  zDict[str, str])r   r:   r   
str | Noner  r  r  zDict[str, str] | Noner   zList[str] | Noner  zbool | Noner  zDict[str, Any])r  r:   r  r:   r|  r:   r  r  )r  zList[Dict[str, Any]])r  r:   r  rf   r  r:   )r  r:   rK  r:   r  r  r  r  )"r(  
__module____qualname____doc__rF  r  propertyr   r  r  r  r  r"  r   r*  r0  r.  r=  r<  rC  rF  rI  r  r  r  r  r  r  r  r  r  r  r  r?  r~   r   r%   rB  rB  m  sP   WP$d  &="T8l(
T3j6
././F5"#**pd
, 9; '$ ?A +&Z
@ #"&*.!%$( 	
   (  " 
> Y[ ]F~>
G8Z "$

 	

 
 

B/ r   rB  c                6    | j                  t                      y)z/Register Hindsight as a memory provider plugin.N)register_memory_providerrB  )ctxs    r%   r;  r;    s      !8!:;r   )r#   r   r$   r   r  r   )r1   dict[str, Any]r  r  )r  ztuple[bool, str | None]r  )rL   r  rM   r:   r  r  )Nr  )rg   r:   rh   r  rS   r+   r  r  rz   )rg   r:   rh   r  r  r  )r  zasyncio.AbstractEventLoop)rS   r+   )r  rf   )r#   r   r  r  )r#   r   r  r   r  )r1   r  r  r:   )r  dict[str, str])r1   r  r  r  r  r  )r1   r  )r1   r  r  r  )r#   r:   r  r:   )r9  r:   r:  r:   r;  r:   r  r:   )Ir  
__future__r   r{   r:  r7   rb   loggingr,   rn  r  r   r   r   typingr   r   r   agent.memory_providerr	   hermes_constantsr
   tools.registryr   r  r   	getLoggerr(  r!   rQ  r  r  r   r   rr   rw  r  r&   r/   r4   r<   rF   rG   __annotations__rk  rq   rN   ro   ru   rv   rw   r   r   r6  r   r   r  r  r  r   r   r   r   r   r   r  r  r  r*  r3  r@  rB  r;  r~   r   r%   <module>r     su  < #      	  
  ' " " 0 , % %			8	$7 ,     '. #'# !#*
 $ E A6 -$ -/ / .()..*  FJ25-*/-:D-< BF#4>#JN#V +/' .(,% ,Y^^
 8 " &6 *( 	S  (9TU (9tu (+e
 K, 	T h7LM
 I   	R h7TU
 I(+\"J J ,^`
$ VZ #L] \` 	$, Js n s B*<r   