+
    lHàjz¡  ã                   ó  a € R6 t30 t R t^ RIt^ RIt^ RIt^ RIt^ RIHtHt ^ RI	H
t
 ^ RIHt ^ RIHtHtHtHtHt ^ RIHt ^ RIHt ]P0                  ! R4      tR	R
RR/tRtR R lt]
! RRR7      t] ^ k R R ltR R ltR R lt R R lt!]"PG                  / ]$PK                  RR4      C]$PK                  RR4      C4      t&R R  lt'R! R" lt(R# R$ lt)R% R& lt*R' R( lt+R)t,R* R+ lt-R, R- lt.R. R/ lt/R0 R1 lt0R2 R3 lt1 ! R4 R54      t2R# )7u!  MemoryStore â€” bounded, file-backed curated memory (MEMORY.md / USER.md).
Entries are joined by ``ENTRY_DELIMITER``; budgets are in chars (model-independent).
Module state that tests monkeypatch (``get_memory_dir``, ``fcntl``/``msvcrt``) stays
in ``tools.memory_tool`` and is read lazily.N)ÚcontextmanagerÚsuppress)Ú
ContextVar©ÚPath)ÚAnyÚDictÚListÚOptionalÚTuple)Úatomic_write_text)Úfirst_threat_messageztools.memory_toolÚmemoryzMEMORY (your personal notes)ÚuserzUSER PROFILE (who the user is)u   
Â§
c                óF   € V ^8„  d   QhR\         R\        \         ,          /# )é   ÚcontentÚreturn©Ústrr
   )Úformats   "Ú</home/ubuntu/.hermes/hermes-agent/tools/memory_tool_store.pyÚ__annotate__r      s   € ÷ :ñ :¤#ð :¬(´3­-ñ :ó    c                ó   € \        V RR7      # )z˜Error string if *content* matches injection/exfil patterns. Strict scope:
memory enters the system prompt, so a poisoned entry persists across sessions.Ústrict©Úscope)Ú_first_threat_message)r   s   &r   Ú_scan_memory_contentr      s   € ô ! °Ô9Ð9r   Úmemory_failure_classÚother©Údefaultc                ó^   € V ^8„  d   QhR\         R\         R\        \         \        3,          /# )r   ÚmessageÚfailure_classr   ©r   Údictr   )r   s   "r   r   r   '   s)   € ÷ 9ñ 9”Cð 9¬ð 9¼¼cÄ3¸h½ñ 9r   c                 ó<   € \         P                  V4       R RRV /VC# )ÚsuccessFÚerror)ÚFAILURE_CLASSÚset)r%   r&   Úextras   &&,r   Ú_errorr/   '   s$   € Ü×Ñ�mÔ$Ø�u˜g wÐ8°%Ð8Ð8r   c                ó0   € V ^8„  d   QhR\         R\         /# )r   Úfilenamer   ©r   )r   s   "r   r   r   ,   s   € ÷ 9ñ 9œCð 9¤Cñ 9r   c                ó   € V R8X  d   R# R# )zTThe memory tool target that owns a store file, for hints that show the call to make.úUSER.mdr   r   © )r1   s   &r   Ú_store_targetr6   ,   s   € à Ô*ˆ6Ð8°Ð8r   c                ó^   € V ^8„  d   QhR\         R\        R\        \        \        3,          /# )r   ÚpathÚbak_pathr   )r   r   r(   r   )r   s   "r   r   r   1   s)   € ÷ ,ñ ,”tð ,¤sð ,¬t´C¼°H­~ñ ,r   c           	     óp   € \        RV P                   RV R2RVR\        V P                  4       R2R7      # )zPExternal drift: the file wouldn't round-trip, so flushing would discard content.úRefusing to write uÜ   : it holds an entry larger than the whole store's char limit, i.e. free-form text written without Â§ delimiters (the patch tool, a shell append, a manual edit). Rewriting it would lose that text. A snapshot was saved to uÊ   . Resolve the drift first â€” either rewrite the file as a clean Â§-delimited list of entries, or move the extra content out â€” then retry. This guard exists to prevent silent data loss (issue #26045).ÚdriftztOpen the .bak file, integrate the missing entries into the memory tool one at a time via memory(action=add, target='zK', content=...), then remove or rewrite the original file to a clean state.)Údrift_backupÚremediation)r/   Únamer6   )r8   r9   s   &&r   Ú_drift_errorr@   1   sX   € äØ
˜TŸY™Y˜Kð (MàMUÈJð Wdð	eð
 ˜Xð	&Ü&3°D·I±IÓ&>Ð%?ð @*ð	*ô	,ð 	,r   c                óR   € V ^8„  d   QhR\         R\        \        \        3,          /# ©r   r8   r   )r   r(   r   r   )r   s   "r   r   r   ?   s&   € ÷ gñ gœTð g¤d¬3´¨8¥nñ gr   c                ó6   € \        RV P                   R2R4      # )zNExisting-but-unreadable file: saving from an assumed-empty view would wipe it.r;   u=  : the file exists on disk but could not be read right now (temporarily locked by another program, a permission change, invalid/corrupt text encoding, or a filesystem error). Treating an unreadable file as empty and saving would wipe existing memory, so the write is refused. Nothing was changed â€” retry in a moment.Úread_failed)r/   r?   ©r8   s   &r   Ú_read_failed_errorrF   ?   s/   € äØ
˜TŸY™Y˜Kð (Vð 	Wð Yfó	gð gr   u   "`â€˜â€™â€šâ€›â€œâ€�â€žâ€ŸÚ'u   â€�â€‘â€’â€“â€”â€•âˆ’Ú-c                ó0   € V ^8„  d   QhR\         R\         /# ©r   Útextr   r2   )r   s   "r   r   r   N   s   € ÷ Rñ Rœsð R¤sñ Rr   c                ó˜   € RP                  \        V 4      P                  RR4      P                  \        4      P                  4       4      # )a2  Quote/dash/whitespace-folded form for tolerant old_text matching. Models re-emit an
entry with straight quotes for curly ones, '-' for an em dash, unwrapped lines, or a
newline over-escaped to a literal backslash-n, and a byte-exact substring test then
reports "No entry matched" for an unambiguous target.Ú z\n)Újoinr   ÚreplaceÚ	translateÚ_MATCH_FOLDÚsplit©rK   s   &r   Ú_normalize_for_matchrT   N   s8   € ð
 �8‰8”C˜“I×%Ñ% e¨SÓ1×;Ñ;¼KÓH×NÑNÓPÓQÐQr   c                óh   € V ^8„  d   QhR\         \        ,          R\        R\         \        ,          /# ©r   ÚentriesÚold_textr   )Úlistr   Úint)r   s   "r   r   r   V   s.   € ÷ Sñ S¤¤S¥	ð S´Sð S¼TÄ#½Yñ Sr   c                ól  € \        V 4       UUu. uF  w  r#W9   g   K  VNK  	  upp;p'       d   V# \        V4      p\        ;QJ d    R V 4       F  '       g   K   RM	  RM! R V 4       4      '       g   . # \        V 4       UUu. uF  w  r#V\        V4      9   g   K  VNK  	  upp# u uppi u uppi )zSIndices of entries containing *old_text*: byte-exact first, else typography-folded.c              3   ó@   "  € T F  qP                  4       x € K  	  R # 5i©N)Úisalnum)Ú.0Úcs   & r   Ú	<genexpr>Ú%_substring_matches.<locals>.<genexpr>[   s   é € Ð+¡F˜q�y‰y�{ˆ{£Fùó   ‚TF)Ú	enumeraterT   Úany)rW   rX   ÚiÚeÚexactÚneedles   &&    r   Ú_substring_matchesrj   V   s™   € ä(¨Ô1ÔCÑ1‘t�q°X±]—�Ñ1ÒCÐC€uÖCØˆÜ! (Ó+€Fß‹3Ñ+¡FÓ+�3�3Š3Ñ+¡FÓ+×+Ò+Øˆ	Ü# GÔ,ÔRÑ,‘$�!°Ô:NÈqÓ:QÑ0Q�AˆAÑ,ÒRÐRùó Dùó
 Ss   �
B*žB*ÂB0Â B0c                óŠ   € V ^8„  d   QhR\         \        ,          R\        R\        \        \        ,          \
        3,          /# rV   )rY   r   Útupler
   rZ   Úbool)r   s   "r   r   r   `   s4   € ÷ 4ñ 4¤¤S¥	ð 4´Sð 4¼UÄ8ÌCÅ=ÔRVÐCVÕ=Wñ 4r   c                ó  € \        V 4       UUu. uF  w  r#W18X  g   K  VNK  	  pppT;'       g    \        W4      p\        V Uu0 uF  q V,          kK  	  up4      ^8”  d   R# V'       d   V^ ,          R3# RR3# u uppi u upi )u°  ``(index, ambiguous)`` for entries matching *old_text*. A whole-entry
EXACT match (``old_text == entry``) takes absolute priority â€” substring
matches are only considered when no entry equals *old_text*, so a short
entry stays addressable even when its full text is contained inside a
longer sibling entry (remove('test') vs '...tests pass...'). Exact-duplicate
matches are safe (first wins); distinct matches â†’ ``(None, True)``.NF)NT)rd   rj   Úlen)rW   rX   rf   rg   rh   Úmatchess   &&    r   Ú_find_unique_matchrq   `   s„   € ô % WÔ-Ô?Ñ-‘4�1°±�QˆQÑ-€EÑ?Ø×<Ð<Ô)¨'Ó<€GÜ
¡Ó(¡˜1�A�JˆJ¡Ñ(Ó)¨AÔ-ØÐß!ˆG�A�J¨eÐ3Ð3 t¨eÐ3Ð3ùó	 @ùâ(s   �
A;žA;ÁBc          
      ó€   € V ^8„  d   QhR\         \        ,          R\        R\        R\        \        \        3,          /# )r   rW   rX   Úverbr   )rY   r   r(   r   )r   s   "r   r   r   n   s=   € ÷ Pñ PœT¤#�Yð P´#ð P¼Sð PÌdÔSVÔX[ÐS[Ínñ Pr   c           	     ó^  a	a
€ R R lo	S	! V4      o
\        S
'       d   V	V
3R l\        V 4       4       M. R R7      pVR,           UUu. uF  w  rVVR8¼  g   K  W,          NK  	  pppRV9   d   R	MR
p\        RV RV RV R2V'       d   RMR,           R3/ V'       d   RV/M/ BVB # u uppi )zçZero-match error that names the fix: the entries sharing the most words with
*old_text* (a paraphrased or stale old_text usually still shares most of them), and a
pointer when old_text spans several entries joined by the delimiter.c                ó0   € V ^8„  d   QhR\         R\        /# rJ   )r   r-   )r   s   "r   r   Ú%_no_match_error.<locals>.__annotate__r   s   € ÷ 5ñ 5”Sð 5œSñ 5r   c                 ó^   € \        \        P                  ! R V P                  4       4      4      # )z\w+)r-   ÚreÚfindallÚlowerrS   s   &r   Ú_wordsÚ_no_match_error.<locals>._wordsr   s   € Ü”2—:’:˜f d§j¡j£lÓ3Ó4Ð4r   c              3   ó|   <"  € T F1  w  r\        SS! V4      ,          4      \        S4      ,          V3x € K3  	  R # 5ir]   )ro   )r_   rf   rg   r{   Úwordss   &  €€r   ra   Ú"_no_match_error.<locals>.<genexpr>u   s1   øé € Ð]ÑJ\Á$À!”c˜%¡&¨£)Õ+Ó,¬s°5«zÕ9¸1Õ=ÓJ\ùs   ƒ9<c                 ó(   € V ^ ,          ) V ^,          3# )é    r5   )Úps   &r   Ú<lambda>Ú!_no_match_error.<locals>.<lambda>v   s   €  A a¥D 5¨!¨A­$¡-r   )Úkey:Né   Ng333333Ó?ô   Â§uR    old_text must come from ONE entry ('Â§' separates entries); use one op per entry.Ú zNo entry matched 'z'.z Retry the z6 with old_text copied verbatim from the intended entryz (closest_entries below).Ú.Úno_matchÚclosest_entries)Úsortedrd   r/   )rW   rX   rs   r.   ÚscoredÚscorerf   ÚclosestÚhintr{   r~   s   &&&,     @@r   Ú_no_match_errorr‘   n   sÐ   ù€ õ5á�8Ó€EÜ×afÕ]Ì)ÐT[ÔJ\Ô]ÐlnÙ/ô1€Fà*0°®*ÔE©*™h˜e¸À¹Œzˆw�zˆz©*€GÑEà�xÔñ aØ%'ð 	äÐ& x j°°4°&¸ÀDÀ6ð J,ð -ßOVÑ0KÐ\_õaØblñPç5<Ð'¨Ñ1À"ðPàINñPð Pùó Fs   Á	B)ÁB)c                ó<   € V ^8„  d   QhR\         R\         R\        /# )r   Ú	new_totalÚlimitr   )rZ   r   )r   s   "r   r   r      s&   € ÷ kñ kœ3ð k¤sð k¬sñ kr   c                 ó,   € R V R RVR RW,
          R R2# )zwould put memory at Ú,Ú/z chars: free at least ú charsr5   )r“   r”   s   &&r   Ú_over_limitr™      s*   € Ø! )¨A ¨a°°a¨yÐ8NÈyÕO`ÐabÐNcÐciÐjÐjr   zeTo drop text inside an entry, patch a longer span that contains it; 'remove' deletes the whole entry.c                ó<   € V ^8„  d   QhR\         R\        R\         /# )r   rX   Úcountr   ©r   rZ   )r   s   "r   r   r   ‡   s&   € ÷ Gñ G¤Sð G´ð G¼ñ Gr   c                 ó   € R V  RV R2# )rG   z
' appears zm times in the matched entry, and patch edits one span. Include more surrounding text so old_text occurs once.r5   )rX   r›   s   &&r   Ú_repeated_span_messagerž   ‡   s!   € Ø�ˆz˜ E 7ð +Eð Fð Gr   c                ó<   € V ^8„  d   QhR\         R\         R\        /# )r   rK   Úspanr   rœ   )r   s   "r   r   r   Œ   s&   € ÷ Sñ SœCð S¤sð S¬sñ Sr   c           	     ó„   a a€ \        VV 3R l\        \        S 4      \        S4      ,
          ^,           4       4       4      # )zXOccurrences of *span* in *text*, overlapping ones included: '00' occurs twice in '1000'.c              3   óH   <"  € T F  pSP                  SV4      x € K  	  R # 5ir]   )Ú
startswith)r_   rf   r    rK   s   & €€r   ra   Ú$_span_occurrences.<locals>.<genexpr>Ž   s!   øé € ÐRÑ1Q¨Aˆt�‰˜t Q×'Ð'Ó1Qùs   ƒ")ÚsumÚrangero   )rK   r    s   ffr   Ú_span_occurrencesr§   Œ   s+   ù€ äÕR´´s¸4³yÄ3ÀtÃ9Õ7LÈqÕ7PÔ1QÓRÓRÐRr   c                óŠ   € V ^8„  d   QhR\         R\         R\         R\        \        \         ,          \         \         3,          /# )r   ÚentryrX   Únew_textr   )r   rl   r
   )r   s   "r   r   r   ‘   s:   € ÷ ñ œð ¤sð ´cð ¼eÄHÌSÅMÔSVÔX[ÐD[Õ>\ñ r   c                óÄ   € \        W4      ;p^8”  d   R\        W4      R3# V P                  W^4      pW@8X  d   RRV RV R2R3# \        V4      ;p'       d   RVR3# VRR	3# )
a  ``(patched entry, "", "none")``, or ``(None, error, failure class)`` when the span occurs more
than once in the entry, the edit changes nothing, or the patched entry fails the threat scan.
Single and batch patches both go through here, so they share one rule.NÚ	ambiguouszPatch is a no-op: 'z' -> 'z' leaves the entry unchanged.Úinvalid_argsÚscan_blockedrˆ   Únone)r§   rž   rO   r   )r©   rX   rª   r›   ÚpatchedÚ
scan_errors   &&&   r   Ú_patch_entryr²   ‘   sˆ   € ô # 5Ó3Ð3ˆ°qÔ8ØÔ+¨HÓ<¸kÐIÐIØ�m‰m˜H°Ó2€GØÔØÐ*¨8¨*°F¸8¸*ÐDaÐbÐdrÐrÐrÜ)¨'Ó2Ð2€zÖ2Ø�Z Ð/Ð/Ø�B˜ÐÐr   c                óh   € V ^8„  d   QhR\         \        ,          R\        R\        \        ,          /# )r   rW   Úmatched_entryr   )rY   r   r
   rZ   )r   s   "r   r   r   Ÿ   s.   € ÷ Nñ Nœ4¤�9ð N´Sð N¼XÄc½]ñ Nr   c                ó4   € W9   d   V P                  V4      # R# )z[Index of the exact entry a staged write was reviewed against; None once it is gone (stale).N)Úindex)rW   r´   s   &&r   Ú_pinned_indexr·   Ÿ   s   € à+8Ô+Cˆ7�=‰=˜Ó'ÐMÈÐMr   c                ó0   € V ^8„  d   QhR\         R\         /# )r   r©   r   r2   )r   s   "r   r   r   ¤   s   € ÷ 3ñ 3¤ð 3¬ñ 3r   c                 ó   € R V  R2# )zCEntry changed since it was staged, so this write was not applied: 'zˆ' is no longer in memory as reviewed. Recreate the change against the current entry or reject it; the pending record has been preserved.r5   )r©   s   &r   Ú_stale_entry_messagerº   ¤   s   € ØQÐRWÐQXð Y1ð 2ð 3r   c                   ó0  a € ] tR t^¯t o Rt^tRPRRRR/V 3R lR llltV 3R lR ltV 3R	 lR
 ltV 3R lR lt	R t
]]V 3R lR l4       4       t]V 3R lR l4       tV 3R lR ltV 3R lR ltV 3R lR ltV 3R lR ltV 3R lR ltV 3R lR ltV 3R lR ltRQV 3R! lR" lltR#R$/V 3R% lR& lltV 3R' lR( ltRQV 3R) lR* lltRQV 3R+ lR, lltRQV 3R- lR. lltRQV 3R/ lR0 lltRQV 3R1 lR2 lltV 3R3 lR4 ltRQV 3R5 lR6 llt]RQV 3R7 lR8 ll4       t V 3R9 lR: lt!V 3R; lR< lt"V 3R= lR> lt#V 3R? lR@ lt$RQV 3RA lRB llt%V 3RC lRD lt&]V 3RE lRF l4       t']V 3RG lRH l4       t(]V 3RI lRJ l4       t)]V 3RK lRL l4       t*V 3RM lRN lt+ROt,V t-R # )RÚMemoryStorezÙBounded curated memory with file persistence; one instance per AIAgent.
``_system_prompt_snapshot`` is frozen at load time (prefix-cache stable);
``memory_entries`` / ``user_entries`` are live state persisted to disk.Úmemory_enabledTÚuser_profile_enabledc                ó2   <€ V ^8„  d   QhRS[ RS[ RS[RS[/# )r   Úmemory_char_limitÚuser_char_limitr½   r¾   )rZ   rm   )r   Ú__classdict__s   "€r   r   ÚMemoryStore.__annotate__º   s+   ø€ ÷ )ñ )©#ð )Ásð )Ù!%ð)ÙDHñ)r   c               ó~   € . V n         . V n        WuV n        V n        W4uV n        V n        R RRR/V n        ^ V n        R# )r   rˆ   r   N)Úmemory_entriesÚuser_entriesrÀ   rÁ   r½   r¾   Ú_system_prompt_snapshotÚ_consolidation_failures)ÚselfrÀ   rÁ   r½   r¾   s   &&&$$r   Ú__init__ÚMemoryStore.__init__º   sK   € à)+ˆÔØ')ˆÔØ7HÐ4ˆÔ Ô 4Ø9GÐ6ˆÔ˜TÔ6Ø8@À"ÀfÈbÐ7QˆÔ$Ø'(ˆÖ$r   c                ó&   <€ V ^8„  d   QhRS[ RS[/# ©r   Útargetr   )r   rm   )r   rÂ   s   "€r   r   rÃ   Å   s   ø€ ÷ Vñ V¡Sð V©Tñ Vr   c                ó@   € VR 8X  d   V P                   # V P                  # ©r   )r¾   r½   ©rÉ   rÎ   s   &&r   Útarget_enabledÚMemoryStore.target_enabledÅ   s    € Ø,2°fÔ,<ˆt×(Ñ(ÐUÀ$×BUÑBUÐUr   c                ó   <€ V ^8„  d   QhRR/# )r   r   Nr5   )r   rÂ   s   "€r   r   rÃ   È   s   ø€ ÷ )ñ )¨dñ )r   c                ó   € ^ V n         R# )zCall at turn start.N)rÈ   )rÉ   s   &r   Úreset_consolidation_failuresÚ(MemoryStore.reset_consolidation_failuresÈ   s
   € à'(ˆÖ$r   c                óR   <€ V ^8„  d   QhRS[ S[S[3,          RS[ S[S[3,          /# )r   Úresponser   )r(   r   r   )r   rÂ   s   "€r   r   rÃ   Ì   s+   ø€ ÷ 7ñ 7©t±C¹°H­~ð 7Á$ÁsÉCÀxÅ.ñ 7r   c                óÄ   € V ;P                   ^,          un         V P                   V P                  8:  d   V# \        P                  R4       RRRRRRV P                    R2/# )	u  Count a consolidation failure: under the per-turn cap return ``response``
(it says how to retry); past it a TERMINAL result so the model stops looping.

Once the cap is exceeded, drop the retry instruction and return a TERMINAL result so the model stops
looping memory calls and proceeds to answer the user â€” a failed memory side effect must never block
the turn's reply (#42405).
Ú	retry_capr*   FÚdoneTr+   zMemory consolidation failed u     times this turn. Stop retrying memory calls â€” leave memory unchanged for now and continue with your reply to the user. The fact can be saved in a later turn.)rÈ   Ú$_MAX_CONSOLIDATION_FAILURES_PER_TURNr,   r-   )rÉ   rÙ   s   &&r   Ú_consolidation_failureÚ"MemoryStore._consolidation_failureÌ   sj   € ð 	×$Ò$¨Õ)Õ$Ø×'Ñ'¨4×+TÑ+TÔTØˆOÜ×Ñ˜+Ô&Ø˜5 &¨$°Ø*¨4×+GÑ+GÐ*Hð I5ð 5ð7ð 	7r   c                ó  a	€ ^ RI Ho	 V	3R lpR Fð  pV P                  V4      p^ RIHp V! VP
                  4       \        \        P                  V P                  V4      4      4      pV P                  W%4       V P                  V4      ;q`P                  V4      ;p8”  d"   \        P                  RVP                  Wg4       T P!                  Y% Uu. uF  q�! WƒP                  4      NK  	  up4      V P"                  V&   Kò  	  R# u upi )u  Load MEMORY.md / USER.md and capture the frozen system-prompt snapshot.
Threat hits are replaced by a ``[BLOCKED: â€¦]`` placeholder in the SNAPSHOT only;
live lists keep the raw text so the user can see and remove poisoned entries
(dropping them silently would hide the attack).)Úscan_for_threatsc                 ó  <€ V '       d"   V P                  R 4      '       g   S! V RR7      MRpV'       g   V # \        P                  RVRP                  V4      4       RV RRP                  V4       R\	        V4       R	2# )
z	[BLOCKED:r   r   Nz-Memory entry from %s blocked at load time: %sz, z
[BLOCKED: z$ entry contained threat pattern(s): z@. Removed from system prompt; use memory(action=remove, target='z') to delete the original.])r£   ÚloggerÚwarningrN   r6   )r©   r1   Úfindingsrá   s   && €r   Ú	_sanitizeÚ-MemoryStore.load_from_disk.<locals>._sanitizeä   s‰   ø€ çBGÐPU×P`ÑP`Ðal×PmÒPmÑ'¨°XÕ>ÐswˆHßØ�Ü�N‰NÐJÈHÐVZ×V_ÑV_Ð`hÓViÔjØ   
Ð*NÈtÏyÉyÐYaÓObÐNcð dUÜUbÐckÓUlÐTmð n/ð0ð 1r   ©Úmkdir_under_hermes_homez„%s exceeds its char limit on load: %d/%d chars. Entries stay loaded; further additions are blocked until it is back under the limit.N)r   r   )Útools.threat_patternsrá   Ú	_path_forÚhermes_constantsré   ÚparentrY   r(   ÚfromkeysÚ
_read_fileÚ_set_entriesÚ_char_countÚ_char_limitrã   rä   r?   Ú_render_blockrÇ   )
rÉ   ræ   rÎ   r8   ré   rW   r›   r”   rg   rá   s
   &        @r   Úload_from_diskÚMemoryStore.load_from_diskÝ   sé   ø€ õ
 	;õ	1ó )ˆFØ—>‘> &Ó)ˆDÝ@á# D§K¡KÔ0äœ4Ÿ=™=¨¯©¸Ó)>Ó?Ó@ˆGØ×Ñ˜fÔ.ð ×)Ñ)¨&Ó1Ð1�×?OÑ?OÐPVÓ?WÐ6W°eÔXÜ—‘ð  aà#Ÿy™y¨%ô8ð 48×3EÑ3EÀfÐpwÓNxÑpwÐklÈyÐYZ×\eÑ\eÖOfÑpwÑNxÓ3yˆD×(Ñ(¨Ó0ó )ùò Oys   ÃDc                ó    <€ V ^8„  d   QhRS[ /# )r   r8   r   )r   rÂ   s   "€r   r   rÃ     s   ø€ ÷ '!ñ '!™ñ '!r   c              #  ó  aaa	"  € ^ RI Hp VP                  VP                  uoo	V P	                  V P
                  R,           4      p^ RIHp V! VP                  4       Sf   S	f   Rx € R# \        P                  \        P                  ,          p\        \        R4      '       d   V\        P                  ,          p\        P                  ! W$R4      p \        \        R4      '       d   \        P                  ! VR4       \        P                   ! VRR	R
7      oS;_uu_ 4        R TTT	3R llpT! R4        Rx € \'        \(        4      ;_uu_ 4        T! R4       RRR4       RRR4       R#   \"         d    \        P$                  ! T4       h i ; i  + '       g   i     L@; i  \'        \(        4      ;_uu_ 4        T! R4       RRR4       i   + '       g   i     i ; i; i  + '       g   i     R# ; i5i)zcExclusive lock on a separate .lock file so the memory file itself can
still be atomically replaced.©Úmemory_toolz.lockrè   NÚ
O_NOFOLLOWi€  Úfchmodzr+úutf-8©Úencodingc                ó$   € V ^8„  d   QhR\         /# )r   Úunlock)rm   )r   s   "r   r   Ú,MemoryStore._file_lock.<locals>.__annotate__  s   € ÷ bñ bœtñ br   c                 ó  <€ S'       d3   SP                  SV '       d   SP                  MSP                  4       R# SP                  ^ 4       SP	                  SP                  4       V '       d   SP                  MSP                  ^4       R# )r�   N)ÚflockÚLOCK_UNÚLOCK_EXÚseekÚlockingÚfilenoÚLK_UNLCKÚLK_LOCK)r   ÚfcntlÚfdÚmsvcrts   &€€€r   Ú_flockÚ&MemoryStore._file_lock.<locals>._flock  sN   ø€ ßØ—K‘K ·V E§M¢MÀÇÁÖOà—G‘G˜A”JØ—N‘N 2§9¡9£;Ç6°·²ÈvÏ~É~Ð_`Öar   FT)Útoolsrù   r  r  Úwith_suffixÚsuffixrì   ré   rí   ÚosÚO_RDWRÚO_CREATÚhasattrrú   Úopenrû   ÚfdopenÚ	ExceptionÚcloser   ÚOSError)
r8   Ú_mtÚ	lock_pathré   ÚflagsÚraw_fdr  r  r  r  s
   &      @@@r   Ú
_file_lockÚMemoryStore._file_lockÿ   s\  úé € õ
 	-ØŸ	™	 3§:¡:ˆˆˆvØ×$Ñ$ T§[¡[°7Õ%:Ó;ˆ	Ý<á 	× 0Ñ 0Ô1ØŠ=˜Vš^ÛÙÜ—	‘	œBŸJ™JÕ&ˆÜ”2�|×$Ò$Ø”R—]‘]Õ"ˆEÜ—’˜¨5Ó1ˆð
	ô
 ”r˜8×$Ò$Ü—	’	˜& %Ô(Ü—’˜6 4°'Ô:ˆB÷ ŠR÷bò bñ �5ŒMð!Ûäœg×&Õ&Ù˜4”L÷ '÷ ‰Røô ô 	Ü�HŠH�VÔØð	ú÷ '×&û”Xœg×&Õ&Ù˜4”L÷ '×&×&Ð&ý÷ �RˆRüs   …CG?ÃAE2 Ä
G?Ä'G+Ä<F+Å G+Å	F	Å G+Å(
G?Å2#FÆG?ÆF(Æ#G+Æ+G(Ç	GÇ	G(ÇG%Ç G(Ç(G+Ç+G<	Ç6	G?c                ó&   <€ V ^8„  d   QhRS[ RS[/# rÍ   )r   r   )r   rÂ   s   "€r   r   rÃ   +  s   ø€ ÷ _ñ _™#ð _¡$ñ _r   c                óZ   € ^ RI Hp VP                  4       V R8X  d	   R,          # R,          # )r�   rø   r   r4   z	MEMORY.md)r  rù   Úget_memory_dir)rÎ   rù   s   & r   rë   ÚMemoryStore._path_for*  s)   € å%Ø×)Ñ)Ó+¸FÀfÔ<L¨yÕ^Ð^ÐR]Õ^Ð^r   c                ó6   <€ V ^8„  d   QhRS[ RS[S[ ,          /# rÍ   ©r   rY   )r   rÂ   s   "€r   r   rÃ   /  s#   ø€ ÷ Nñ N¡3ð N©4±­9ñ Nr   c                ó@   € VR 8X  d   V P                   # V P                  # rÐ   )rÆ   rÅ   rÑ   s   &&r   Ú_entries_forÚMemoryStore._entries_for/  s    € Ø$*¨fÔ$4ˆt× Ñ ÐM¸$×:MÑ:MÐMr   c                ó6   <€ V ^8„  d   QhRS[ RS[S[ ,          /# )r   rÎ   rW   r'  )r   rÂ   s   "€r   r   rÃ   2  s#   ø€ ÷ Yñ Y¡3ð Y±±cµñ Yr   c                ó0   € \        YR 8X  d   RMRV4       R# )r   rÆ   rÅ   N)Úsetattr)rÉ   rÎ   rW   s   &&&r   rð   ÚMemoryStore._set_entries2  s   € Ü�°&Ô(8‘nÐ>NÐPWÖXr   c                ó&   <€ V ^8„  d   QhRS[ RS[/# rÍ   rœ   )r   rÂ   s   "€r   r   rÃ   5  s   ø€ ÷ Dñ D¡#ð D©#ñ Dr   c                ó\   € \        \        P                  V P                  V4      4      4      # r]   )ro   ÚENTRY_DELIMITERrN   r)  rÑ   s   &&r   rñ   ÚMemoryStore._char_count5  s#   € Ü”?×'Ñ'¨×(9Ñ(9¸&Ó(AÓBÓCÐCr   c                ó&   <€ V ^8„  d   QhRS[ RS[/# rÍ   rœ   )r   rÂ   s   "€r   r   rÃ   8  s   ø€ ÷ Tñ T¡#ð T©#ñ Tr   c                ó@   € VR 8X  d   V P                   # V P                  # rÐ   )rÁ   rÀ   rÑ   s   &&r   rò   ÚMemoryStore._char_limit8  s    € Ø'-°Ô'7ˆt×#Ñ#ÐS¸T×=SÑ=SÐSr   c                ó&   <€ V ^8„  d   QhRS[ RS[ /# rÍ   r2   )r   rÂ   s   "€r   r   rÃ   ;  s   ø€ ÷ Lñ L™Sð L¡Sñ Lr   c                óP   € V P                  V4      R  RV P                  V4      R  2# )r–   r—   )rñ   rò   rÑ   s   &&r   Ú_usageÚMemoryStore._usage;  s/   € Ø×"Ñ" 6Ó*¨1Ð-¨Q¨t×/?Ñ/?ÀÓ/GÈÐ.JÐKÐKr   c                ó,   <€ V ^8„  d   QhRS[ RS[RS[ /# )r   rÎ   Úcurrentr   rœ   )r   rÂ   s   "€r   r   rÃ   >  s'   ø€ ÷ pñ p¡ð p©sð p±sñ pr   c                ó�   € V P                  V4      pV^ 8”  d#   \        ^d\        W#,          ^d,          4      4      M^  RVR RVR R2# )r�   u   % â€” r–   r—   r˜   )rò   ÚminrZ   )rÉ   rÎ   r;  r”   s   &&& r   Ú
_usage_pctÚMemoryStore._usage_pct>  sS   € Ø× Ñ  Ó(ˆØ<AÀA¼I”#�cœ3 ¥°3Õ6Ó7Ô8È1ÐMÈVÐT[Ð\]ÐS^Ð^_Ð`eÐfgÐ_hÐhnÐoÐor   c                óB   <€ V ^8„  d   QhRS[ RS[ RS[S[ S[3,          /# )r   rÎ   r%   r   r'   )r   rÂ   s   "€r   r   rÃ   B  s/   ø€ ÷ rñ r©Cð r¹#ð rÁ$ÁsÉCÀxÅ.ñ rr   c           
     óz   € V P                  \        VRV P                  V4      V P                  V4      R7      4      # )zYOver-budget consolidation failure carrying the live entries so the model can consolidate.Úover_budget)Úcurrent_entriesÚusage)rÞ   r/   r)  r8  )rÉ   rÎ   r%   s   &&&r   Ú_failure_with_entriesÚ!MemoryStore._failure_with_entriesB  s=   € à×*Ñ*Ü�7˜M¸4×;LÑ;LÈVÓ;TÐ\`×\gÑ\gÐhnÓ\oÔpórð 	rr   Nc                ón   <€ V ^8„  d   QhRS[ RS[ RS[ RS[S[S[ ,          ,          RS[S[ S[3,          /# )r   rÎ   r%   r&   r‹   r   )r   r
   rY   r(   r   )r   rÂ   s   "€r   r   rÃ   G  sK   ø€ ÷ 	Yñ 	Y¡Sð 	Y±3ð 	YÁsð 	YÙ(0±±cµÕ(;ð	YÙGKÉCÑQTÈHÅ~ñ	Yr   c           	     óŽ   € T P                  \        VR,           V3RV P                  V4      /V'       d   RV/B 4      # / B 4      # )a  Batch-abort failure WITHOUT ``current_entries``: the store did not change and the
caller already holds the inventory, so echoing it made each consolidation retry
grow the context it was invoked to shrink (#97316). A zero-match op carries only
its few ``closest_entries``.z6 No operations were applied (batch is all-or-nothing).rD  r‹   )rÞ   r/   r8  )rÉ   rÎ   r%   r&   r‹   s   &&&&&r   Ú_batch_failureÚMemoryStore._batch_failureG  si   € ð ×*Ñ*Ü�7ÐUÕUÐWdñ XØŸ™ VÓ,ðXç>MÐ(¨/Ð:ñXóYð 	Yð TVñXóYð 	Yr   Ú
skip_driftFc                óB   <€ V ^8„  d   QhRS[ RS[RS[S[ S[3,          /# )r   rÎ   rK  r   )r   rm   r(   r   )r   rÂ   s   "€r   r   rÃ   R  s2   ø€ ÷ Mñ M™cð M¹$ð MÉ4ÑPSÑUXÐPXÍ>ñ Mr   c               ój  € V P                  V4      pV P                  V4      ;_uu_ 4        V P                  V4      w  rVV'       g   \        V4      uuRRR4       # V'       d   RMV P	                  W4      pV P                  V\        \        P                  V P                  V4      4      4      4       V'       d   \        WG4      uuRRR4       # V! V P                  V4      V P                  V4      4      p\        V\        4      '       d   VuuRRR4       # T P                  W^ ,          4       ^ RIHp	 V	! VP                   4       V P#                  WH^ ,          4       \%        V4      ^8”  d
   V^,          M/ p
V P&                  ! W^,          3/ V
B uuRRR4       #   + '       g   i     R# ; i)u)  Lock, re-read from disk, run ``mutate(entries, limit)`` -> ``(new_entries, message)``
or an error dict, then persist and return the success response. The reload aborts
on an existing-but-unreadable file (even append-only ``add`` rewrites the whole
file) and, unless *skip_drift*, on external drift (flushing would discard
un-roundtrippable content). Drift check and parse use the SAME raw snapshot â€”
a failed second read used to count as "no drift". The closure may return a
third value, a dict merged into the success payload (``_error``'s ``**extra``
convention) â€” e.g. the full text a replace overwrote (#117952). ANY dict the closure
returns is passed through verbatim and nothing is persisted: error dicts, or the
success payload of a read-only closure (``resolve_entry``, ``resolve_batch_entries``).Nrè   )rë   r   Ú_read_raw_checkedrF   Ú_detect_external_driftrð   rY   r(   rî   Ú_parse_entriesr@   r)  rò   Ú
isinstancerì   ré   rí   Ú_write_filero   Ú_success_response)rÉ   rÎ   ÚmutaterK  r8   ÚrawÚread_okÚbakÚresultré   Úextra_fieldss   &&&$       r   Ú_mutateÚMemoryStore._mutateR  sD  € ð �~‰~˜fÓ%ˆØ�_‰_˜T×"Õ"Ø×1Ñ1°$Ó7‰LˆCßÜ)¨$Ó/÷ #Ò"÷ %‘$¨$×*EÑ*EÀfÓ*RˆCØ×Ñ˜f¤d¬4¯=©=¸×9LÑ9LÈSÓ9QÓ+RÓ&SÔTßÜ# DÓ.÷ #Ò"ñ ˜D×-Ñ-¨fÓ5°t×7GÑ7GÈÓ7OÓPˆFÜ˜&¤$×'Ò'Ø÷ #Ò"ð ×Ñ˜f¨Q¥iÔ0Ý@á# D§K¡KÔ0Ø×Ñ˜T¨!¥9Ô-Ü(+¨F«°a¬˜6 !ž9¸RˆLØ×)Ò)¨&¸µ)ÑL¸|ÑL÷# #×"×"Ó"ús%   «&F!ÁF!Á$A"F!Ã>F!ÄA<F!Æ!F2	c                óB   <€ V ^8„  d   QhRS[ RS[ RS[S[ S[3,          /# )r   rÎ   r   r   r'   )r   rÂ   s   "€r   r   rÃ   q  s*   ø€ ÷ ;ñ ;™#ð ;©ð ;±±S¹#°Xµñ ;r   c                óÆ   a aa€ SP                  4       oS'       g   \        RR4      # \        S4      ;p'       d   \        VR4      # VV V3R lpS P                  SVRR7      # )zDAppend a new entry. Returns error if it would exceed the char limit.zContent cannot be empty.Úmissing_contentr®   c                 ó„  <€ SV 9   d   SP                  SR 4      # \        \        P                  V S.,           4      4      V8”  dq   \        \        P                  V S.,           4      4      pSP	                  SRSP                  S4      R RVR R\        S4       RW!,
          R RW!,
          R R24      # V S.,           R3# )	z*Entry already exists (no duplicate added).z
Memory at r–   r—   z chars; adding this entry (z" chars) would exceed the limit by zƒ chars. Retry as ONE 'operations' batch that removes or shortens (patch) stale entries from current_entries below to free at least uM    chars AND adds this entry â€” the limit is checked only on the batch result.zEntry added.)rS  ro   r1  rN   rE  rñ   )rW   r”   r“   r   rÉ   rÎ   s   && €€€r   Ú_addÚMemoryStore.add.<locals>._addy  sÝ   ø€ Ø˜'Ô!Ø×-Ñ-¨fÐ6bÓcÐcÜ”?×'Ñ'¨°7°)Õ(;Ó<Ó=ÀÔEÜ¤× 4Ñ 4°WÀ¸yÕ5HÓ IÓJ�	Ø×1Ñ1°&Ø  ×!1Ñ!1°&Ó!9¸!Ð <¸A¸eÀA¸YÐFaÔbeÐfmÓbnÐaoð p1Ø1:Õ1BÀ1Ð0Eð Fmà Õ(¨Ð+Ð+xðzó|ð |ð
 ˜g˜YÕ&¨Ð6Ð6r   T©rK  )Ústripr/   r   rZ  )rÉ   rÎ   r   r±   r`  s   fff  r   ÚaddÚMemoryStore.addq  sY   ú€ à—-‘-“/ˆßÜÐ4Ð6GÓHÐHÜ-¨gÓ6Ð6ˆ:Ö6Ü˜* nÓ5Ð5÷
	7ð �|‰|˜F D°Tˆ|Ó:Ð:r   c                ó^   <€ V ^8„  d   QhRS[ RS[ RS[ RS[S[ ,          RS[S[ S[3,          /# ©r   rÎ   rX   Únew_contentr´   r   ©r   r
   r(   r   )r   rÂ   s   "€r   r   rÃ   ˆ  sE   ø€ ÷ Pñ P™cð P©Sð P¹sð PÙ'©�}ðPÙ8<¹SÁ#¸X½ñPr   c                ó  € VP                  4       pVP                  4       '       g   \        RR4      # V'       g   \        RR4      # \        V4      ;p'       d   \        VR4      # V P                  WP                  4       W44      # )u½   Find the entry containing old_text (whole-entry exact match first) and
replace the WHOLE entry with new_content â€” old_text only locates the entry;
the matched span is not spliced into it.úold_text cannot be empty.Úmissing_old_textz<new_content cannot be empty. Use 'remove' to delete entries.r^  r®   )rc  r/   r   Ú_edit)rÉ   rÎ   rX   rh  r´   r±   s   &&&&& r   rO   ÚMemoryStore.replaceˆ  su   € ð
 "×'Ñ'Ó)ˆØ�~‰~×ÒÜÐ5Ð7IÓJÐJßÜÐXÐZkÓlÐlÜ-¨kÓ:Ð:ˆ:Ö:Ü˜* nÓ5Ð5Ø�z‰z˜&§.¡.Ó"2°KÓOÐOr   c                ó^   <€ V ^8„  d   QhRS[ RS[ RS[ RS[S[ ,          RS[S[ S[3,          /# ©r   rÎ   rX   rª   r´   r   ri  )r   rÂ   s   "€r   r   rÃ   –  sE   ø€ ÷ Kñ K™Cð K©3ð K¹#ð KÙ%¡c�]ðKÙ6:¹3Á¸8µnñKr   c                óþ   € T;'       g    RP                  4       '       g   \        RR4      # Ve    \        V4      P                  4       '       g   \        R\         2R4      # V P	                  W\        V4      V4      # )a;  Find the entry containing *old_text* and replace that one span with *new_text*;
the rest of the entry is preserved verbatim. This is the partial-edit shape
``replace`` deliberately is not (replace overwrites the WHOLE entry). A span that
occurs more than once in the entry is rejected rather than edited everywhere.rˆ   rk  rl  znew_text cannot be empty. r^  )rc  r/   r   ÚPATCH_DROP_HINTÚ_patch)rÉ   rÎ   rX   rª   r´   s   &&&&&r   ÚpatchÚMemoryStore.patch–  sn   € ð —�˜B×%Ñ%×'Ò'ÜÐ5Ð7IÓJÐJØÒ¤3 x£=×#6Ñ#6×#8Ò#8ÜÐ6´Ð6GÐHÐJ[Ó\Ð\à�{‰{˜6¬S°«]¸MÓJÐJr   c                ó^   <€ V ^8„  d   QhRS[ RS[ RS[ RS[S[ ,          RS[S[ S[3,          /# rp  ri  )r   rÂ   s   "€r   r   rÃ   £  s>   ø€ ÷ ,ñ ,™Sð ,©Cð ,¹3ð ,Ù&¡s�mð,Ù7;¹CÁ¸Hµ~ñ,r   c                óD   a aaaa€ VVVV V3R lpS P                  SV4      # )z:Locked find-and-splice inside the matched entry (#124582).c                 ót  <€ SP                  V SR S	4      p\        V\        4      '       d   V# W,          p\        VSS
4      w  rEpVf   \	        WV4      # V RV V.,           W^,           R ,           p\        \        P                  V4      4      pW�8”  d   SP                  SRVR RVR R24      # VRRVRV/3# )	rt  NzPatch would put memory at r–   r—   uš    chars. Shorten the new text, or 'remove' other stale or less important entries to make room (see current_entries below), then retry â€” all in this turn.zEntry patched.Úpatched_entry_beforeÚpatched_entry_after)	Ú_locaterQ  r(   r²   r/   ro   r1  rN   rE  )rW   r”   ÚidxÚbeforeÚafterr%   r&   r°   r“   r´   rª   rX   rÉ   rÎ   s   &&       €€€€€r   Ú_applyÚ"MemoryStore._patch.<locals>._apply¦  sç   ø€ Ø—,‘,˜w¨°'¸=ÓIˆCÜ˜#œt×$Ò$Ø�
Ø•\ˆFÜ,8¸ÀÈ8Ó,TÑ)ˆE˜MØŠ}Ü˜gÓ5Ð5Ø˜d˜s�m u gÕ-°¸a½¸Ð0AÕAˆGÜœO×0Ñ0°Ó9Ó:ˆIØÔ Ø×1Ñ1°&Ø0°¸1°¸Q¸uÀQ¸ið HTð UóWð Wð Ð,Ø&¨Ð0EÀuð/Nð Nð Nr   ©rZ  )rÉ   rÎ   rX   rª   r´   r  s   fffff r   rs  ÚMemoryStore._patch£  s"   ü€ ÷	Nñ 	Nð" �|‰|˜F FÓ+Ð+r   c          
      óX   <€ V ^8„  d   QhRS[ RS[ RS[S[ ,          RS[S[ S[3,          /# )r   rÎ   rX   r´   r   ri  )r   rÂ   s   "€r   r   rÃ   ¹  s@   ø€ ÷ Iñ I™Sð I©Cð IÁÉÅð IÑY]Ñ^aÑcfÐ^fÕYgñ Ir   c                óˆ   € VP                  4       '       g   \        RR4      # V P                  WP                  4       RV4      # )z/Remove the entry containing old_text substring.rk  rl  N)rc  r/   rm  )rÉ   rÎ   rX   r´   s   &&&&r   ÚremoveÚMemoryStore.remove¹  s8   € à�~‰~×ÒÜÐ5Ð7IÓJÐJØ�z‰z˜&§.¡.Ó"2°D¸-ÓHÐHr   c          	      óR   <€ V ^8„  d   QhRS[ S[,          RS[RS[RS[S[,          /# )r   rW   rX   rs   r´   )rY   r   r
   )r   rÂ   s   "€r   r   rÃ   ¿  s4   ø€ ÷ ñ ™t¡C�yð ±Cð ¹sð ÑS[Ñ\_ÕS`ñ r   c                ó|  € Ve'   \        W4      pVe   V# \        \        V4      R4      # \        W4      w  rVV'       dX   \        RV R2R\	        W4       Uu. uF1  pW,          R,          \        W,          4      ^P8”  d   RMR,           NK3  	  upR7      # Vf   V P                  \        WW1R	7      4      # V# u upi )
a
  Index of the entry *old_text* selects, or the error dict the edit returns. A write
staged for approval carries the FULL entry it was reviewed against (*matched_entry*):
only that exact entry qualifies, so replay never hits a newer entry that still
contains old_text.Ústale_entryzMultiple entries matched 'z'. Be more specific.r¬   :NéP   Nz...rˆ   )rp   )rC  )r·   r/   rº   rq   rj   ro   rÞ   r‘   )rÉ   rW   rX   rs   r´   r|  r¬   rf   s   &&&&&   r   r{  ÚMemoryStore._locate¿  sË   € ð
 Ò$Ü Ó7ˆCØš/�3Ði¬vÔ6JÈ=Ó6YÐ[hÓ/iÐiÜ+¨GÓ>‰ˆßÜÐ6°x°jÐ@TÐUÐWbä,>¸wÔ,Qó#SÙ,Q qð $+¥:¨c¥?¼sÀ7Å:»ÐQSÔ?S±eÐY[×#\Ð#\Ù,Qñ#SôTð Tð Š;Ø×.Ñ.¬¸wÐRVÔ/pÓqÐqØˆ
ùò	#Ss   Á7B9c          
      óH   <€ V ^8„  d   QhRS[ RS[ RS[ RS[S[ S[3,          /# )r   rÎ   rX   rs   r   r'   )r   rÂ   s   "€r   r   rÃ   Ð  s2   ø€ ÷ ?ñ ?¡Cð ?±3ð ?¹cð ?ÁdÉ3ÑPSÈ8Ånñ ?r   c                ó>   a aa€ VV V3R lpS P                  WRR7      # )zš``{"success": True, "matched_entry": <full entry>}`` for the entry *old_text* selects
now, read under the lock, or the error the direct edit would return.c                 óŽ   <€ SP                  V SP                  4       S4      p\        V\        4      '       d   V# R RRW,          /# )r*   Tr´   )r{  rc  rQ  r(   )rW   r”   r|  rX   rÉ   rs   s   && €€€r   Ú_resolveÚ+MemoryStore.resolve_entry.<locals>._resolveÓ  s@   ø€ Ø—,‘,˜w¨¯©Ó(8¸$Ó?ˆCÜ$ S¬$×/Ò/�3Ðe°iÀÀÐX_ÕXdÐ5eÐer   Trb  r�  )rÉ   rÎ   rX   rs   r�  s   f&ff r   Úresolve_entryÚMemoryStore.resolve_entryÐ  s   ú€ ÷	fð �|‰|˜F¸ˆ|Ó>Ð>r   c                ón   <€ V ^8„  d   QhRS[ RS[ RS[S[ ,          RS[S[ ,          RS[S[ S[3,          /# rg  ri  )r   rÂ   s   "€r   r   rÃ   Ø  sB   ø€ ÷ ,ñ ,™Cð ,©3ð ,¹XÁc½]ð ,Ù%¡c�]ð,Ù6:¹3Á¸8µnñ,r   c                óD   a aaaa€ VVVV V3R lpS P                  SV4      # )zWLocked replace (``new_content`` set) or remove (None) of the entry matching *old_text*.c                 óx  <€ SP                  T SS'       d   R MRS4      p\        V\        4      '       d   V# V RV Sf   . MS.,           W^,           R ,           pSf   VRRW,          /3# \        \        P                  V4      4      pWA8”  d    SP                  S	R\        WA4       R24      # VRRW,          /3# )	rO   r…  NzEntry removed.Úremoved_entryzReplacement uÎ   . Shorten the new content, or retry as ONE 'operations' batch with this replace plus removes/shortenings of other stale entries (see current_entries below) â€” the limit is checked only on the batch result.zEntry replaced.Úreplaced_entry)r{  rQ  r(   ro   r1  rN   rE  r™   )
rW   r”   r|  Úreplacedr“   r´   rh  rX   rÉ   rÎ   s
   &&   €€€€€r   r  Ú!MemoryStore._edit.<locals>._applyÛ  sÙ   ø€ Ø—,‘,˜w¨¿{±)ÐPXÐZgÓhˆCÜ˜#œt×$Ò$Ø�
Ø˜t �}¨kÒ.A©ÈÀ}ÕUÐX_ÐfgÕ`gÐ`hÐXiÕiˆHØÒ"ØÐ!1°OÀWÅ\Ð3RÐRÐRÜœO×0Ñ0°Ó:Ó;ˆIØÔ Ø×1Ñ1°&Ø"¤;¨yÓ#@Ð"Að Beð fóhð hð Ð.Ð1AÀ7Å<Ð0PÐPÐPr   r�  )rÉ   rÎ   rX   rh  r´   r  s   fffff r   rm  ÚMemoryStore._editØ  s"   ü€ ÷	Qñ 	Qð �|‰|˜F FÓ+Ð+r   c                ó¢   <€ V ^8„  d   QhRS[ S[,          RS[RS[RS[RS[RS[S[,          RS[S[S[,          S[S[S[S[,          3,          /# )r   ÚworkingÚactr   rX   Úposr´   r   )rY   r   r
   rl   r   )r   rÂ   s   "€r   r   rÃ   ì  sd   ø€ ÷ -7ñ -7¡¡c¥ð -7±ð -7¹sð -7Écð -7ÑX[ð -7Ù'/±¥}ð-7Ù@EÁhÉsÅmÑUXÑZ]Ñ_gÑhkÕ_lÐFlÕ@mñ-7r   c                óò  € VR8X  d+   V'       g
   V R2RRR3# W 9  d   V P                  V4       R# VR9  d
   V R2RR	R3# VP                  4       '       g
   V R
2RRR3# VR8X  d   V'       g
   V R2RRR3# VR8X  d&   VP                  4       '       g   V R\         2RRR3# Ve%   \        W4      pVf   V R\	        V4       2RRR3# MR\        W4      w  rgV'       d   V RV R2RRR3# Vf.   \        WV4      pV RVR,           2VP                  R4      RR3# W,          p	VR8w  d   VR8X  d   V.M. WV^,           % RV	RR3# \        W“V4      w  r«pV
f   V RV 2RVR3# V
.WV^,           % RV	RV
3# )uó  Apply one batch op to *working*; return ``(error message, previous content, failure class,
patched entry)`` â€” on a zero-match error the second value is that op's ``closest_entries``
instead, and the fourth is the entry a patch produced (None for every other op).
Previous content is captured before each replace/remove, under the store lock.
It is published only after the entire batch has been validated and persisted.
A staged op's *matched_entry* selects exactly that entry, as in ``_locate``.
rd  z: content is required.Nr^  r¯   rO   rt  z,: unknown action. Use add, patch, or remove.r­   z: old_text is required.rl  u�   : content is required â€” set this operation object's own 'content' to the COMPLETE new entry (or use action='remove' to delete).uk   : content is required â€” set this operation object's own 'content' to the new text for the old_text span. ú: r‰  z: 'z8' matched multiple distinct entries -- be more specific.r¬   r+   r‹   rŠ   )NNr¯   N)rO   r…  rt  )	Úappendrc  rr  r·   rº   rq   r‘   Úgetr²   )rœ  r�  r   rX   rž  r´   r|  r¬   ÚmissÚprevious_contentr°   r%   r&   s   &&&&&&       r   Ú_apply_batch_opÚMemoryStore._apply_batch_opë  s%  € ð �%Œ<ßØ˜Ð4Ð5°tÐ=NÐPTÐTÐTØÔ%Ø—‘˜wÔ'Ø+Ð+ØÐ4Ô4Ø�UÐFÐGÈÈ~Ð_cÐcÐcØ�~‰~×ÒØ�UÐ1Ð2°DÐ:LÈdÐRÐRØ�)Ô§GØ�eð Dð EØGKÐM^Ð`dðeð eà�'Œ> '§-¡-§/¢/Ø�eð 3Ü3BÐ2CðEØGKÐM^Ð`dðeð eàÒ$Ü Ó7ˆCØŠ{Ø˜˜bÔ!5°mÓ!DÐ EÐFÈÈmÐ]aÐaÐað ô 0°ÓB‰NˆCßØ˜%˜s 8 *Ð,dÐeÐgkØ# Tð+ð +àŠ{Ü& w¸#Ó>�Ø˜˜b  g¥ Ð0°$·(±(Ð;LÓ2MÈzÐ[_Ð_Ð_Ø"�<ÐØ�'Œ>Ø03°yÔ0@ G¡9ÀbˆG˜˜a�Ð ØÐ)¨6°4Ð7Ð7Ü*6Ð7GÐSZÓ*[Ñ'ˆ˜-ØŠ?Ø�U˜"˜W˜IÐ&¨¨m¸TÐAÐAØ '˜yˆ�C˜!•GÐØÐ% v¨wÐ6Ð6r   c                óh   <€ V ^8„  d   QhRS[ RS[S[S[ S[3,          ,          RS[S[ S[3,          /# ©r   rÎ   Ú
operationsr   ©r   rY   r(   r   )r   rÂ   s   "€r   r   rÃ     s:   ø€ ÷ <ñ <¡#ð <±4¹¹SÁ#¸X½Õ3Gð <ÉDÑQTÑVYÐQYÍNñ <r   c                ó(   € V P                  WRR7      # )u@  Apply add/replace/remove ops atomically against the FINAL budget, so one call
can free space and add entries. All-or-nothing: any malformed / unmatched op or
an over-limit result writes NOTHING and returns the first failure. Aborts do not
echo ``current_entries`` â€” the store is unchanged and the model already has it.T©Úcommit©Ú_batch©rÉ   rÎ   r©  s   &&&r   Úapply_batchÚMemoryStore.apply_batch  s   € ð
 �{‰{˜6°dˆ{Ó;Ð;r   c                óh   <€ V ^8„  d   QhRS[ RS[S[S[ S[3,          ,          RS[S[ S[3,          /# r¨  rª  )r   rÂ   s   "€r   r   rÃ   "  s<   ø€ ÷ =ñ =©Cð =¹TÁ$ÁsÉCÀxÅ.Õ=Qð =ÑVZÑ[^Ñ`cÐ[cÕVdñ =r   c                ó(   € V P                  WRR7      # )u@  Dry-run ``apply_batch`` under the lock without persisting: the same content scan,
op walk, empty-store and budget checks, so it fails exactly where the direct batch
would; on success ``{"success": True, "matched_entries": [...]}`` â€” per op, the FULL
entry its replace/remove selects now (None for add), in batch order.Fr¬  r®  r°  s   &&&r   Úresolve_batch_entriesÚ!MemoryStore.resolve_batch_entries"  s   € ð
 �{‰{˜6°eˆ{Ó<Ð<r   c          
      ón   <€ V ^8„  d   QhRS[ RS[S[S[ S[3,          ,          RS[RS[S[ S[3,          /# )r   rÎ   r©  r­  r   )r   rY   r(   r   rm   )r   rÂ   s   "€r   r   rÃ   )  sI   ø€ ÷ ?Cñ ?C™Sð ?C©d±4¹¹S¸µ>Õ.Bð ?CÉtð ?CÑX\Ñ]`ÑbeÐ]eÕXfñ ?Cr   c               óê  a aaaa
€ ^ RI Hp V! S SS4      ;p'       d   V# S'       g   \        RR4      # S Uu. uF  qf;'       g    / NK  	  upo
\        S
4       Fo  w  rvVP	                  R4      R9   ;'       d,    VP	                  R4      ;'       d    \        VR,          4      pV'       g   KV  \        RV^,            RV 2R4      u # 	  VVV
V V3R	 lp	S P                  SV	S'       * R
7      # u upi )r�   )Ú_memory_target_errorzoperations list is empty.r­   Úactionr   ú
Operation r   r®   c                 óÐ  <€ \        V 4      p. p/ p\        S4       EF	  w  rVVP                  R 4      pVP                  R4      ;'       g    VP                  R4      ;'       g    RVP                  R4      ;'       g    Rr˜VR8w  d    VP                  4       V	P                  4       r˜SP	                  Y'Y‰RV^,            RT;'       g    R R	2VP                  R
4      4      w  r«rÍV
'       d   SP                  SW¬VR7      u # VP                  V4       Vf   Kþ  WÔV^,           &   EK  	  V '       d;   V'       g3   SP                  S4      P                  pSP                  SRV R2R4      # \        \        P                  V4      4      pWñ8”  d-   SP                  SR\        S4       R\        Wñ4       R2R4      # S'       g   RRRV/# / / / ppp\        \        SV4      ^4       F?  w  pw  rkVf   K  RVRVRV/P                  VP                  R 4      4      pVf   K:  VVV&   KA  	  V'       d   RV/M/ pV'       d   VVR&   VVR&   V'       d   VVR&   VR\        S4       R2V3# )rº  r   rª   rˆ   rX   rt  r»  z (ÚunknownÚ)r´   )r‹   zRefusing to empty uö   : this batch would remove every entry from a previously non-empty store. Keep at least one entry â€” merge overlapping entries into a shorter one instead of removing the last one. To delete the final entry deliberately, use single remove() calls.Úwould_emptyzApplying all z operations z^ more. Add removes or shortening patches of other stale entries to the same batch, then retry.rB  r*   TÚmatched_entriesrO   r…  Úreplaced_entriesÚpatched_entriesÚpatched_entries_afterÚremoved_entrieszApplied z operation(s).)rY   rd   r¢  rc  r¥  rI  r¡  rë   r?   ro   r1  rN   r™   Úzip)rW   r”   rœ  ÚmatchedÚproducedrf   Úopr�  r   rX   Úmsgr¤  r&   r~  Úlabelr“   r˜  Úremovedr°   Ú
result_mapÚreplaced_fieldsr­  r©  ÚopsrÉ   rÎ   s   &&                   €€€€€r   r  Ú"MemoryStore._batch.<locals>._apply6  s’  ø€ Ü˜7“mˆGØˆGØˆHÜ" 3Ÿ‘�Ø—f‘f˜XÓ&�Ø$&§F¡F¨9Ó$5×$QÐ$Q¸¿¹À
Ó9K×$QÐ$QÈrÐSU×SYÑSYÐZdÓSe×SkÐSkÐik˜Ø˜'”>Ø(/¯©«¸¿¹Ó9I˜XØ>B×>RÑ>RØ '°zÀ!ÀaÅ%ÀÈÈ3×K[ÐK[ÐR[ÐJ\Ð\]Ð5^Ø—F‘F˜?Ó+ó?-Ñ;� }÷ Ø×.Ñ.¨v°sÐ[kÐ.ÓlÒlØ—‘Ð/Ô0ØÔ$Ø&+˜Q �U”Oñ (÷ Ÿwð Ÿ™ vÓ.×3Ñ3�Ø×*Ñ*¨6Ø(¨¨ð 0Kð Lð O\ó	]ð ]ô
 œO×0Ñ0°Ó9Ó:ˆIØÔ Ø×*Ñ*¨6Ø#¤C¨
£OÐ#4°LÄÈYÓA^Ð@_ð `jð kà!ó#ð #÷ Ø! 4Ð):¸GÐDÐDð *,¨R°˜w�gˆHÜ-6´s¸3ÀÓ7HÈ!Ö-LÑ)�Ñ)�BØ#Ô/Ø"+¨X°wÀÈÐSZÐ![×!_Ñ!_Ð`b×`fÑ`fÐgoÓ`pÓ!q�JØ!Ô-Ø(8˜
 1›ñ	 .M÷
 AIÐ1°8Ñ<ÈbˆOßØ5<�Ð 1Ñ2Ø;C�Ð 7Ñ8ßØ5<�Ð 1Ñ2Ø˜h¤s¨:£Ð&7°~ÐFÈÐWÐWr   rb  >   rd  rO   )Útools.memory_toolr¹  r/   rd   r¢  r   rZ  )rÉ   rÎ   r©  r­  r¹  Útarget_errorrÈ  rf   r±   r  rÎ  s   fffd      @r   r¯  ÚMemoryStore._batch)  sä   ü€ Ý:Ù/°°f¸jÓIÐIˆ<ÖIØÐßÜÐ5°~ÓFÐFÙ",Ó-¡*˜B�xˆx�RŠx¡*Ñ-ˆä˜s–^‰EˆAØŸ™ Ó)Ð-?Ñ?×}Ð}ÀBÇFÁFÈ9ÓDU×}Ð}ÔZnÐoqÐr{Õo|ÓZ}ˆJß‰zÜ 
¨1¨q­5¨'°°J°<Ð@À.ÓQÒQñ $÷
1	Xñ 1	Xðd �|‰|˜F F¸6´zˆ|ÓBÐBùòs .s   ¸C0ÁC0c                ó6   <€ V ^8„  d   QhRS[ RS[S[ ,          /# rÍ   r   )r   rÂ   s   "€r   r   rÃ   j  s#   ø€ ÷ Dñ D©sð D±xÁµ}ñ Dr   c                óN   € V P                   P                  VR4      ;'       g    R# )u}   Frozen load-time snapshot (NOT live state â€” mid-session writes don't touch
it, preserving the prefix cache); None if empty.rˆ   N)rÇ   r¢  rÑ   s   &&r   Úformat_for_system_promptÚ$MemoryStore.format_for_system_promptj  s%   € ð ×+Ñ+×/Ñ/°¸Ó;×CÐC¸tÐCr   c                óP   <€ V ^8„  d   QhRS[ RS[ R,          RS[S[ S[3,          /# )r   rÎ   r%   Nr   r'   )r   rÂ   s   "€r   r   rÃ   o  s8   ø€ ÷ Vñ V©ð V±c¸Dµjð VÑUYÑZ]Ñ_bÐZbÕUcñ Vr   c                ó¼   € ^ V n         RRRRRVRV P                  WP                  V4      4      R\        V P	                  V4      4      /V'       d   RV/M/ CVCRR	/C# )
u‚  TERMINAL and WITHOUT the entries list: echoing entries invites the model to
"find more to fix" and re-issue the same ops. A successful write resets the
per-turn failure budget. ``**extra`` mirrors ``_error``'s convention â€” e.g. the
full text a replace overwrote (#117952), deliberately visible despite the
no-entries rule: silent data loss is the failure this field exists to prevent.r*   TrÜ   rÎ   rD  Úentry_countr%   Únoteu:   Write saved. This update is complete â€” do not repeat it.)rÈ   r>  rñ   ro   r)  )rÉ   rÎ   r%   r.   s   &&&,r   rS  ÚMemoryStore._success_responseo  s   € ð ()ˆÔ$Ø˜4 ¨¨x¸Ø˜Ÿ™¨×1AÑ1AÀ&Ó1IÓJØœs 4×#4Ñ#4°VÓ#<Ó=ðVçZaÀ9ÈgÑBVÐgiðVð ðVð ÐTñ	Vð 	Vr   c                ó<   <€ V ^8„  d   QhRS[ RS[S[ ,          RS[ /# )r   rÎ   rW   r   r'  )r   rÂ   s   "€r   r   rÃ   ~  s+   ø€ ÷ ]ñ ]¡Cð ]±$±sµ)ð ]Áñ ]r   c           
     óÀ   € V'       g   R# \         P                  V4      RrC\        VR8X  d   RMR,          pV RV RV P                  V\	        V4      4       RV RV 2	# )zHSystem prompt block: header + usage indicator + entries ("" when empty).rˆ   r   r   Ú
z [z]
uŠ   â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�)r1  rN   ÚMEMORY_BLOCK_HEADERSr>  ro   )rÉ   rÎ   rW   r   ÚsepÚtitles   &&&   r   ró   ÚMemoryStore._render_block~  sc   € çÙÜ&×+Ñ+¨GÓ4°j�Ü$¨v¸Ô/?¡VÀXÕNˆØ��b˜˜˜r $§/¡/°&¼#¸g»,Ó"GÐ!HÈÈCÈ5ÐPRÐSZÐR[Ð\Ð\r   c                ó<   <€ V ^8„  d   QhRS[ RS[S[S[3,          /# rB   )r   rl   r   rm   )r   rÂ   s   "€r   r   rÃ   ‡  s$   ø€ ÷ ñ ¡ð ©©s±D¨yÕ)9ñ r   c                óŽ   € V P                  4       '       g   R#  V P                  RR7      R3#   \        \        3 d    Ru # i ; i)zð``(raw, read_ok)``; ``read_ok`` is False ONLY when the file EXISTS but can't be
read. Decoding stays STRICT (``errors="replace"`` would hand callers a lossy view
a save then persists); ``utf-8-sig`` strips a Notepad BOM off the first entry.Tz	utf-8-sigrý   )rˆ   T)rˆ   F)ÚexistsÚ	read_textr  ÚUnicodeDecodeErrorrE   s   &r   rN  ÚMemoryStore._read_raw_checked†  sL   € ð
 �{‰{�}Š}ØˆOð		ð —>‘>¨;�>Ó7¸Ð=Ð=øÜÔ+Ð,ô 	ØÒð	ús   š. ®AÁAc                ó6   <€ V ^8„  d   QhRS[ RS[S[ ,          /# )r   rU  r   r'  )r   rÂ   s   "€r   r   rÃ   ™  s#   ø€ ÷ Qñ Q™Cð Q¡D©¥Iñ Qr   c                óv   € R V P                  \        4       4        Uu. uF  q'       g   K  VNK  	  up# u upi )uR   Stripped, non-empty entries; splits on the FULL delimiter so a bare "Â§" survives.c              3   ó@   "  € T F  qP                  4       x € K  	  R # 5ir]   )rc  )r_   Úxs   & r   ra   Ú-MemoryStore._parse_entries.<locals>.<genexpr>›  s   é € ÐJÑ/I¨!ŸG™GŸI˜IÓ/Iùrc   )rR   r1  )rU  rg   s   & r   rP  ÚMemoryStore._parse_entries˜  s1   € ñ K¨s¯y©y¼Ô/IÔJÓPÑJ�aËa—�ÑJÑPÐPùÒPs   Ÿ	6­6c                ó6   <€ V ^8„  d   QhRS[ RS[S[,          /# rB   ©r   rY   r   )r   rÂ   s   "€r   r   rÃ   ž  s#   ø€ ÷ Rñ R™ð R¡$¡s¥)ñ Rr   c                ó`   € \         P                  \         P                  V 4      ^ ,          4      # )z Entries of a memory file ([] on any error). Read-only callers only; mutation
paths use ``_read_raw_checked`` so they can refuse to overwrite an unreadable file.)r¼   rP  rN  rE   s   &r   rï   ÚMemoryStore._read_file�  s%   € ô ×)Ñ)¬+×*GÑ*GÈÓ*MÈaÕ*PÓQÐQr   c                ó6   <€ V ^8„  d   QhRS[ RS[S[,          /# )r   r8   rW   rð  )r   rÂ   s   "€r   r   rÃ   ¤  s#   ø€ ÷ Kñ K™$ð K©©c­ñ Kr   c                ó’   €  \        V \        P                  V4      RR7       R#   \         d   p\	        RT  RT 24      hRp?ii ; i)z·Atomic temp-file + rename: readers never see a truncated file. Callers
hold ``_file_lock`` (via ``_mutate``): a bare write from an earlier snapshot
drops concurrent entries (#119668).z.mem_)Ú
tmp_prefixzFailed to write memory file r   N)r   r1  rN   r  ÚRuntimeError)r8   rW   rg   s   && r   rR  ÚMemoryStore._write_file£  sJ   € ð
	KÜ˜d¤O×$8Ñ$8¸Ó$AÈg×VøÜô 	KÜÐ!=¸d¸VÀ2ÀaÀSÐIÓJÐJûð	Kús   ‚!% ¥A°AÁAc                ó<   <€ V ^8„  d   QhRS[ RS[ RS[S[ ,          /# )r   rÎ   rU  r   r   )r   rÂ   s   "€r   r   rÃ   ­  s&   ø€ ÷ ñ ©Sð ±sð ¹xÉ½}ñ r   c                óª  € \        \        \        V P                  V4      4      ^ R7      V P	                  V4      8:  d   R# V P                  V4      pVP                  VP                  R\        \        P                  ! 4       4       2,           4      p VP                  VRR7       \        T4      #   \         d    \        T4      R,           u # i ; i)uù  ``.bak.<ts>`` snapshot path if *raw* shows external drift, else None. The one
signal is an entry over the whole-file limit: no tool-written entry can be, so it is
free-form text appended without delimiters, and replacing that "entry" would discard
it. Layout differences (blank lines around ``Â§``, empty entries, padding) are NOT
drift: parsing only strips whitespace, so the flush loses nothing but whitespace, and
refusing there blocked every replace/remove on a hand-formatted file for good (#107270).r"   Nz.bak.rü   rý   u+    (BACKUP FAILED â€” file unchanged on disk))ÚmaxÚmapro   rP  rò   rë   r  r  rZ   ÚtimeÚ
write_textr  r   )rÉ   rÎ   rU  r8   r9   s   &&&  r   rO  Ú"MemoryStore._detect_external_drift­  s¶   € ô Œs”3˜×+Ñ+¨CÓ0Ó1¸1Ô=À×AQÑAQÐRXÓAYÔYÙØ�~‰~˜fÓ%ˆØ×#Ñ# D§K¡K°E¼#¼d¿iºi»kÓ:JÐ9KÐ2LÕ$LÓMˆð	QØ×Ñ ¨gÐÔ6ô �8‹}Ðøô ô 	QÜ�x“=Ð#PÕPÒPð	Qús   ÂB2 Â2CÃC)rÈ   rÇ   rÀ   r½   rÅ   rÁ   rÆ   r¾   )i˜  i_  r]   ).Ú__name__Ú
__module__Ú__qualname__Ú__firstlineno__Ú__doc__rÝ   rÊ   rÒ   rÖ   rÞ   rô   Ústaticmethodr   r   rë   r)  rð   rñ   rò   r8  r>  rE  rI  rZ  rd  rO   rt  rs  r…  r{  r‘  rm  r¥  r±  rµ  r¯  rÕ  rS  ró   rN  rP  rï   rR  rO  Ú__static_attributes__Ú__classdictcell__)rÂ   s   @r   r¼   r¼   ¯   s  ø‡ € ñOð ,-Ð(ñ)Ø(,ð)ØKO÷)ó )÷Vð V÷)ð )÷7ð 7ò" zðD Ø÷'!ó ó ð'!ðR ÷_ó ð_÷Nð N÷Yð Y÷Dð D÷Tð T÷Lð L÷pð p÷rð r÷
	Yò 	YðMÀ÷ Mò M÷>;ð ;÷.Pò P÷Kò K÷,ò ,÷,Iò I÷ò ÷"?ð ?÷,ò ,ð& ÷-7ñ -7ó ð-7÷^<ð <÷=ð =÷?Cð ?C÷BDð D÷
Vò V÷]ð ]ð ÷ó ðð" ÷Qó ðQð ÷Ró ðRð
 ÷Kó ðK÷ö r   r¼   c                óV   € V ^8„  d   Qh/ ^ \         9   d   \        \        ,          ;R&   # )r   r,   )Ú__conditional_annotations__r   r   )r   s   "r   r   r      s%   € ÷ 0ñ 0÷F UÒ TŒzœ#�Ñ TòG0r   )4r  r  Úloggingr  rx   rü  Ú
contextlibr   r   Úcontextvarsr   Úpathlibr   Útypingr   r   r	   r
   r   Úutilsr   rê   r   r   Ú	getLoggerrã   rß  r1  r   r,   r/   r6   r@   rF   r   Ú	maketransr(   rî   rQ   rT   rj   rq   r‘   r™   rr  rž   r§   r²   r·   rº   r¼   r   )r  s   @r   Ú<module>r     s  øðö0ó
 Û 	Û 	Û ß /Ý "Ý ß 3Õ 3å #Ý Oà	×	Ò	Ð.Ó	/€ð
 Ð,¨fÐ6VðXÐ ð €õ:ñ ",Ð,BÈGÔ!T€Ó Tõ9õ
9õ
,õgð �m‰mð a˜tŸ}™}Ð-bÐdgÓhð aØ#Ÿ}™}Ð-YÐ[^Ó_ðaó b€õRõSõ4õPõ"kð
 z€õGõ
Sõ
õNõ
3÷Mó Mr   