+
    lHàjÆ¬  ã            #       óÌ  € R t ^ RIt^ RIt^ RIt^ RIt^ RIHtHtHt ^ RIH	t	H
t
HtHtHt ^ RIHt ^ RIHt R‰tRŠtRtRt^t]P.                  ! R]P0                  4      tR	R
RRRR/tR‹tRŒt]tRR/R R lltR tR R lt R R lt!R R lt"R R lt#R R lt$R R  lt%R! R" lt&R# R$ lt'R% R& lt(R' R( lt)R) R* lt*R+ R, lt+R- R. lt,R/ R0 lt-R1 R2 lt.R3 R4 lt/R5 R6 lt0R�R7 R8 llt1RŽR9 R: llt2R; R< lt3R= R> lt4R? R@ lt5RA RB lt6RC RD lt7R�RE RF llt8RG RH lt9R�RI RJ llt:RK RL lt;R�RM RN llt<RO RP lt=RQ RR lt>R‘RS RT llt?R’RU RV llt@R“RX RY lltARZ R[ ltBR\R]R^R_R`RaRbRcRdRaReR^Rf/RgRaRhR^RiRj^/RkRaReRlRmRn.R^Ro/RpRaReRlRWRq.R^RrRjRW/RsRaReR^Rt/RuRaReR^Rv/RwRaRxRyRaRe/R^Rz/RRaReR^R{/R|RaRhR^R}/R~RaRhR^RRj^/R€RaReR^R�/R‚RaReR^Rƒ//R„. //tC^ R…IDHEtEHFtF ]EPŽ                  ! R]R]]CR† ]BR‡Rˆ7       R# )”u·  Session Search Tool - long-term conversation recall over the SQLite session DB.

Single-shape tool; the mode is inferred from the args: DISCOVERY (``query``;
FTS5 deduped by lineage, adaptive detail hydrates only the top result),
SCROLL (``session_id`` + ``around_message_id``; Â±window around the anchor),
READ (``session_id`` alone; whole session or head/tail), BROWSE (no args).
No LLM calls â€” every shape returns actual DB messages.
N)ÚdatetimeÚtimezoneÚUTC)ÚAnyÚDictÚListÚOptionalÚUnion)Ú_BOUNDARY_END_REASONS)Úsafe_strftimeiÐ  i,  z^(\d+)\s*(h|d|w)$Úhi  Údi€Q Úwi€:	 Ú
session_idÚwith_excFc                ó$   € V ^8„  d   QhR\         /# )é   r   ©Úbool)Úformats   "Ú>/home/ubuntu/.hermes/hermes-agent/tools/session_search_tool.pyÚ__annotate__r   ;   s   € ÷ ñ ´$ñ ó    c               óœ   €  V ! 4       #   \          d8   p\        P                  ! T.T'       d
   YE3,           MTO5RR/  Tu Rp?# Rp?ii ; i)zS``fn()``, or *default* after debug-logging *msg* (+ the exception when *with_exc*).Úexc_infoTN)Ú	ExceptionÚloggingÚdebug)ÚfnÚdefaultÚmsgr   Úlog_argsÚes   &&&$* r   Ú_quietr#   ;   sB   € ðÙ‹tˆøÜô Ü�Š�cÐW·˜X¨ž_¸hÒWÐRVÒWØ�ûðús   ‚	 ‰A”,AÁ AÁAc                ó¦   €  V ! 4       R3#   \          d;   p\        P                  ! T.TOTN5RR/  R\        T RT 2RR7      3u Rp?# Rp?ii ; i)u|   ``(fn(), None)``, or ``(None, tool_error_json)`` after an error-level log â€” for DB
calls whose failure the model must see.Nr   Tz: F©Úsuccess)r   r   ÚerrorÚ
tool_error)r   Úlog_msgÚerror_prefixr!   r"   s   &&&* r   Ú_loudr+   D   s^   € ðGÙ‹t�TˆzÐøÜô GÜ�Š�gÐ; Ð;¨!Ò;°dÒ;Ø”Z < .°°1°#Ð 6ÀÔFÐFÕFûðGús   ‚ ‹A–/AÁAÁAc                óT   € V ^8„  d   QhR\         \        ,          R,          R\        /# )r   ÚtsNÚreturn)ÚfloatÚstr)r   s   "r   r   r   N   s'   € ÷ Jñ Jœ%¤#�+¨Õ,ð J´ñ Jr   c                óæ   a € S f   R# \        S \        4      '       d9   S P                  RR4      P                  RR4      P                  4       '       g   S # \	        V 3R l\        S 4      RS RR7      # )	zNUnix timestamp -> readable date; ISO strings pass through; "unknown" for None.ÚunknownÚ.Ú Ú-c                  óV   <€ \        \        P                  ! \        S 4      4      R 4      # )z%B %d, %Y at %I:%M %p)r   r   Úfromtimestampr/   ©r-   s   €r   Ú<lambda>Ú#_format_timestamp.<locals>.<lambda>T   s   ø€ œ-¬×(>Ò(>¼uÀR»yÓ(IÐKbÔcr   z!Failed to format timestamp %s: %sT©r   )Ú
isinstancer0   ÚreplaceÚisdigitr#   r8   s   fr   Ú_format_timestampr?   N   se   ø€ à	‚zÙÜ�"”c×Ò 2§:¡:¨c°2Ó#6×#>Ñ#>¸sÀBÓ#G×#OÑ#O×#QÒ#QØˆ	ÜÔcÔehÐikÓelØ5°rÀDôJð Jr   c                ó0   € V ^8„  d   QhR\         R\        /# ©r   r   r.   )r0   Údict)r   s   "r   r   r   X   s   € ÷ Tñ T¤cð T¬dñ Tr   c                óD   a a€ \        V V3R lRRSRR7      ;'       g    / # )z4``db.get_session`` that degrades to ``{}`` on error.c                  ó&   <€ S P                  S4      # ©N©Úget_session©Údbr   s   €€r   r9   Ú#_get_session_meta.<locals>.<lambda>Z   s   ø€ ˜"Ÿ.™.¨Ô4r   Nzget_session failed for %s: %sTr;   )r#   rH   s   ffr   Ú_get_session_metarK   X   s-   ù€ äÕ4°dØ1°:ÈôN÷ Tð TØQSðTr   c                ót   € V ^8„  d   QhR\         \        \        3,          R\         \        \        3,          /# )r   Úmetar.   )rB   r0   r   )r   s   "r   r   r   ^   s.   € ÷ Dñ Dœd¤3¬ 8�nð D´´c¼3°hµñ Dr   c           
      ó    € R \        V P                  R4      4      RV P                  R4      RV P                  R4      RV P                  R4      /# )ÚwhenÚ
started_atÚsourceÚmodelÚtitle)r?   Úget)rM   s   &r   Ú_session_meta_blockrU   ^   sK   € ØÔ% d§h¡h¨|Ó&<Ó=¸xÈÏÉÐRZÓI[Ø�T—X‘X˜gÓ&¨°·±¸'Ó1BðDð Dr   c                ó$   € V ^8„  d   QhR\         /# ©r   r.   ©r0   )r   s   "r   r   r   c   s   € ÷ Hñ H”cñ Hr   c                  ó:   € \         P                  ! R R/V CRR7      # )r&   TF)Úensure_ascii)ÚjsonÚdumps)Úpayloads   ,r   Ú_okr^   c   s   € Ü�:Š:�y $Ð2¨'Ð2ÀÔGÐGr   c                ó0   € V ^8„  d   QhR\         R\        /# )r   Úcontentr.   ©r0   r   )r   s   "r   r   r   g   s   € ÷ Oñ O¤Cð O¬Dñ Or   c                 ón   € \        V 4      ;'       d$    V P                  4       P                  \        4      # rE   )r   ÚlstripÚ
startswithÚ_COMPACTION_PREFIXES)r`   s   &r   Ú_is_compaction_summaryrf   g   s'   € Ü�‹=×NÐN˜WŸ^™^Ó-×8Ñ8Ô9MÓNÐNr   c                óR   € V ^8„  d   QhR\         R\        \         \        3,          /# rA   )r0   Útupler   )r   s   "r   r   r   k   s#   € ÷  ñ  ¤sð  ¬u´S¼$°YÕ/?ñ  r   c                óþ   € \        4       pTRrCV'       dg   W29  da   VP                  V4       \        W4      pT;'       g    VP                  R4      R8H  pVP                  R4      '       g    W43# VR,          pKn  W43# )zÐWalk parent_session_id to the root -> ``(root_id, has_compression_hop)``; the flag
separates a compression-split lineage (parent summarised away) from a delegation
lineage (child still visible to the parent).FÚ
end_reasonÚcompressionÚparent_session_id)ÚsetÚaddrK   rT   )rI   r   ÚvisitedÚcurÚhas_compressionÚss   &&    r   Ú_resolve_to_parentrs   k   s}   € ô ›€GØ% uˆß
�#Ô$Ø�‰�CÔÜ˜bÓ&ˆØ)×QÐQ¨Q¯U©U°<Ó-@ÀMÑ-QˆØ�u‰uÐ(×)Ò)ØàÐÐð Ð#Õ$ŠØÐÐr   c                ó0   € V ^8„  d   QhR\         R\         /# rA   rX   )r   s   "r   r   r   {   s   € ÷ 1ñ 1¤Sð 1¬Sñ 1r   c                 ó&   € \        W4      ^ ,          # )é    )rs   rH   s   &&r   Ú_resolve_lineagerw   {   s   € Ü˜bÓ-¨aÕ0Ð0r   c                ó\   € V ^8„  d   QhR\         \        ,          R\         \        ,          /# ©r   Úvaluer.   )r   r0   Úint)r   s   "r   r   r      s"   € ÷ #ñ #œH¤S�Mð #¬h´s­mñ #r   c                óN  € V f   R# \        V 4      P                  4       pV'       g   R# \        P                  V4      ;p'       dm   \	        \
        P
                  ! 4       4      \	        VP                  ^4      4      \        VP                  ^4      P                  4       ,          ,          ,
          #  \        P                  ! V4      pTP                  f   TP                  \        R7      p\	        TP                  4       4      #   \         d    \        RT : R24      Rhi ; i)a›  Parse an ISO date/datetime OR a relative duration into a UTC unix timestamp.

ISO: a date-only value (``YYYY-MM-DD``) is midnight UTC on that day (the SQL
``before`` predicate is exclusive, so ``before=2026-07-01`` keeps June and drops
July 1 00:00). Relative: ``"7d"``, ``"24h"``, ``"2w"`` = now minus N
hours/days/weeks, so ``after="7d"`` is the last week and ``before="7d"`` is
everything older than a week.
Nzinvalid time bound: zV (expected ISO date/datetime like 2026-07-01, or a relative duration like 7d, 24h, 2w))Útzinfo)r0   ÚstripÚ_RELATIVE_BOUND_REÚmatchr{   ÚtimeÚgroupÚ_RELATIVE_UNIT_SECONDSÚlowerr   ÚfromisoformatÚ
ValueErrorr}   r=   r   Ú	timestamp)rz   ÚtextÚrelÚparseds   &   r   Ú_parse_iso_boundr‹      sø   € ð ‚}ÙÜˆu‹:×ÑÓ€DßÙÜ ×&Ñ& tÓ,Ð,€sÖ,Ü”4—9’9“;Ó¤# c§i¡i°£lÓ"3Ô6LÈSÏYÉYÐWXË\×M_ÑM_ÓMaÕ6bÕ"bÕbÐbð[Ü×'Ò'¨Ó-ˆð ‡}�}ÒØ—‘¤s�Ó+ˆÜˆv×ÑÓ!Ó"Ð"øô ô [ÜÐ/°©yð 9Pð Pó QØVZð	[ð[ús   Â4D ÄD$c                óF   € V ^8„  d   QhR\         R\        \        ,          /# ry   )r   r   r{   )r   s   "r   r   r   ™   s   € ÷ ñ œcð ¤h¬s¥mñ r   c                ó\  € V e   V R8X  g   \        V \        4      '       d   R# \        V \        \        34      '       d   \        V 4      # \	        V 4      P                  4       p \        \        V4      4      #   \        \        3 d     Mi ; i \        T4      #   \         d     R# i ; i)zY``sessions.started_at`` as an int unix timestamp (numeric or ISO text); None if unusable.Nr4   )	r<   r   r{   r/   r0   r~   Ú	TypeErrorr†   r‹   )rz   rˆ   s   & r   Ú_coerce_started_tsr�   ™   s–   € à‚}˜ œ¤z°%¼×'>Ò'>ÙÜ�%œ#œu˜×&Ò&Ü�5‹zÐÜˆu‹:×ÑÓ€DðÜ”5˜“;ÓÐøÜ”zÐ"ô ÙðúðÜ Ó%Ð%øÜô Úðús$   Á%A9 Á9BÂBÂ
B ÂB+Â*B+c                óŠ   € V ^8„  d   QhR\         \        ,          R\         \        ,          R\         \        ,          R\        /# )r   Ú
started_tsÚafter_tsÚ	before_tsr.   )r   r{   r   )r   s   "r   r   r   ª   s>   € ÷ jñ j¤¬¥ð j¼Ä#½ð jÔS[Ô\_ÕS`ð jÔeiñ jr   c                ór   € Vf   Vf   R# V f   R# VRJ ;'       g    W8¬  ;'       d    VRJ ;'       g    W8  # )zI``after_ts <= started_ts < before_ts``; an unknown start fails any bound.NTF© )r‘   r’   r“   s   &&&r   Ú_in_time_windowr–   ª   sH   € àÒ˜IÒ-ÙØÒÙØ˜Ð×6Ð6 
Ñ 6×iÐi¸YÈ$Ð=N×=hÐ=hÐR\ÑRhÐir   c                óF   € V ^8„  d   QhR\         R\        \        ,          /# )r   Úrawr.   )r   Úlistr0   )r   s   "r   r   r   ³   s   € ÷ 
ñ 
¬ð 
´´Sµ	ñ 
r   c                ó\  € \        V \        4      '       d   V .M(\        V \        \        34      '       d   \        V 4      M. p. pV Fa  p\        V\        4      '       d   VP	                  4       MRpV'       d   WB9  d   VP                  V4       \        V4      \        8¼  g   K`   V# 	  V# )zYDeduped, stripped session ids from a str or list, capped at ``_EXCLUDE_SESSION_IDS_CAP``.r4   )r<   r0   r™   rh   r~   ÚappendÚlenÚ_EXCLUDE_SESSION_IDS_CAP)r˜   ÚitemsÚoutÚitemÚsids   &    r   Ú_normalize_exclude_session_idsr¢   ³   s…   € ä ¤S×)Ò)ˆS‰E¼JÀsÌTÔSXÈM×<ZÒ<Z¬t°C¬yÐ`b€EØ€CÛˆÜ(¨¬s×3Ò3ˆd�j‰jŒl¸ˆß�3”>Ø�J‰J�sŒOÜˆs‹8Ô/Ö/ØØ€Jñ ð €Jr   c                ó\   € V ^8„  d   QhR\         \        ,          R\        \        ,          /# )r   Úexclude_session_idsr.   )r™   r0   rm   )r   s   "r   r   r   À   s"   € ÷ ñ ´T¼#µYð Ä3ÄsÅ8ñ r   c                ó–   € \        4       pV F8  pVP                  V4       TP                  \        W4      ;'       g    T4       K:  	  V# )zUThe excluded ids plus their lineage roots, so a child id also hides its parent chain.)rm   rn   rw   )rI   r¤   Úrootsr¡   s   &&  r   Ú_excluded_lineage_rootsr§   À   s?   € ä“e€EÛ"ˆØ�	‰	�#ŒØ�	‰	Ô" 2Ó+×2Ð2¨sÖ3ñ #ð €Lr   c                ó<   € V ^8„  d   QhR\         R\         R\        /# )r   ÚaÚbr.   ra   )r   s   "r   r   r   É   s!   € ÷ >ñ >œð >¤ð >¬ñ >r   c                 óZ   € \        W4      p\        T;'       d    V\        W4      8H  4      # rE   )rw   r   )rI   r©   rª   Úa_roots   &&& r   Ú_same_lineager­   É   s*   € Ü˜bÓ$€FÜ�×<Ð<˜6Ô%5°bÓ%<Ñ<Ó=Ð=r   c                ó0   € V ^8„  d   QhR\         R\        /# rA   ra   )r   s   "r   r   r   Î   s   € ÷ Qñ Q¬sð Q´tñ Qr   c                óŠ   € T;'       d#    \        W4      P                  R4      ;'       g    RpVR8H  ;'       g
    V\        9   # )a2  True when the transcript left everyone's live context: ``compression``
(summarised into the child) or a fresh reset (child starts empty). Live delegation
children (``end_reason is None``) and ``branched`` parents (copied verbatim into
the branch) ARE the current context, so they stay excluded from recall.rj   Nrk   )rK   rT   Ú_FRESH_RESET_END_REASONS)rI   r   rj   s   && r   Ú_session_left_live_contextr±   Î   sD   € ð
 ×TÐTÔ!2°2Ó!B×!FÑ!FÀ|Ó!T×]Ð]ÐY]€JØ˜Ñ&×PÐP¨*Ô8PÑ*PÐPr   c                ó\   € V ^8„  d   QhR\         \        \        \        3,          ,          /# rW   )r   rB   r0   r   )r   s   "r   r   r   ×   s    € ÷ &ñ &´(¼4ÄÄSÀ½>Õ2Jñ &r   c                ón   a a€ V V3R lpS;'       d    \        VRRS4      pV'       d   \        V4      # R# )zMOwning session and visibility flags for *message_id* (None if missing/error).c                  óÀ   <€ S P                   ;_uu_ 4        S P                  P                  R S34      P                  4       uuRRR4       #   + '       g   i     R# ; i)z?SELECT session_id, active, compacted FROM messages WHERE id = ?N)Ú_lockÚ_connÚexecuteÚfetchone©rI   Ú
message_ids   €€r   Ú_lookupÚ+_get_message_storage_state.<locals>._lookupÙ   s=   ø€ Ø�X�X‹XØ—8‘8×#Ñ#ØQÐT^ÐS`óbßbjÑbjÓbl÷ �X�X‹Xús   –+AÁA	Nz*message storage-state lookup failed for %s)r#   rB   )rI   rº   r»   Úrows   ff  r   Ú_get_message_storage_stater¾   ×   s6   ù€ ömð ×
hÐ
hœ ¨Ð/[Ð]gÓh€CßŒ4�‹9Ð% Ð%r   c                óh   € V ^8„  d   QhR\         \        \        \        3,          ,          R\        /# )r   Ústater.   )r   rB   r0   r   r   )r   s   "r   r   r   á   s+   € ÷ Rñ Rœx¬¬S´#¨X­Õ7ð R¼Dñ Rr   c                óZ   € V RJ;'       d!    V R,          ^ 8H  ;'       d    V R,          ^8H  # )zwCompaction archives are ``active=0, compacted=1``; rewind/undo rows are
``active=0, compacted=0`` and must stay hidden.NÚactiveÚ	compactedr•   )rÀ   s   &r   Ú_is_compacted_staterÄ   á   s3   € ð ˜Ð×QÐQ  x¥°AÑ!5×QÐQ¸%ÀÕ:LÐPQÑ:QÐQr   c                ó$   € V ^8„  d   QhR\         /# rW   r   )r   s   "r   r   r   ç   s   € ÷ Kñ K¬Tñ Kr   c                ó*   € \        \        W4      4      # )zTrue for a compaction-archived row: no longer in live context, so discoverable
even on the current session. False on any error.)rÄ   r¾   r¹   s   &&r   Ú_is_compacted_messagerÇ   ç   s   € ô Ô9¸"ÓIÓJÐJr   c          
      ó¸   € V ^8„  d   QhR\         \        \        3,          R\        \        ,          R\        \        ,          R\         \        \        3,          /# )r   ÚmÚ	anchor_idÚmax_content_lenr.   )rB   r0   r   r   r{   )r   s   "r   r   r   í   sH   € ÷ Oñ O”dœ3¤˜8•nð O´¼#µð OÜ$,¬S¥MðOÜ=AÄ#ÄsÀ(½^ñOr   c           
     ó¼  € V P                  R4      p\        V\        4      '       d   RV9   d   ^ RIHp V! V4      pRV P                  R4      RV P                  R4      RVRV P                  R4      /pTP                  R Uu/ uF,  q`P                  V4      '       g   K  W`P                  V4      bK.  	  up4       Ve   V P                  R4      V8X  d   RVR	&   V'       d@   V'       d8   \        V4      V8”  d(   VP                  VRV R
,           R\        V4      R7       VP                  4        UUu/ uF  w  rgVf
   VR8X  g   K  WgbK  	  upp# u upi u uppi )zMSlim a message row; keeps ``content`` even when empty (tool-call-only turns).r`   Ú)Ú
strip_ansiÚidÚroler‡   NTÚanchoru   â€¦)r`   Úcontent_truncatedÚoriginal_content_chars)Ú	tool_nameÚ
tool_callsÚtool_call_id)rT   r<   r0   Útools.ansi_striprÎ   Úupdaterœ   rž   )rÉ   rÊ   rË   r`   rÎ   ÚentryÚkÚvs   &&&     r   Ú_shape_messagerÜ   í   s+  € ð �e‰e�IÓ€GÜ�'œ3×Ò F¨gÔ$5Ý/Ù˜WÓ%ˆØ�1—5‘5˜“; ¨¯©¨f«°yÀ'È;ÐXY×X]ÑX]Ð^iÓXjÐk€EØ	‡L�LÑ'RÓ_Ñ'R !×V[ÑV[Ð\]×V^”+�!—U‘U˜1“X’+Ñ'RÑ_Ô`ØÒ §¡ t£°	Ô!9Øˆˆh‰ßŸ7¤s¨7£|°oÔ'EØ�‰˜WÐ%5 oÐ6¸Õ>ÐRVÜ,/°«Lð 	ô 	:à"Ÿ[™[œ]ÔN™]‘T�Q¨aªm¸qÀI¹~ŒDˆAŠD™]ÒNÐNùò `ùó Os   ÂEÂ EÄ5EÅ	Ec                óJ   € V ^8„  d   QhR\         R\         R,          R\         /# )r   r   ÚprofileNr.   rX   )r   s   "r   r   r   þ   s*   € ÷ 	Qñ 	Qœcð 	Q¬C°$­Jð 	QÄ#ñ 	Qr   c                ó�   € R pT;'       g    RP                  4       ;'       g    \        VRR4      pV'       d	   RV RV  2# RV  2# )uï   The reference the agent writes for a session â€” same value the desktop composer
emits, so it renders as a titled link. The profile segment is omitted when it
can't be named confidently (a bare id still resolves, just not across profiles).c                  ó2   € ^ RI Hp  V ! 4       pVR8X  d   R# T# )rv   )Úget_active_profile_nameÚcustomr4   )Úhermes_cli.profilesrá   )rá   Úresolveds     r   Ú_activeÚ_session_link.<locals>._active  s   € Ý?Ù*Ó,ˆØ Ô)ˆrÐ7¨xÐ7r   r4   z/get_active_profile_name failed for session linkz	@session:Ú/)r~   r#   )r   rÞ   rå   Únames   &&  r   Ú_session_linkré   þ   sP   € ò8ð �MˆM�r× Ñ Ó"×lÐl¤f¨W°bÐ:kÓ&l€Dß.2ˆY�t�f˜A˜j˜\Ð*ÐP¸)ÀJÀ<Ð8PÐPr   c                óh   € V ^8„  d   QhR\         \        ,          R\        \        \        3,          /# )r   Úlineage_rootr.   )r   r0   rB   r   )r   s   "r   r   r   
  s&   € ÷ ñ ¤8¬C¥=ð ¼tÄCÌÀH½~ñ r   c                óp   € R Uu/ uF  q"W,          bK  	  ppV '       d   WR,          8w  d   WR&   V# u upi )zMCanonical key order; ``parent_session_id`` set when the hit lives in a child.r   rl   ©r   rO   rQ   rR   rS   Úmatched_roleÚmatch_message_idÚsnippetÚbookend_startÚmessagesÚbookend_endÚmessages_beforeÚmessages_afterÚdetailr•   )rë   ÚfieldsrÚ   rÙ   s   &,  r   Ú_discovery_entryrø   
  sN   € ñ$có dñ $c˜a�•	Š\ñ $c€Eð d÷ ˜¨lÕ(;Ô;Ø%1Ð!Ñ"Ø€Lùòds   …3c          	      óŠ   € V ^8„  d   QhR\         R\        \         ,          R\        \        \         \        3,          ,          /# )r   ÚqueryÚcurrent_lineage_rootr.   )r0   r   rB   r   )r   s   "r   r   r     s8   € ÷ #'ñ #'¤3ð #'¼hÄs½mð #'ÔPXÔY]Ô^aÔcfÐ^fÕYgÕPhñ #'r   c                óà  a aaa	a
a€ VP                  4       P                  R4      o
S
;'       d    \        V V
3R lRRS
4      o	S	'       g   R# \        S S	4      oV'       d   SV8X  d   \        S S	4      '       g   R# \        V VV	3R lRRS	4      ;'       g    / pVP	                  R4      \
        9   d   R# \        V V	3R l. R	S	4      pV'       d   V^ ,          P	                  R
4      MRoSf   / M\        VV V	3R l/ RS	S4      oVP	                  R4      ;'       g    S
pR V3R llp/ \        SS	\        VP	                  R4      4      VP	                  RR4      VP	                  R4      ;'       g    RVRSRV 2V! RVR,          4      V! RVR,          SRR7      V! RVR!R 4      SP	                  R^ 4      SP	                  R\        \        V4      ^,
          ^ 4      4      RR7      CRS/C# )"zJDiscovery-shaped result when the query matches a session title, else None.z`'"c                  ó&   <€ S P                  S4      # rE   )Úresolve_session_by_title)rI   Útitle_querys   €€r   r9   Ú%_title_match_result.<locals>.<lambda>  s   ø€ °×0KÑ0KÈKÔ0Xr   Nz&resolve_session_by_title failed for %rc                  óX   <€ S P                  S4      ;'       g    S P                  S4      # rE   rF   )rI   rë   r   s   €€€r   r9   r      s#   ø€  "§.¡.°Ó">×"\Ð"\À"Ç.Á.ÐQ[ÓB\Ð"\r   z%get_session failed for title match %srQ   c                  ó&   <€ S P                  S4      # rE   ©Úget_messagesrH   s   €€r   r9   r   $  ó   ø€ ˜bŸo™o¨jÔ9r   z&get_messages failed for title match %srÏ   c                  ó.   <€ SP                  SS ^^R7      # )é   ©ÚwindowÚbookend)Úget_anchored_view)rÊ   rI   r   s   €€€r   r9   r   '  s   ø€ �×$Ñ$ Z°À1ÈaÐ$ÔPr   z.get_anchored_view failed for title match %s/%srS   c           	      óz   <€ SP                  V 4      ;'       g    T Uu. uF  p\        WBVR 7      NK  	  up# u upi )©rÊ   rË   )rT   rÜ   )ÚkeyÚfallbackrÑ   rË   rÉ   Úviews   &&&& €r   ÚshapeÚ"_title_match_result.<locals>.shape+  sB   ø€ àŸ(™( 3›-×3Ð3¨8Ð3ó6Ù3�Aô ˜qÀO×TÙ3ñ6ð 	6ùò 6s   Ÿ8rP   r2   rR   Úsession_titlezSession title matched: rñ   :Né   Nr	  :Nr  Né   ©rË   ró   rô   rõ   Úfullrí   Ú_lineage_root)Né°  éýÿÿÿ)
r~   r#   rw   r±   rT   Ú_HIDDEN_SESSION_SOURCESrø   r?   Úmaxrœ   )rI   rú   rû   Úsession_metarò   rS   r  rÊ   rë   r   rÿ   r  s   f&&    @@@@@r   Ú_title_match_resultr    sê  ý€ à—+‘+“-×%Ñ% fÓ-€KØ÷ _ð _¤Õ(XÐZ^Ø(PÐR]ó"_€JçÙÜ# B¨
Ó3€L÷  Ð0DÔ DÔMgÐhjÐlv×MwÒMwÙÜÖ\Ð^bØAÀ:óO÷ Uð UØRTð à×Ñ˜Ó!Ô%<Ô<ÙÜÕ9¸2Ð?gÐisÓt€Hß)1�˜•—‘ Ô%°t€IØÒ"‰2¬ÞPÐRTØ8¸*Àió)Q€Dð ×Ñ˜WÓ%×4Ð4¨€E÷6ð	'ÔØ Ô2CÀL×DTÑDTÐUaÓDbÓ2cØ×Ñ ¨)Ó4¸L×<LÑ<LÈWÓ<U×<bÐ<bÐYbØ /ÀIØ)¨%¨Ð1Ù˜O¨X°b­\Ó:Ù�x ¨"¥¨yÈ$ÔOÙ˜-¨°"°#¨Ó7ÈÏÉÐRcÐefÓIgØ—x‘xÐ 0´#´c¸(³mÀaÕ6GÈÓ2KÓLÐU[ô]ð 	'ð 	˜ñ	'ð 	'r   c                óH   € V ^8„  d   QhR\         R\         R\        R\         /# )r   rú   rö   Úresultsr.   )r0   r™   )r   s   "r   r   r   :  s.   € ÷ uñ u¤ð u¬cð u¼Dð uÌcñ ur   c                óÜ   € \        V P                  RR4      pVf   / M/RRVR,          RRVR,           RVR,          R	 R
VR,          R	 R2//p\        RRRRVRVRVR\        V4      /VBVB # )zDiscovery response; notes FTS backfill progress so the agent can explain thin
results instead of treating them as ground truth.Nzfts_rebuild_status failedÚindex_rebuildÚpercentÚnotez2The search index is rebuilding in the background (z% done, ÚindexedÚ,z of ÚtotalzL messages). Results from older messages may be incomplete until it finishes.ÚmodeÚdiscoverrú   rö   r   Úcountr•   )r#   Úfts_rebuild_statusr^   rœ   )rI   rú   rö   r   ÚextraÚstatusÚrebuilds   &&&&,  r   Ú_discover_payloadr/  :  s¤   € ô �B×)Ñ)¨4Ð1LÓM€FØ’N‰b¨¸9ÀfÈYÕFWÐY_Ø
<¸VÀIÕ=NÐ<OÈxØ�)Õ˜QÐ
˜t F¨7¥O°AÐ#6ð 7/ð	0ð;2ð )3€Gô Ñt�JÐt eÐt°FÐtÀGÐtÔSVÐW^ÓS_ÐtÐchÐtÐlsÑtÐtr   c          	      ó–   € V ^8„  d   QhR\         \        \        3,          R\        R\        \         \        \        3,          ,          /# )r   r  r  r.   )rB   r0   r   r™   )r   s   "r   r   r   E  s;   € ÷ Añ A”4œœS˜•>ð A¬ð A´´T¼#¼s¸(µ^Õ0Dñ Ar   c           	      ó¾   € V P                  V4      ;'       g    .  Uu. uF3  p\        VP                  R R4      4      '       d   K&  \        VRR7      NK5  	  up# u upi )r`   r4   r  r  )rT   rf   rÜ   )r  r  rÉ   s   && r   Ú_bookendr2  E  sZ   € Ø>B¿h¹hÀs»m×>QÐ>QÈrÐ>Qó AÑ>Q¸Ü)¨!¯%©%°	¸2Ó*>×?ô 4ŒN˜1¨d×3Ñ>Qñ Að Aùò As   ž#AÁAc                ó¢   € V ^8„  d   QhR\         R\        \         \        3,          R\         R\        \        \         \        3,          ,          /# )r   rë   Ú
match_infoÚresult_detailr.   )r0   rB   r   r   )r   s   "r   r   r   J  sD   € ÷ ñ ¤3ð ´D¼¼c¸µNð ÔSVð Ô[cÔdhÔilÔnqÐiqÕdrÕ[sñ r   c                ó  € VP                  R4      ;'       g    TVP                  R4      rT V P                  WE^^R7      p\        Y4      TR8H  r˜\        Y\        TP                  R	4      ;'       g    TP                  R
4      4      TP                  R4      ;'       g    TP                  RR4      TP                  R4      ;'       g    TP                  R4      ;'       g    RTP                  R4      ;'       g    RTP                  R4      YRP                  R4      ;'       g    RT	'       d   \        TR4      M. TP                  R4      ;'       g    .  U
u. uF/  q©'       g   T
P                  R4      T8X  g   K"  \        Y¥RR7      NK1  	  up
T	'       d   \        TR4      M. TP                  R^ 4      TP                  R^ 4      TR7      #   \         d&   p\        P                  ! RYETRR7        Rp?R# Rp?ii ; iu up
i )zQDiscovery result from a surviving FTS row; None (dropped) if the view can't load.r   rÏ   r  z&get_anchored_view failed for %s/%s: %sT©r   Nr  rP   Úsession_startedrQ   r2   rR   rS   rÐ   rð   r4   rñ   r	  r  r  ró   rô   rõ   rí   )
rT   r  r   r   ÚwarningrK   rø   r?   r2  rÜ   )rI   rë   r4  r5  Úhit_sidÚmsg_idr  r"   r  r  rÉ   s   &&&&       r   Ú_hydrate_hitr<  J  s¾  € à —n‘n \Ó2×BÐB°lÀJÇNÁNÐSWÓDXˆVðØ×#Ñ# G¸AÀqÐ#ÓIˆô +¨2Ó<¸mÈvÑ>U�$ÜØÜ˜|×/Ñ/°Ó=×bÐbÀÇÁÐPaÓAbÓcØ×Ñ Ó)×PÐP¨Z¯^©^¸HÀiÓ-PØ×Ñ˜wÓ'×OÐO¨:¯>©>¸'Ó+B×OÐOÀiØ×Ñ˜wÓ'×/Ð/¨4¸j¿n¹nÈVÓ>TØ¯©¸	Ó)B×)HÐ)HÀbß9=”h˜t _Ô5À2à ŸH™H XÓ.×4Ð4°"Ð4óXÙ4�a¾ÀÇÁÀtÃÐPVÑAVô L”. Àd×KÙ4ñXç59”H˜T =Ô1¸rØŸ™Ð!2°AÓ6ÀtÇxÁxÐP`ÐbcÓGdØôð øô	 ô Ü�ŠÐ@À'ÐSTÐ_cÕdÝûðüòXs#   ­G ÅHÅ?HÇH ÇG;Ç;H c                óR  € V ^8„  d   QhR\         R\        \        \         ,          ,          R\        R\        \         ,          R\         R\         R,          R\         R,          R	\        \        ,          R
\        \        ,          R\        \        \         ,          ,          R\         /# )r   rú   Úrole_filterÚlimitÚsortrö   Úcurrent_session_idNÚlink_profiler’   r“   r¤   r.   )r0   r   r™   r{   )r   s   "r   r   r   b  s«   € ÷ MPñ MPœð MP¬8´D¼µIÕ+>ð MPÄsð MPÔRZÔ[^ÕR_ð MPÜðMPÜ/2°T­zðMPÜPSÐVZÕPZðMPä ¤�ðMPä9AÄ#½ðMPô $,¬D´­IÕ#6ðMPô CFñMPr   c           	     óp  a aaaaa	€ V'       d   \        S V4      MRp\        S T
;'       g    . 4      p\        S SV4      pV'       dˆ   VR,          VP                  R4      ;'       g
    VR,          rþ\	        \        S V4      ;'       g    \        S V4      P                  R4      4      pWï0V,          '       g   \        VSS	4      '       g   Rp\        VV	V VVV3R lRR4      w  ppV'       d   V# \        VR R	7      pV'       g   V'       g   \        S SV. R
R7      # / pV'       d   V.M. pV'       d"   VP                  RR4      ;p'       d   RR/VV&   V F¸  p\        V4      V8¼  d    M§VR,          \        S VR,          4      ppVV9   g   VV9   d   KA  \        S VP                  R4      4      pV'       d$   VV8X  d   \        S V4      '       g   V'       g   K‡  V'       d   VV8X  d   V'       g   K   VP                  V/ VCRV/C4       Kº  	  VP                  4        FU  w  ppVP                  R4      '       d   K  \!        S TTVR8X  g	   V'       g   RMR4      pVf   KD  VP#                  V4       KW  	  V F  p\%        VR,          V4      VR&   K  	  \        S SVV\        V4      RR7      # )z=Discovery shape: FTS5 plus adaptive or full result hydration.Nr   r  rP   c                  óz   <€ SP                  SS;'       g    R R.\        \        4      \        ^ S\        S SR7	      # )ÚuserÚ	assistant)	rú   r>  Úexclude_sourcesr?  Úoffsetr@  r÷   r’   r“   )Úsearch_messagesr™   r  Ú_DISCOVER_SCAN_LIMITÚ_DISCOVER_SEARCH_FIELDS)r’   r“   rI   rú   r>  r@  s   €€€€€€r   r9   Ú_discover.<locals>.<lambda>q  sA   ø€  R×%7Ñ%7Ø ×!EÐ!E°¸Ð0EÜÔ4Ó5Ô=QÐZ[ÐbfÜ&°ÀYð &8ô &Pr   zFTS5 search failed: %szSearch failedc                 óF   € V P                  R 4      ;'       g    R\        9   # )rQ   r4   )rT   Ú_DEMOTED_SESSION_SOURCES)Úrs   &r   r9   rL  z  s   € °Q·U±U¸8³_×5JÐ5JÈÔOgÒ4gr   )r  u´   No matching sessions found. FTS5 ANDs all terms by default â€” broaden with OR (`alpha OR beta`), exact-match with quoted phrases, exclude with NOT, or prefix-match with `deploy*`.)ÚmessageÚ_title_onlyTrÏ   r  ÚcompactÚlinku=  When referring the user to a session, write its `link` value verbatim inline mid-sentence (it renders as a titled link) â€” never as markdown, in backticks, on its own line, or next to the title/id/date. To read more around a compact result, scroll: session_search(session_id=..., around_message_id=match_message_id).)Úsessions_searchedÚ	link_hint)rw   r§   r  rT   r�   rK   r–   r+   Úsortedr/  Úpoprœ   rÇ   r±   Ú
setdefaultrž   r<  r›   ré   )rI   rú   r>  r?  r@  rö   rA  rB  r’   r“   r¤   rû   Úexcluded_rootsÚtitle_resultÚ	title_sidÚ
title_rootÚtitle_startedÚraw_resultsÚerrÚseen_sessionsr   Útitle_lineagerO  Úraw_sidÚresolved_sidÚis_compacted_hitrë   r4  rÙ   s   fff&f&&&ff&                  r   Ú	_discoverre  b  s­  ý€ ÷
 HZÔ+¨BÐ0BÔCÐ_cÐÜ,¨RÐ1D×1JÐ1JÈÓK€NÜ& r¨5Ð2FÓG€L÷ Ø ,¨\Õ :¸L×<LÑ<LÈ_Ó<]×<{Ð<{ÐamÐnzÕa{�:Ü*Ô,=¸bÀ*Ó,M×,qÐ,qÔQbÐceÐgpÓQq×+vÑ+vð  xDó  ,Eó  FˆØÐ" ^×3Ô3¼?È=ÐZbÐdm×;nÒ;nØˆLÜ÷ Pñ Pð RjÐkzó|Ñ€K�÷ Øˆ
ô ˜Ñ*gÔh€KçŸ|Ü   U¨F°BðIôKð 	Kð 02€Mß ,ˆ|‰n°"€Gß¨,×*:Ñ*:¸?ÈDÓ*QÐQ˜ÖQØ(5°tÐ'<ˆ�mÑ$ó ˆÜˆ}Ó Ô&ÙØ ! ,¥Ô1AÀ"ÀaÈÅoÓ1V�ˆØ�nÔ$¨¸Ô(FÙô 1°°Q·U±U¸4³[ÓAÐß LÐ4HÔ$HÜ*¨2¨w×7Ò7×;KÙß 'Ð-?Ô"?×HXÙØ× Ñ  Ð/S°!Ð/S°_ÀlÑ/SÖTñ- ð. %2×$7Ñ$7Ö$9Ñ ˆ�jØ�>‰>˜-×(Ò(Ùä˜R ¨zÀVÈvÔEU×]d¹6ÐjsÓtˆØÔØ�N‰N˜5Ö!ñ %:ó ˆÜ% e¨LÕ&9¸<ÓHˆˆf‹ñ ä˜R ¨°Ì3È}ÓK]ð	NôPð Pr   c                ó$   € V ^8„  d   QhR\         /# )r   rÞ   rX   )r   s   "r   r   r   ²  s   € ÷ 
_ñ 
_¤ñ 
_r   c                ó4  € V e    \        V 4      P                  4       '       g   R# ^ RIHp ^ RIHp VP                  V 4      pVP                  V4       VP                  V4      '       g   \        RV R24      hV! VP                  V4      R,          RR7      # )	zTAnother profile's ``state.db`` opened read-only (safe on a live DB); None = current.N)Úprofiles)Ú	SessionDBú	profile 'z' does not existústate.dbT©Údb_pathÚ	read_only)r0   r~   Ú
hermes_clirh  Úhermes_stateri  Únormalize_profile_nameÚvalidate_profile_nameÚprofile_existsr†   Úget_profile_dir)rÞ   Úprofiles_modri  Úcanons   &   r   Ú_resolve_profile_dbrw  ²  s„   € à‚œc '›l×0Ñ0×2Ò2ÙÝ3Ý&Ø×/Ñ/°Ó8€EØ×&Ñ& uÔ-Ø×&Ñ& u×-Ò-Ü˜9 U GÐ+;Ð<Ó=Ð=Ù˜\×9Ñ9¸%Ó@À:ÕMÐY]Ô^Ð^r   c          
      ób   € V ^8„  d   QhR\         R\        R\        R\         R,          R\         /# )r   r   ÚheadÚtailrB  Nr.   ©r0   r{   )r   s   "r   r   r   ¿  s>   € ÷ vñ v¤#ð v¬Sð v¼Sð vÔUXÐ[_ÕU_ð vÔknñ vr   c                óÈ  a a€ \        S S4      pV'       g   \        RS 2RR7      # \        V V3R lRRS4      w  rgV'       d   V# V Uu. uF  p\        V\        R7      NK  	  p	p\        V	4      \        V	4      W#,           8„  rº\        RRR	R
SR\        SV4      R\        V4      RT
RTRV'       d   V	RV W“) R ,           MT	/V'       d   RRV
 RV RV R2/B # / B # u upi )zQRead shape: whole session, or ``head`` + ``tail`` messages with a scroll pointer.úsession_id not found: Fr%   c                  ó&   <€ S P                  S4      # rE   r  rH   s   €€r   r9   Ú_read_session.<locals>.<lambda>Ä  r  r   zget_messages failed for %s: %szfailed to load sessionr  r(  Úreadr   rS  r  Úmessage_countÚ	truncatedrò   NrP  zSession has z messages; showing first z + last z=. Pass around_message_id (any id above) to scroll the middle.r•   )	rK   r(   r+   rÜ   Ú_READ_MAX_CONTENTrœ   r^   ré   rU   )rI   r   ry  rz  rB  rM   Úrowsr_  rÉ   Úshapedr'  r‚  s   ff&&&       r   Ú_read_sessionr†  ¿  s:  ù€ ä˜R Ó,€DßÜÐ2°:°,Ð?ÈÔOÐOÜÕ9Ð;[Ð]uØ ó"�I€Dç
Øˆ
ÙLPÓQÉDÀqŒn˜QÔ0A×BÉD€FÐQÜ˜6“{¤C¨£K°$µ+Ñ$=ˆ9Üñ v�Fð v zð v¼ÀjÐR^Ó8_ð vÜ/°Ó5ðvØEJðvØV_ðvç:C˜˜u ˜¨¨u¨v¨Ö6Èðv÷ clð  ¨e¨WÐ4MÈdÈVÐS[Ð\`Ð[að b]ð  ]ð _ñvð vð rtñ	vð vùò Rs   Á
Cc                óR   € V ^8„  d   QhR\         R\        \         ,          R\         /# )r   r¡   rÞ   r.   )r0   r   )r   s   "r   r   r   Ñ  s*   € ÷ lñ lœ#ð l¬´­ð l¼#ñ lr   c                ó¤   € \        WVR7      p\        P                  ! V4      P                  R4      RJg	   V'       d   V# \	        RV R2RR7      # )u‰  Read shape scoped to ONE store: the caller's profile, or the profile it named.

A miss is a miss. Profiles are isolated islands, so a bare id never falls through to
a scan of every other profile's ``state.db`` â€” that returned another profile's full
transcript to any caller holding the id (#106761). The hint tells the model how to
ask properly: ``@session:<profile>/<id>`` or ``profile=``.
©rB  r&   Fz&session_id not found in this profile: z^. If it belongs to another profile, pass profile=<name> (or the @session:<profile>/<id> link).r%   )r†  r[   ÚloadsrT   r(   )rI   r¡   rÞ   Úresults   &&& r   Ú_read_scopedrŒ  Ñ  sY   € ô ˜2°Ô9€FÜ‡z‚z�&Ó×Ñ˜iÓ(°Ó5¿ØˆÜÐ>¸s¸eð D\ð \Øejôlð lr   c                ód   € V ^8„  d   QhR\         R\        R,          R\        R,          R\        /# )r   r?  rA  NrB  r.   )r{   r0   )r   s   "r   r   r   à  s4   € ÷ ñ ¤Sð ¼cÀD½jð Ô_bÐeiÕ_ið Ôuxñ r   c                óR   a aaa€ VV VV3R lp\        VRR4      w  rVT;'       g    T# )zFBrowse shape: metadata for the most recent sessions (no LLM, no FTS5).c                  óÞ  <€ \        S
R R4      p V f   \        R4      hV ! S^,           \        \        4      RR7      pS	'       d   \	        S
S	4      MRw  r#S	V'       d   V'       d   TMR0pV Uu. uF  qUP                  RR4      V9  g   K  VNK  	  upRS  UUu. uF–  pRVP                  RR4      R\        VP                  RR4      S4      R	VP                  R	4      ;'       g    R/R Uu/ uF  qwVP                  VR4      bK  	  upCR
VP                  R
^ 4      RVP                  RR4      /CNK˜  	  ppp\        RV\        V4      R\        V4       R2R7      # u upi u upi u uppi )Úlist_recent_sessions_boundedNz?session database does not support bounded recent-session browseg      @)r?  rG  Útimeout_secondsrÏ   r4   r   rS  rS   r�  ÚpreviewÚbrowsezShowing zZ most recent sessions. Pass a query= to search, or session_id+around_message_id to scroll.)r(  r   r*  rP  )NF)rQ   rP   Úlast_active)	ÚgetattrÚRuntimeErrorr™   r  rs   rT   ré   r^   rœ   )Úbounded_listÚsessionsÚcurrent_rootÚhas_compression_hopÚhiddenÚxrr   rÚ   r   rA  rI   r?  rB  s            €€€€r   Ú_browseÚ&_list_recent_sessions.<locals>._browseâ  sŽ  ø€ ô ˜rÐ#AÀ4ÓHˆØÒÜÐ`ÓaÐaÙØ˜"•*Ü Ô!8Ó9È3ôPˆ÷ ;MÔ˜rÐ#5Ô6ÐR_ñ 	*ˆð %×6IÏl¡lÐ`dÐeˆñ
 "*ÓK¡˜A¯U©U°4¸«_ÀFÑ-J—a�a¡ÑKÈFÈUÑSô	Uñ T�ð ˜!Ÿ%™%  b›/¨6´=ÀÇÁÀtÈRÃÐR^Ó3_Ø�Q—U‘U˜7“^×+Ð+ tðYáIpÓ/qÑIpÀA°1·5±5¸¸B³<²ÑIpÑ/qðYð ˜QŸU™U ?°AÓ6¸	À1Ç5Á5ÈÐTVÓCWôYñ Tð	 	ñ Uô
 ˜¨'¼¸W»Ø”s˜7“|�nð %9ð 9ô;ð 	;ùò Lùò 0rùóUs+   Á/EÂEÂAE)Ã'E)Ã.E$Ä	.E)Å$E)z!Error listing recent sessions: %szFailed to list recent sessions)r+   )rI   r?  rA  rB  r�  rŸ   r_  s   ffff   r   Ú_list_recent_sessionsrŸ  à  s-   û€ ÷;ð ;ô6 �WÐAÐCcÓd�H€CØ�:ˆ:�#Ðr   c                óH   € V ^8„  d   QhR\         R\         R\         R\         /# )r   r   ÚloÚhir.   )r{   )r   s   "r   r   r     s(   € ÷ #ñ #œsð #¬ð #´ð #¼ñ #r   c                 óv   €  \        V 4      p \        V\	        W4      4      #   \        \        3 d    Tp  L*i ; irE   )r{   rŽ   r†   r  Úmin)rz   r   r¡  r¢  s   &&&&r   Ú
_clamp_intr¥    s>   € ðÜ�E“
ˆô ˆr”3�u“>Ó"Ð"øô ”zÐ"ô ØŠðús   ‚" ¢8·8c                ó<   € V ^8„  d   QhR\         R\         R\        /# )r   Ú
anchor_sidrA  r.   ra   )r   s   "r   r   r   	  s(   € ÷ xñ x¼#ð xÔSVð xÔ[_ñ xr   c                ó¬   € \        WV4      '       d   \        V4      '       d   R# VRJ;'       d    VR,          ^ 8H  ;'       g    \        W4      '       * # )aC  True when the scroll anchor is still in the caller's active context (reject).
Same-lineage history that LEFT live context (compacted rows, compression-ended
parents, /new-reset predecessors) passes, so scroll never rejects a discovery result.
Rewind/undo rows (active=0, compacted!=1) never count as out-of-context history.FNrÂ   )r­   rÄ   r±   )rI   Úanchor_stater§  rA  s   &&&&r   Ú_anchor_in_live_contextrª  	  sP   € ô
 ˜Ð);×<Ò<Ô@SÐT`×@aÒ@aÙØ Ð$×DÐD¨°hÕ)?À1Ñ)D×wÐwÔMgÐhjÓMwÔIwÐwr   c          
      ób   € V ^8„  d   QhR\         R\        R\        R\         R,          R\         /# )r   r   Úaround_message_idr	  rA  Nr.   r{  )r   s   "r   r   r     s<   € ÷ +Eñ +EœCð +E´Cð +EÄð +EÜ # d¥
ð+EÜ69ñ+Er   c                ó$  a aaaa€  \        S4      o\	        S^^^4      o\        S S4      pT;'       g    / P                  R4      oT'       d,   \        S TS;'       g    ST4      '       d   \        RRR7      # \        S S4      pT'       g   \        RS 2RR7      # \        TT TT3R lRR	4      w  rxT'       d   T# TP                  R
4      ;'       g    . p	/ p
T	'       g‹   S'       dƒ   SS8w  d|   \        S SS4      ;'       d    \        TT TT3R lRRRR7      pT'       dI   TP                  R
4      '       d2   RS RS RS R2T
R&   Y»R
,          Suryo\        S S4      ;'       g    TpT	'       g   \        RS RS 2RR7      # \        R RRRSRSR\        T4      R
SRT	 Uu. uF  p\        TSR7      NK  	  upRTP                  R^ 4      RTP                  R^ 4      RR/	T
B #   \        \        3 d    \        RRR7      u # i ; iu upi )!zDScroll shape: a window centered on an anchor (no FTS5, no bookends).z)scroll requires integer around_message_idFr%   r   z]scroll rejected: anchor lives in the current session lineage (already in your active context)r}  c                  ó,   <€ SP                  SS SR 7      # ©)r	  ©Úget_messages_around)r¬  rI   r   r	  s   €€€€r   r9   Ú_scroll.<locals>.<lambda>#  s   ø€ ˜b×4Ñ4°ZÐARÐ[aÐ4Ôbr   zget_messages_around failed: %szfailed to load messagesr	  c                  ó,   <€ SP                  SS SR 7      # r¯  r°  )r¬  rI   Úowningr	  s   €€€€r   r9   r²  -  s   ø€ �B×*Ñ*¨6Ð3DÈVÐ*ÔTr   Nz%rebind get_messages_around failed: %sTr;   zaround_message_id z
 lives in z (child of z); rebound transparentlyr9  z not in session_id r(  Úscrollr¬  r  rò   )rÊ   rô   rõ   ÚhintzóScroll forward: re-call with around_message_id = the LAST message's id; backward: the FIRST message's id (the boundary message repeats as an orientation marker). messages_before/messages_after < window means you've hit that end of the session.r•   )r{   rŽ   r†   r(   r¥  r¾   rT   rª  rK   r+   r­   r#   r^   rU   rÜ   )rI   r   r¬  r	  rA  r©  r  r  r_  rò   r,  Úrebind_viewrÉ   r´  s   ffff&        @r   Ú_scrollr¸    s}  ü€ ðVÜÐ 1Ó2Ðô ˜  1 bÓ)€Fä-¨bÐ2CÓD€LØ× Ð ˜b×%Ñ% lÓ3€FßÔ5°b¸,È×H\ÐH\ÐR\Ð^p×qÒqÜÐyð  DIô  Jð  	JÜ$ R¨Ó4€LßÜÐ2°:°,Ð?ÈÔOÐOÜ×bØ6Ð8QóS�I€Dç
Øˆ
Ø�x‰x˜Ó!×'Ð' R€HØ€EßŸ 6¨ZÔ#7ô $ B¨
°FÓ;÷ Jð JÄßTØÐ9ÀDôAJˆ÷ ˜;Ÿ?™?¨8×4Ò4Ø"4Ð5FÐ4GÀzÐRXÐQYð Z-Ø-7¨LÐ8Pð!RˆE�)Ñà)4À(Õ6KÈVÐ&ˆD˜JÜ,¨R°Ó8×HÐH¸LˆLßÜÐ.Ð/@Ð.AÐATÐU_ÐT`ÐaÐkpÔqÐqÜñ EØðEØ",ðEØ@QðEä(¨Ó6ðEà?EðEñ KSÓSÉ(ÀQ”. Ð.?×@É(ÑSðEð Ÿ™Ð!2°AÓ6ð	Eð HLÇxÁxÐP`ÐbcÓGdð	Eð
:ðEð ?DñEð Eøô= ”zÐ"ô VÜÐEÈuÔUÒUðVüòB Ts   ‡G) Æ&H Ç)H
È	H
c                ó$   € V ^8„  d   QhR\         /# rW   rX   )r   s   "r   r   r   A  s   € ÷ Qñ QäDGñQr   c                ó  € \        V\        4      '       dP   VP                  4       '       d:   Ve   \        W5P                  4       WgV4      # \	        W5P                  4       V	4      # \        V^^^
4      pV '       d-   \        V \        4      '       d   V P                  4       '       g   \        W2WIR7      # \        V\        4      '       d   VP                  4       P                  4       MRp \        V4      \        V4      pp\        Y0P                  4       Y.R	9   d   TMR\        T\        4      '       dR   TP                  R4       Uu. uF+  pTP                  4       '       g   K  TP                  4       NK-  	  up;'       g    RMR\        T
\        4      '       d&   T
P                  4       P                  4       R8X  d   RMRYITT\        T4      R7      #   \         d!   p\        \        T4      RR7      u Rp?# Rp?ii ; iu upi )
zHMode dispatch (see module docstring); scroll wins when an anchor is set.Nr‰  Fr%   r&  r  Úadaptive)rI   rú   r?  r@  r>  rö   rA  rB  r’   r“   r¤   )ÚnewestÚoldest)r<   r0   r~   r¸  rŒ  r¥  rŸ  r„   r‹   r†   r(   re  Úsplitr¢   )rú   r>  r?  rI   rA  r   r¬  r	  r@  rÞ   rö   ÚafterÚbeforer¤   Ú	sort_normr’   r“   r"   rO  s   &&&&&&&&&&&&&&     r   Ú	_dispatchrÂ  A  s�  € ô �*œc×"Ò" z×'7Ñ'7×'9Ò'9ØÒ(Ü˜2×/Ñ/Ó1Ð3DÐN`ÓaÐaÜ˜B× 0Ñ 0Ó 2°GÓ<Ð<Ü�u˜a  BÓ'€Eßœ
 5¬#×.Ò.°e·k±k·m²mÜ$ RÐ0BÔYÐYÜ(2°4¼×(=Ò(=�—
‘
“×"Ñ"Ô$À4€Ið1Ü.¨uÓ5Ô7GÈÓ7O�)ˆô Ø—[‘[“]¨%ÐPdÔCd±iÐjnÜZdÐepÔru×ZvÒZv¨×):Ñ):¸3Ô)?ÓMÑ)? AÀ1Ç7Á7Ç9”i�a—g‘g–iÑ)?ÑM×UÐUÐQUøð  }AÜ# F¬C×0Ò0°V·\±\³^×5IÑ5IÓ5KÈvÔ5U‰vÐ[eØ-ÈhÐbkÜ:Ð;NÓOôQð Qøô ô 1Üœ#˜a›&¨%Ô0Õ0ûð1üò Ns*   Ã,G Å	HÅ&HÇHÇ"G=Ç7HÇ=Hr»  c                ó\  € V ^8„  d   QhR\         R\         R,          R\        R\         R,          R\         R,          R\        R,          R\        R	\         R,          R
\         R,          R\         R\         R,          R\         R,          R\        \        \         ,          ,          R\         /# )r   rú   r>  Nr?  rA  r   r¬  r	  r@  rÞ   rö   r¿  rÀ  r¤   r.   )r0   r{   r   r™   )r   s   "r   r   r   Y  sÃ   € ÷ 1iñ 1iœ#ð 1i´°tµð 1iÌ3ð 1iÜ'*¨T¥zð1iÜFIÈDÅjð1iÜloÐrvÕlvð1iäð1iä*-°­*ð1iäFIÈDÅjð1iäadð1iô  �*ð1iô 69¸4µZð1iô ^fÔfjÔknÕfoÕ]pð1iô }@ñ1ir   c                óH  aaaa€ ^ RI Ho ^ RIHoHp ^ RIHo . p\        V\        4      '       dT   RV9   dM   VP                  R4      w  pppV'       d0   TpV'       d&   V	e    \        V	4      P                  4       '       g   Tp	 \        V	4      pTe   TRrCTP!                  T4       ^ RIHp \        TT4      '       d   RpTf:   \'        TT3R lRR4      pTf   \        T! 4       RR7      # TP!                  T4        \)        YY#YEYgY‰T
Y¼TR7      \+        T4       F  o\'        TT3R lRR4       K  	  #   \         d7   p\        P                  ! RT	RR7       \        R	T	 R
T 2RR7      u Rp?# Rp?ii ; i  \+        T4       F  o\'        TT3R lRR4       K  	  i ; i)z†Run session search, closing DBs opened here. Positional order is frozen for old callers;
new parameters are appended after ``detail``.)Úget_hermes_home)ri  Úformat_session_db_unavailable)Úrelease_or_closerç   Nz&session_search: cannot open profile %rTr7  rj  z': Fr%   )ÚRuntimeSessionStorec                  ó0   <€ S ! S! 4       R ,          RR7      # )rk  Trl  r•   )ri  rÅ  s   €€r   r9   Ú session_search.<locals>.<lambda>~  s   ø€ ‘I¡oÓ&7¸*Õ&DÐPTÕUr   z(SessionDB unavailable for session_search)r¿  rÀ  r¤   c                  ó   <€ S! S 4      # rE   r•   )Úowned_dbrÇ  s   €€r   r9   rÊ  Š  s   ø€ Ñ+¨HÔ5r   z(Failed to close session_search SessionDB)Úhermes_constantsrÅ  rp  ri  rÆ  Úhermes_state_registryrÇ  r<   r0   Ú	partitionr~   rw  r   r   r   r(   r›   Úagent.runtime_session_storerÈ  r#   rÂ  Úreversed)rú   r>  r?  rI   rA  r   r¬  r	  r@  rÞ   rö   r¿  rÀ  r¤   rÆ  Ú	owned_dbsÚemb_profileÚ_Úemb_idÚ
profile_dbr"   rÈ  ri  rÅ  rÌ  rÇ  s   &&&&&&&&&&&&&&        @@@@r   Úsession_searchr×  Y  s�  û€ õ 1ßEÝ6Ø€Iô �*œc×"Ò" s¨jÔ'8Ø!+×!5Ñ!5°cÓ!:Ñˆ�Q˜ßØˆJß ¢´s¸7³|×7IÑ7I×7KÒ7KØ%�ðFÜ(¨Ó1ˆ
ð ÒØ!+¨TÐØ×Ñ˜Ô$õ
 @Ü�"Ð)×*Ò*ØˆØ	‚zÜÝUØÐ<ó
ˆð Š:ÜÑ;Ó=ÀuÔMÐMØ×Ñ˜ÔðiÜ˜¨UÐ8JØ*°DÀ6Ø$ÐI\ô^ô ! Ö+ˆHÜÕ5°tÐ=gÖhò ,øô5 ô FÜ�ŠÐ>ÀÐRVÕWÜ˜I g Y¨c°!°Ð5¸uÔEÕEûðFûô4 ! Ö+ˆHÜÕ5°tÐ=gÖhò ,ús*   ÂD7 Ä E; Ä7E8Å+E3Å-E8Å3E8Å;&F!c                ó$   € V ^8„  d   QhR\         /# rW   r   )r   s   "r   r   r   �  s   € ÷ ñ ¬4ñ r   c                 ór   €  ^ RI Hp  V ! 4       P                  P                  4       #   \         d     R# i ; i)z#Requires the SQLite state database.©Ú_default_db_pathF)rp  rÛ  ÚparentÚexistsÚImportErrorrÚ  s    r   Ú!check_session_search_requirementsrß  �  s4   € ðÝ1ÙÓ!×(Ñ(×/Ñ/Ó1Ð1øÜô Úðús   ‚$' §6µ6rè   r×  Údescriptionu[  Recall past conversations: search or read old Hermes sessions (FTS5), or scroll inside one. Four shapes, picked by args: `query` = discovery (top-N matching sessions, top result fully hydrated); `session_id` + `around_message_id` = scroll (window of messages around an anchor); `session_id` alone = read a whole session â€” how you resolve an `@session:<profile>/<id>` link (split on '/' into profile + id); no args = browse recent sessions. Results are actual DB messages, no LLM. Searches conversation history ONLY â€” when the user gave a direct source (URL, file, contact, live system), inspect that first; never conclude 'not found' from history alone. Use for questions about past conversations: 'what did we do about X', 'where did we leave Y'. When referring the user to a session, write its `link` value verbatim inline (it renders as a titled link).Ú
parametersÚtypeÚobjectÚ
propertiesrú   ÚstringzÇSearch query (discovery shape). Keywords, phrases, or boolean expressions to find in past sessions. Omit to browse recent sessions. Ignored when session_id + around_message_id are set (scroll shape).r?  Úintegeru°   Discovery shape only. Max sessions to return (default 3, max 10). Bump to 5â€“10 when the topic likely spans several sessions and you want to pick the right one to scroll into.r   r@  Úenumr¼  r½  z®Discovery shape only. Temporal bias on top of FTS5 ranking: omit for relevance-only (exploratory recall), 'newest' for "where did we leave X", 'oldest' for "how did X start".rö   r  zÞDiscovery shape only. 'adaptive' (default) fully hydrates the top-ranked result and returns only the exact anchor message for lower-ranked results. 'full' returns bookends and the complete anchored window for every result.r¿  zîDiscovery shape only. Inclusive lower bound on session start time. ISO date/datetime (e.g. 2026-06-01) or relative duration (7d, 24h, 2w = within the last N). Use only when the user names a time frame. sort is a ranking bias, not a bound.rÀ  zÛDiscovery shape only. Exclusive upper bound on session start time. ISO date/datetime (a date-only value is midnight UTC that day) or relative duration (7d = older than a week). Use only when the user names a time frame.r¤   Úarrayrž   z°Discovery shape only. Session ids already inspected this task. Those sessions and their lineage are omitted so a later query explores instead of repeating the same hit. Cap 20.z…Scroll shape. Session to read inside. Use the session_id returned from a prior discovery call. Must be paired with around_message_id.r¬  u�   Scroll shape. Message id to center the window on â€” use match_message_id from a discovery result, or any id from a prior window.r	  z€Scroll shape only. Messages to return on each side of the anchor (anchor itself always included). Clamped to [1, 20]. Default 5.r>  zåOptional. Comma-separated roles to include. Discovery defaults to 'user,assistant' (tool output is usually noise). Pass 'user,assistant,tool' to include tool output (debugging tool behaviour) or 'tool' to search tool output only.rÞ   zãOptional. Read sessions from another Hermes profile's database (read-only). Use when resolving an `@session:<profile>/<id>` link: pass the profile segment here with session_id as the id segment. Omit to use the current profile.Úrequired)Úregistryr(   c                 óF  € \        RR V P                  R 4      ;'       g    RRV P                  R^4      RV P                  R^4      RV P                  RR4      RVP                  R4      RVP                  R4      /R	 Uu/ uF  q"V P                  V4      bK  	  upB # u upi )
rú   r4   r?  r	  rö   r»  rI   rA  r•   )r>  r   r¬  r@  rÞ   r¿  rÀ  r¤   )r×  rT   )ÚargsÚkwrÚ   s   &, r   r9   r9   !  sÁ   € œ~ñ  PØ�h‰h�wÓ×%Ð% 2ð PØ-1¯X©X°g¸qÓ-Að PØJNÏ(É(ÐS[Ð]^ÓJ_ð Pà�x‰x˜ *Ó-ð Pà24·&±&¸³,ð PàSU×SYÑSYÐZnÓSoð Pñ$Nó Oñ $N˜aˆd�h‰h�q‹kŠ>ñ $Nñ Oò PùòOs   Á?Bu   ðŸ”�)rè   ÚtoolsetÚschemaÚhandlerÚcheck_fnÚemoji)ÚkanbanÚsubagentÚtool)Úcron)rÏ   r   rÐ   rð   rQ   rR   r8  )z[CONTEXT COMPACTIONz[CONTEXT SUMMARY]:)NNrE   )NNNNN)é   é
   N)r  N)NNN)r4   Nr  NNNNr  NNr»  NNN)HÚ__doc__r[   r   Úrer�   r   r   r   Útypingr   r   r   r   r	   Úhermes_state_commonr
   Úhermes_timer   r  rN  rƒ  rJ  r�   ÚcompileÚ
IGNORECASEr   rƒ   rK  re   r°   r#   r+   r?   rK   rU   r^   rf   rs   rw   r‹   r�   r–   r¢   r§   r­   r±   r¾   rÄ   rÇ   rÜ   ré   rø   r  r/  r2  r<  re  rw  r†  rŒ  rŸ  r¥  rª  r¸  rÂ  r×  rß  ÚSESSION_SEARCH_SCHEMAÚtools.registryrê  r(   Úregisterr•   r   r   Ú<module>r     s  ðñó Û Û 	Û ß ,Ñ ,ß 3Õ 3å 5Ý %ð 9Ð ð %Ð ð Ð ð Ð àÐ à—Z’ZÐ 4°b·m±mÓDÐ Ø˜t S¨%°°fÐ=Ð àgÐ àDÐ ð 1Ð ð¸÷ òGõJõTõDõ
HõOõ õ 1õ#õ4õ"jõ
õõ>õ
Qõ&õRõK÷O÷"	Qõõ#'õLuõAõ
÷0MPõ`
_÷võ$l÷õB#õx÷+E÷\Q÷01iõhð ÐØð	0ð Ø�ØØØ˜Øð&ðð Ø˜	ØðAð ˜1ðð Ø˜Ø˜ 8Ð,ØðRð	ð Ø˜Ø˜ VÐ,Øð8ð
 ˜:ð
ð Ø˜ØðIðð Ø˜Øð8ðð "Ø˜Ø˜& (Ð+ØðJð	$ð Ø˜Øð)ðð  Ø˜	Øð$ð"ð Ø˜	ØðVð ˜1ðð Ø˜ØðGðð Ø˜Øð7ððGl
ðZ 	�Bð_pð#BÐ ÷J 0à × Ò Ø	ØØ ñPð
 /Ø
÷
r   