+
    jHàjê�  ã                  ó  € R t ^ RIHt ^ RIt^ RIt^ RIt^ RIt^ RIt^ RIH	t	 ^ RI
HtHtHtHtHt ]'       d   ^ RIHt ]P$                  ! R4      t ! R R]4      tR	 R
 ltRtRtR R ltRR/R R llt ! R R4      tR# )zëSessionStore transcript I/O: SQLite append with a per-session retry queue, compression-reroute
following, FTS corruption recovery, rewrite/rewind/load. Mixin split out of ``gateway/session.py``;
bound onto ``SessionStore`` via the MRO.)ÚannotationsN)Úextract_api_content_sidecar)ÚTYPE_CHECKINGÚAnyÚDictÚListÚOptional)ÚSessionEntryzgateway.sessionc                  ó2   a € ] tR t^tRtR V 3R lltRtV ;t# )ÚTranscriptReadErrorz4Raised when persisted history cannot be read safely.c               ó    € V ^8„  d   QhRRRR/# ©é   Ú
session_idÚstrÚreturnÚNone© )Úformats   "Ú?/home/ubuntu/.hermes/hermes-agent/gateway/session_transcript.pyÚ__annotate__Ú TranscriptReadError.__annotate__   s   € ÷ Mñ M 3ð M¨4ñ Mó    c                	ó8   <€ Wn         \        SV `	  R V 24       R# )z#transcript read failed for session N)r   ÚsuperÚ__init__)Úselfr   Ú	__class__s   &&€r   r   ÚTranscriptReadError.__init__   s   ø€ Ø$ŒÜ‰ÑÐ>¸z¸lÐKÖLr   )r   )Ú__name__Ú
__module__Ú__qualname__Ú__firstlineno__Ú__doc__r   Ú__static_attributes__Ú__classcell__)r   s   @r   r   r      s   ø† Ù>÷Mö Mr   r   c               ó    € V ^8„  d   QhRRRR/# )r   r   r   Úmessageúdict[str, Any]r   )r   s   "r   r   r      s   € ÷ ñ ˜sð ¨^ñ r   c                óD   €  ^ RI Hp V! W4      #   \         d     R# i ; i)zŠSpool one evicted/undeliverable message to disk (same machinery as the shutdown flush, so it
is replayed after DB recovery); path or None.)Ú spool_dropped_transcript_messageN)Úgateway.shutdown_flushr*   Ú	Exception)r   r'   r*   s   && r   Ú_spool_droppedr-      s'   € ðÝKÙ/°
ÓDÐDøÜô Úðús   ‚ �žc               ó    € V ^8„  d   QhRRRR/# )r   Úvaluer   r   r   )r   s   "r   r   r   2   s   € ÷ 	ñ 	˜#ð 	 #ñ 	r   c                ó  € V eG   \        V \        \        34      '       g+   \        V \        4      '       d   RT u;8:  d
   R8  d    V #  MV #  \        P
                  ! V \        R7      #   \        \        3 d    \        T 4      u # i ; i)z¯*value* when sqlite can bind it as is, else its JSON text (``str`` if that fails too). An int
outside sqlite's signed 64-bit range raises OverflowError even for a TEXT column.)Údefaultl            lûÿÿÿ         )Ú
isinstancer   ÚfloatÚintÚjsonÚdumpsÚ	TypeErrorÚ
ValueError)r/   s   &r   Ú_bindable_textr9   2   su   € ð ‚}œ
 5¬3´¨,×7Ò7Ü�uœc×"Ò" v°Ö'>¸Õ'>Øˆñ (?ØˆðÜ�zŠz˜%¬Ô-Ð-øÜ”zÐ"ô Ü�5‹zÒðús   ÁA* Á*B	ÂB	Úfallback_tsc               ó(   € V ^8„  d   QhRRRRRRRR/# )r   r   r   r'   r(   r:   r   r   r   )r   s   "r   r   r   >   s*   € ÷ ñ ¨ð °~ð ÐWZð Ðftñ r   c               ó¢  € VP                  R4      R8H  pVP                  R4      pRV RVP                  RR4      RVP                  R4      RVP                  R4      RVP                  R4      R	VP                  R	4      /\         Uu/ uF  qUV'       d   VP                  V4      MR
bK   	  upCRVP                  R4      ;'       g    VP                  R4      R\        VP                  R4      4      RVf   TMTR\        V4      RVP                  R4      RVP                  R4      /Cp\         F  p\        Wg,          4      Wg&   K  	  V# u upi )a‚  ``SessionDB.append_message`` kwargs for one transcript row. The live writer and the restart
replay of the transcript spool (gateway/shutdown_flush.py) both build rows here, so a replayed
message lands as the row the live drain would have written. Fields are listed rather than
splatted: a spooled message is arbitrary JSON from disk, and an unexpected key would raise and
abort the replay. *fallback_ts* applies only to a message with no timestamp at all, because a
truthiness test would rewrite epoch 0. Values bound straight to a TEXT column are made bindable
(:func:`_bindable_text`), so one malformed field cannot make the row unwritable.ÚroleÚ	assistantÚ	timestampr   ÚunknownÚcontentÚ	tool_nameÚ
tool_callsÚtool_call_idNÚplatform_message_idÚ
message_idÚobservedÚapi_contentÚdisplay_kindÚdisplay_metadata)ÚgetÚ_ASSISTANT_ONLY_KEYSÚboolr   Ú_BOUND_TEXT_KEYSr9   )r   r'   r:   Úis_assistantr?   ÚkÚkwargsÚkeys   &&$     r   Útranscript_append_kwargsrS   >   s=  € ð —;‘;˜vÓ&¨+Ñ5€LØ—‘˜KÓ(€Ià�jØ�—‘˜F IÓ.Ø�7—;‘;˜yÓ)Ø�W—[‘[ Ó-Ø�g—k‘k ,Ó/Ø˜Ÿ™ NÓ3ðõ AUÓ
UÑ@T¸1§ˆg�k‰k˜!Œn°$Ò6Ñ@TÑ
Uðð 	˜wŸ{™{Ð+@ÓA×^Ð^ÀWÇ[Á[ÐQ]ÓE^Ø”D˜Ÿ™ ZÓ0Ó1Ø IÒ$5‘[¸9ð 	Ô2°7Ó;ð 	˜Ÿ™ NÓ3Ø˜GŸK™KÐ(:Ó;ñ#€F÷&  ˆÜ$ V¥[Ó1ˆ‹ñ  à€Mùò Vs   Â$Ec                  ó‚  € ] tR t^`tRt^ÈtRt^tR R ltR R lt	R R lt
R	 tR<R R l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4       tR% R& ltR' R( ltR) R* ltR+ R, ltR=R- R. lltR/ R0 ltR1 R2 lt R3 R4 lt!R5 R6 lt"R>R7R
/R8 R9 lllt#R:t$R;# )?ÚSessionTranscriptMixinz—SessionStore transcript I/O: SQLite append with a per-session retry queue,
compression-reroute following, FTS corruption recovery, rewrite/rewind/load.i,  c               ó    € V ^8„  d   QhRRRR/# )r   r   úOptional[str]r   r   )r   s   "r   r   Ú#SessionTranscriptMixin.__annotate__n   s   € ÷ 
ñ 
¸-ð 
ÈMñ 
r   c                óÒ   € V'       d   V P                  V4      MRpVf   V#  VP                  V4      ;'       g    T#   \         d    \        P	                  RTRR7       Tu # i ; i)z„Latest compression continuation for *session_id* (heals a mapping left pointing at a
compressed parent by a restart or failed send).Nz,Compression-tip lookup failed for session %sT©Úexc_info)Ú_db_for_session_idÚget_compression_tipr,   ÚloggerÚdebug©r   r   Údbs   && r   Ú_compression_tip_for_session_idÚ6SessionTranscriptMixin._compression_tip_for_session_idn   sj   € ÷ 5?ˆT×$Ñ$ ZÔ0ÀDˆØŠ:ØÐð	Ø×)Ñ)¨*Ó5×CÐC¸ÐCøÜô 	Ü�L‰LÐGÈÐ^bˆLÔcØÒð	ús   £> »> ¾%A&Á%A&c               ó(   € V ^8„  d   QhRRRRRRRR/# )r   Úentryr	   Úoriginal_session_idrW   Úcanonical_session_idr   rM   r   )r   s   "r   r   rX   z   s,   € ÷ ñ Ø!ðØ8Eðà+ðà04ñr   c                óª   € V'       d	   V'       g   R# VP                   V8w  g   W28X  d   R# \        P                  RVP                   V4       W1n         R# )zDRewrite *entry* to the compression continuation if stale. Lock held.Fz8SessionStore healed compressed session mapping: %s -> %sT)r   r^   Úinfo)r   re   rf   rg   s   &&&&r   Ú_heal_compression_tip_lockedÚ3SessionTranscriptMixin._heal_compression_tip_lockedz   sJ   € ÷ #×*>ÙØ×ÑÐ2Ô2Ð6JÔ6aÙÜ�‰ØFÈ×HXÑHXØ ô	"ð 0ÔÙr   c               ó(   € V ^8„  d   QhRRRRRRRR/# )r   Úsession_keyr   Úexpected_session_idÚtarget_session_idr   zOptional[SessionEntry]r   )r   s   "r   r   rX   ˆ   s,   € ÷ ñ ØðØ58ðØMPðà	ñr   c                ó€  € V'       d   V'       d	   V'       g   R# V P                   ;_uu_ 4        V P                  V4      pVf    RRR4       R# VP                  V8X  d   VuuRRR4       # V P                  WBV4      '       g    RRR4       R# V P	                  4        VuuRRR4       #   + '       g   i     R# ; i)u  CAS-advance one route along an already-verified compression lineage. Unlike
``switch_session`` this never ends/reopens SQLite rows (the compression transaction owns
that). ``None`` means the route moved after the caller's snapshot (e.g. /new) â€” caller
must fail closed.N)Ú_lockÚ_entry_lockedr   rj   Ú_save)r   rm   rn   ro   re   s   &&&& r   Úadvance_compression_sessionÚ2SessionTranscriptMixin.advance_compression_sessionˆ   s�   € ÷ ×"5×=NÙØ�Z�Z‹ZØ×&Ñ& {Ó3ˆEØŠ}Ø÷ ‰Zð ×ÑÐ#4Ô4Ø÷ ŠZð ×4Ñ4°UÐQb×cÒcØ÷ ‰Zð �J‰JŒLØ÷ �Z�Z‹Zús   ¯B,ÁB,Á-B,ÂB,Â,B=	c                óB   € V P                  R\        P                  4      # )z?Return the lock that serializes pending-queue drain boundaries.Ú_transcript_drain_lock)Ú_lazyÚ	threadingÚRLock)r   s   &r   Ú_get_transcript_drain_lockÚ1SessionTranscriptMixin._get_transcript_drain_lockœ   s   € à�z‰zÐ2´I·O±OÓDÐDr   Fc               ó(   € V ^8„  d   QhRRRRRRRR/# )	r   r   r   r'   r(   Úskip_dbrM   r   r   r   )r   s   "r   r   rX       s0   € ÷ ^ñ ^¨sð ^¸^ð ^ÐVZð ^Ðgkñ ^r   c                óÆ   € V'       d   R# V P                  4       ;_uu_ 4        V P                  V P                  V4      V4       RRR4       R#   + '       g   i     R# ; i)a  Serialize transcript draining across queue migration boundaries. A session with no usable
store is NOT skipped: the write is queued and counted like any other failed append, so a
dead/unopenable state.db escalates and spools instead of dropping turns silently
(#114266).N)r{   Ú _append_to_transcript_serializedÚ_follow_reroutes)r   r   r'   r~   s   &&&&r   Úappend_to_transcriptÚ+SessionTranscriptMixin.append_to_transcript    sD   € ÷
 ÙØ×,Ñ,×.Õ.Ø×1Ñ1°$×2GÑ2GÈ
Ó2SÐU\Ô]÷ /×.×.Ò.ús   £"AÁA 	c               ó    € V ^8„  d   QhRRRR/# ©r   r   r   r   r   )r   s   "r   r   rX   ª   s   € ÷ ñ ¨3ð °3ñ r   c                ó”   € V P                  R\        4      p\        4       pW9   d"   W9  d   VP                  V4       W!,          pK'  V# )z5Follow the compression reroute chain (cycle-guarded).Ú_transcript_reroutes)rx   ÚdictÚsetÚadd)r   r   ÚreroutesÚseens   &&  r   r�   Ú'SessionTranscriptMixin._follow_reroutesª   s?   € à—:‘:Ð4´dÓ;ˆÜ‹uˆØÔ$¨Ô)?Ø�H‰H�ZÔ Ø!Õ-ŠJØÐr   c               ó$   € V ^8„  d   QhRRRRRR/# )r   r   r   r'   r(   r   Úlistr   )r   s   "r   r   rX   ³   s"   € ÷ ñ °cð ÀNð ÐW[ñ r   c                ó¶  € V P                   P                  V. 4      pVP                  \        V4      4       \	        V4      V P
                  8”  d‰   \        WP                  ^ 4      4      pVeJ   V P                  R\        4      P                  V4       \        P                  RVV P
                  V4       V# \        P                  RVV P
                  4       V# )zKQueue *message* (retry lock held); evicts + spools the oldest past the cap.Ú_spooled_drop_sessionszsSession DB transcript pending queue full for %s (cap=%d); spooled oldest message to %s for replay after DB recoveryzzSession DB transcript pending queue full for %s (cap=%d); dropping oldest message to make room (on-disk spool unavailable))Ú_dirty_transcriptsÚ
setdefaultÚappendrˆ   ÚlenÚ_MAX_PENDING_PER_SESSIONr-   Úpoprx   r‰   rŠ   r^   Úwarning)r   r   r'   ÚpendingÚ
spool_paths   &&&  r   Ú_enqueue_transcript_messageÚ2SessionTranscriptMixin._enqueue_transcript_message³   s¾   € à×)Ñ)×4Ñ4°ZÀÓDˆØ�‰”t˜G“}Ô%ô
 ˆw‹<˜$×7Ñ7Ô7Ü'¨
·K±KÀ³NÓCˆJØÒ%Ø—
‘
Ð3´SÓ9×=Ñ=¸jÔIÜ—‘ðAØBLØ×1Ñ1°:ô?ð ˆô	 —‘ðGØHRØ×1Ñ1ô3ð ˆr   c               ó(   € V ^8„  d   QhRRRRRRRR/# )r   r   r   Úqueue_session_idÚexcr,   r   r   r   )r   s   "r   r   rX   Ê   s,   € ÷ ñ ØðØ14ðØ;Dðà	ñr   c                óH  € \         P                  RV\        V4      P                  V4       V P                  ;_uu_ 4        \        V P                  P                  V. 4      4      pV P                  P                  VR4       V P                  P                  VR4       RRR4       X F*  p\        W4      e   K  \         P                  RVRR7       K,  	   ^ RIHp V! W4       R#   + '       g   i     LQ; i  \         d    \         P                  RTRR7        R# i ; i)z²Stop SQLite writes on a replaced/quarantined handle and divert the backlog to the on-disk
spool + JSONL fallback: retrying cannot succeed and the FTS rebuild must never run here.z’Session DB refused further writes on this handle for %s (%s); stopping SQLite writes and diverting pending transcripts to the on-disk fallback: %sNz>pending fallback failed for replaced state.db transcript on %sTrZ   )Údivert_session_transcript_jsonlz:JSONL divert failed for replaced state.db transcript on %s)r^   ÚerrorÚtyper   Ú_transcript_retry_lockr�   r’   rK   r—   Ú_transcript_append_failuresr-   r˜   Úhermes_stater¡   r,   )r   r   rž   rŸ   Ú	remainingÚdroppedr¡   s   &&&&   r   Ú$_divert_transcript_after_db_replacedÚ;SessionTranscriptMixin._divert_transcript_after_db_replacedÊ   sù   € ô
 	�‰ðLØMWÜ�‹I×Ñ ô	%ð ×(×(Ó(Ü˜T×4Ñ4×8Ñ8Ð9IÈ2ÓNÓOˆIØ×#Ñ#×'Ñ'Ð(8¸$Ô?Ø×,Ñ,×0Ñ0°¸TÔB÷ )ó !ˆGÜ˜jÓ2Ô:Ü—‘ØTÐV`Ø!ð ö #ñ !ð
	ÝDÙ+¨JÖB÷ )×(ûô ô 	Ü�N‰NØLÈjØð ÷ ð	ús   Á AC'ÃC: Ã'C7	Ã:#D!Ä D!c               ó    € V ^8„  d   QhRRRR/# r…   r   )r   s   "r   r   rX   ä   s   € ÷ ñ °#ð ¸#ñ r   c                óØ   € V P                  V4      pVe   VP                  V4      MRpV'       d:   W18w  d4   VP                  V4      pVe   VP                  R4      f   \	        V4      # R# )a  Transitive compression tip of *session_id* if it is a different, still-live row, else ""
(a depth-1 lookup misses multi-hop lineages). Uses the PARENT's proven owner handle: the
child's id is unpublished until its write succeeds, so a by-id lookup would hit the ambient
store.NÚended_atÚ )r\   r]   Úget_sessionrK   r   )r   r   Úowner_dbÚtipÚtip_rows   &&   r   Ú_live_compression_childÚ.SessionTranscriptMixin._live_compression_childä   sd   € ð
 ×*Ñ*¨:Ó6ˆØ:BÒ:Nˆh×*Ñ*¨:Ô6ÐTXˆß�3Ô$Ø×*Ñ*¨3Ó/ˆGØÒ" w§{¡{°:Ó'>Ò'FÜ˜3“x�Ùr   c          
     ó,   € V ^8„  d   QhRRRRRRRRRR/# )r   r   r   rž   Úchild_idr™   r�   r   r   )r   s   "r   r   rX   ñ   s4   € ÷ ñ ØðØ14ðØ@CðØNRðà	ñr   c                óî  € V'       d   V^ ,          VJ d   VP                  ^ 4       V P                  P                  V. 4      pV'       d!   VP                  V4       W@P                  V&   M
V'       d   TpV P                  P                  VR4       V P                  P                  V^ 4      pV'       d3   \        WpP                  P                  V^ 4      4      V P                  V&   W0P                  V&   V# )aJ  Move the retry queue + failure counter from parent to child and record the reroute (retry
lock held); returns the child's pending list. Older parent backlog must precede messages
already queued directly on the child; routing is published only AFTER the queue moved
(caller), so new child writes cannot bypass older parent backlog.N)r—   r’   rK   Úextendr¥   Úmaxr‡   )r   r   rž   r¶   r™   ÚmsgÚexisting_child_pendingÚprevious_failuress   &&&&&&  r   Ú"_migrate_transcript_queue_to_childÚ9SessionTranscriptMixin._migrate_transcript_queue_to_childñ   sÑ   € ÷ �w˜q•z SÓ(Ø�K‰K˜ŒNØ!%×!8Ñ!8×!<Ñ!<¸XÀrÓ!JÐßØ�N‰NÐ1Ô2Ø07×#Ñ# HÒ-ß#Ø,ˆGØ×Ñ×#Ñ#Ð$4°dÔ;Ø ×<Ñ<×@Ñ@ÐAQÐSTÓUÐßÜ9<Ø!×#CÑ#C×#GÑ#GÈÐRSÓ#Tó:VˆD×,Ñ,¨XÑ6à08×!Ñ! *Ñ-Øˆr   c               ó$   € V ^8„  d   QhRRRRRR/# )r   r   r   r¶   r   r   r   )r   s   "r   r   rX     s&   € ÷ Pñ P°cð PÀSð PÈTñ Pr   c                óH  € V P                   ;_uu_ 4        V P                  P                  4        F  pVP                  V8X  g   K  W#n        K  	  V P	                  4        RRR4       \        V RR4      ;'       g    / P                  VR4       R#   + '       g   i     L9; i)zRRepoint every route at the compression child and save (index authoritative again).NÚ_session_owner_hints)rq   Ú_entriesÚvaluesr   rs   Úgetattrr—   )r   r   r¶   re   s   &&& r   Ú_publish_transcript_rerouteÚ2SessionTranscriptMixin._publish_transcript_reroute  sr   € à�Z�Z‹ZØŸ™×-Ñ-Ö/�Ø×#Ñ# zÖ1Ø'/Ö$ñ 0ð �J‰JŒL÷	 ô
 
�Ð-¨tÓ	4×	:Ð	:¸×?Ñ?ÀÈ$ÖO÷ �Zús   •,BÁBÂB!	c               ó$   € V ^8„  d   QhRRRRRR/# ©r   r   r   r'   r(   r   r   r   )r   s   "r   r   rX     s'   € ÷ iñ i¸3ð iÈð iÐ\`ñ ir   c           
     óø  a aaaa€ S P                   ;_uu_ 4        S P                  SV4      oS^ ,          oRRR4       SoR VVVV V3R llp Rp S P                  S4      pVe   VhS P                  SS4       S P                   ;_uu_ 4        V! 4       pV'       g
   S^ ,          oRRR4       X'       d   R# Kn    + '       g   i     L�; i  + '       g   i     L/; i  \         Ed   p^ RIHpHp ^ RIH	p	 \        YhT34      '       d   S P                  SST4        Rp?R# \        Yi4      '       EdG   S P                  S4      p
S P                  S4      pT'       dÉ   T
'       d   T
S P                  R\        4      T&    S P                  TS4       S P                   ;_uu_ 4        S P!                  SSTSS4      oToRRR4       M  + '       g   i     M; iS P#                  ST4       S'       g    Rp?R# S^ ,          oTo Rp?EKÄ    \         d   pTp Rp?M\Rp?ii ; iS P                   ;_uu_ 4        T! 4        RRR4       M  + '       g   i     M; i\$        P'                  RS4        Rp?R# S P)                  T4      '       dŽ   S P+                  4       '       dx   Te    Rp?EKj   S P                  SS4       S P                   ;_uu_ 4        T! 4        RRR4       M  + '       g   i     M; i Rp?EK¼    \         d   pTp Rp?MRp?ii ; iS P                   ;_uu_ 4        S P,                  P/                  S^ 4      ^,           pTS P,                  S&   RRR4       M  + '       g   i     M; iXS P0                  8¼  d6   S P3                  SS4      p\$        P'                  RST\5        S4      Yö4       M"\$        P7                  R	ST\5        S4      T4        Rp?R# Rp?ii ; i)
a  Append a message to a session's transcript (SQLite), draining the per-session retry
queue.

Args: skip_db: When True, skip the SQLite write. Used when the agent already persisted messages to
SQLite via its own _flush_messages_to_session_db(), preventing the duplicate-write bug (#860).
Nc               ó   € V ^8„  d   QhRR/# ©r   r   rM   r   )r   s   "r   r   ÚMSessionTranscriptMixin._append_to_transcript_serialized.<locals>.__annotate__  s   € ÷ 	ñ 	˜4ñ 	r   c                 óØ   <€ S'       d   S^ ,          S J d   SP                  ^ 4       S'       g;   SP                  P                  SR4       SP                  P                  SR4       R# R# )zCPop the acknowledged head (retry lock held). True if queue drained.NTF)r—   r’   r¥   )rº   r™   rž   r   r   s   €€€€€r   Ú	_ack_headÚJSessionTranscriptMixin._append_to_transcript_serialized.<locals>._ack_head  sR   ø€ ç˜7 1�:¨Ó,Ø—‘˜A”ßØ×'Ñ'×+Ñ+Ð,<¸dÔCØ×0Ñ0×4Ñ4°ZÀÔFÙÙr   )ÚStateDbCorruptErrorÚStateDbReplacedError)ÚCompressionSessionClosedErrorrÁ   zfSession DB transcript append rejected for compression-ended %s with no unique live child; not retryingz’Session DB transcript append failed for %s (failure_count=%d, pending=%d, spooled_to_disk=%d); session is stalled and needs operator attention: %szYSession DB transcript append failed for %s (failure_count=%d, pending=%d); will retry: %s)r¤   r›   Ú_drain_spooled_dropsÚ_append_transcript_messager,   r¦   rÐ   rÑ   Úhermes_state_errorsrÒ   r2   r©   Ú_owner_key_for_session_idr³   rx   rˆ   r½   rÅ   r^   r¢   Ú_is_fts_corruption_errorÚ_rebuild_fts_oncer¥   rK   Ú/_TRANSCRIPT_APPEND_FAILURE_ESCALATION_THRESHOLDÚ_spool_stalled_backlogr•   r˜   )r   r   r'   rÎ   Ú	spool_excÚqueue_emptyrŸ   rÐ   rÑ   rÒ   Ú
_owner_keyr¶   Úreroute_excÚ	retry_excÚfailuresÚspooledrº   r™   rž   s   ff&             @@@r   r€   Ú7SessionTranscriptMixin._append_to_transcript_serialized  sP  ü€ ð ×(×(Ó(Ø×6Ñ6°zÀ7ÓKˆGØ˜!•*ˆC÷ )ð &Ð÷	ô 	ð ØˆIðPð
 !×5Ñ5°jÓA�	ØÒ(Ø#�OØ×/Ñ/°
¸CÔ@ðD ×0×0Ó0Ù"+£+�Kß&Ø% a�j˜÷ 1÷ ÙÙ÷E )×(ú÷x 1×0ûôC õ ?ßRÝMÜ˜cÐ:MÐ#N×OÒOØ×=Ñ=¸jÐJZÐ\_Ô`ÝÜ˜c×AÓAà!%×!?Ñ!?À
Ó!K�JØ#×;Ñ;¸JÓG�Hß÷ &ØQ[˜DŸJ™JÐ'=¼tÓDÀXÑNð%Ø ×;Ñ;¸HÀcÔJð "&×!<×!<Ó!<Ø*.×*QÑ*QØ$.Ð0@À(ÈGÐUXó+Z à3;Ð 0÷ "=×!<×!<Ð!<úð !×<Ñ<¸ZÈÔRß#*Ý &Ø")¨!¥*˜CØ)1˜JÞ$øô  )ô .Ø"-�Cûð.úð  "×8×8Ó8Ù%œK÷ 9×8×8Ð8úäŸ™ðAØBLôNõ Ø×0Ñ0°×5Ò5¸$×:PÑ:P×:RÒ:RØ Ò,Þ ð!Ø×7Ñ7¸
ÀCÔHð "×8×8Ó8Ù%œK÷ 9×8×8Ð8úæ øô %ô (Ø'�ûð(úð ×0×0Ó0Ø#×?Ñ?×CÑCÀJÐPQÓRÐUVÕV�HØCK�D×4Ñ4°ZÑ@÷ 1×0×0Ð0úð ˜t×SÑSÔSØ"×9Ñ9¸*ÐFVÓW�GÜ—L‘Lð(à)3°X¼sÀ7»|ÈWõ[ô
 —N‘Nð)Ø*4°hÄÀGÃÈcôSõ ûð?ús  šB;Á)C! ÂCÂ;C	ÃC	Ã!O9Ã-4O4Ä';O4Å#O4Å+O4ÆHÆO4Æ+GÇ	O4ÇGÇ!O4Ç?O4ÈH(ÈH#ÈO4È#H(È(O4È?IÉ	O4ÉI ÉO4É?O4ÊO4Ê,O4Ê8L	Ë
O4ËK/Ë&	O4Ë/K?Ë:O4Ì	L ÌLÌO4ÌL Ì O4Ì73M3Í*	O4Í3NÍ>A0O4Ï4O9c               ó$   € V ^8„  d   QhRRRRRR/# )r   r   r   rž   r   r4   r   )r   s   "r   r   rX   |  s"   € ÷ ñ °ð Èð ÐPSñ r   c                ó  € V P                   ;_uu_ 4        V P                  P                  V. 4      p\        V4      pRRR4       ^ pX F  p\	        W4      f    MV^,          pK  	  V'       dn   V P                   ;_uu_ 4        V P                  R\        4      P                  V4       XRV1 V'       g   V P                  P                  VR4       RRR4       V# V#   + '       g   i     Lª; i  + '       g   i     T# ; i)a]  Move a stalled session's in-memory backlog (oldest first) to the on-disk pending spool so
a crash/restart during the outage no longer loses it (#114266): ``recover_pending_to_db``
replays it at boot, ``_drain_spooled_drops`` before the next live write. Stops at the first
spool failure so order holds; whatever stays in memory remains under the cap.Nr‘   )	r¤   r’   rK   r�   r-   rx   r‰   rŠ   r—   )r   r   rž   r™   Úbacklográ   r'   s   &&&    r   rÚ   Ú-SessionTranscriptMixin._spool_stalled_backlog|  sÙ   € ð
 ×(×(Ó(Ø×-Ñ-×1Ñ1Ð2BÀBÓGˆGÜ˜7“mˆG÷ )ð ˆÛˆGÜ˜jÓ2Ò:ÙØ�q�LŠGñ ÷ Ø×,×,Ó,Ø—
‘
Ð3´SÓ9×=Ñ=¸jÔIØ˜H˜W˜HÐ%ßØ×+Ñ+×/Ñ/Ð0@À$ÔG÷	 -ð
 ˆˆwˆ÷ )×(ú÷ -Ö,ð
 ˆús   •(CÂAC2ÃC/	Ã2D	c               ó    € V ^8„  d   QhRRRR/# )r   r   r   r   zException | Noner   )r   s   "r   r   rX   ‘  s   € ÷  ñ  ¨sð  Ð7Gñ  r   c                óf  a aa	€ \        S RR4      pV'       d   SV9  d   R# . o	R V	V V3R llp ^ RIHp S P                  ;_uu_ 4        \	        S P
                  P                  S4      4      pRRR4       V! SVXR7      w  rgV'       g1   S P                  ;_uu_ 4        VP                  S4       RRR4       R# S	'       d
   S	R
,          # \        RS R24      #   + '       g   i     Lu; i  + '       g   i     R# ; i  \         d#   p\        P                  R	ST4        Rp?R# Rp?ii ; i)zõReplay cap-dropped spooled transcript messages after DB recovery; return the replay
failure while some of them are still on disk, else None. Best-effort: replay failures keep
the spool files for the next successful flush; nothing here may raise.r‘   Nc               ó    € V ^8„  d   QhRRRR/# )r   r'   r(   r   r   r   )r   s   "r   r   ÚASessionTranscriptMixin._drain_spooled_drops.<locals>.__annotate__š  s   € ÷ 	ñ 	˜Nð 	¨tñ 	r   c                óx   <€  SP                  SV 4       R #   \         d   pSP                  T4       h R p?ii ; i)N)rÔ   r,   r”   )r'   rŸ   rà   r   r   s   & €€€r   ÚreplayÚ;SessionTranscriptMixin._drain_spooled_drops.<locals>.replayš  s7   ø€ ðØ×/Ñ/°
¸GÖDøÜô Ø—‘ Ô$Øûðús   ƒ —9¢4´9)Údrain_transcript_spool)Údb_known_failingz"older spooled transcript rows for z still pendingz+Failed to drain transcript spool for %s: %séÿÿÿÿ)rÄ   r+   rî   r¤   rM   r¥   rK   ÚdiscardÚRuntimeErrorr,   r^   r˜   )
r   r   Úspooled_sessionsrì   rî   Úknown_failingÚ	_replayedr§   rŸ   rà   s
   ff       @r   rÓ   Ú+SessionTranscriptMixin._drain_spooled_drops‘  s  ú€ ô # 4Ð)AÀ4ÓHÐß :Ð5EÔ#EÙØ$&ˆ÷	ò 	ð	ÝEð ×,×,Ó,Ü $ T×%EÑ%E×%IÑ%IÈ*Ó%UÓ V�÷ -á#9Ø˜F°]ô$DÑ ˆIçØ×0×0Ó0Ø$×,Ñ,¨ZÔ8÷ 1áß#+�8˜B•<ð Q´Ø4°Z°LÀÐOó2Qð Q÷ -×,ú÷
 1Ö0áûô ô 	Ü�N‰NÐHÈ*ÐVYÔZÝûð	ús_   °D Á
%CÁ/1D Â C/Â2D Â<D ÃD ÃD ÃC,	Ã'D Ã/D 	Ã:D Ä D ÄD0ÄD+Ä+D0c               ó   € V ^8„  d   QhRR/# )r   r   r   r   )r   s   "r   r   rX   ³  s   € ÷ Jñ J¸ñ Jr   c                óÆ   € V'       g   R# V P                   ;_uu_ 4        V P                  R\        4      P                  V4       RRR4       R#   + '       g   i     R# ; i)z°Have each session's next transcript write drain the on-disk spool first. Boot recovery marks
the sessions it held back, so their next live row cannot land ahead of those files.Nr‘   )r¤   rx   r‰   Úupdate)r   Úsession_idss   &&r   Úmark_spooled_drop_sessionsÚ1SessionTranscriptMixin.mark_spooled_drop_sessions³  s?   € ÷ ÙØ×(×(Ó(Ø�J‰JÐ/´Ó5×<Ñ<¸[ÔI÷ )×(×(Ò(ús   Ÿ&AÁA 	c               ó$   € V ^8„  d   QhRRRRRR/# rÈ   r   )r   s   "r   r   rX   »  s'   € ÷ Lñ L°Sð LÀ>ð LÐVZñ Lr   c                ó„   € V P                  V4      pVf   \        RV R24      hVP                  ! R/ \        W4      B  R# )z7Write one transcript row. Caller handles retry queuing.Nzno owning session store for z; deferring transcript writer   )r\   rò   Úappend_messagerS   )r   r   r'   Ú_dbs   &&& r   rÔ   Ú1SessionTranscriptMixin._append_transcript_message»  sL   € à×%Ñ% jÓ1ˆØŠ;ô Ø.¨z¨lÐ:VÐWóYð Yà×ÒÑKÔ5°jÓJÔKr   c               ó    € V ^8„  d   QhRRRR/# )r   rŸ   r,   r   rM   r   )r   s   "r   r   rX   Æ  s   € ÷ hñ h ið h°Dñ hr   c                ó²   € R\        V 4      P                  4       9   d   R# ^ RIp^ RIHp \        WP                  4      ;'       d    VP                  V 4      # )ua  True only when the failure is provably scoped to the FTS index. A bare SQLITE_CORRUPT
can mean structural B-tree damage; only errors naming ``messages_fts`` or carrying FTS
provenance (``SessionDB._is_fts_write_corruption_error``) may authorize the one-shot
rebuild-and-retry; everything else takes the retry path.

A generic ``database disk image is malformed`` (bare SQLITE_CORRUPT) can mean structural damage to
canonical B-trees, not just the FTS shadow tables â€” treating it as FTS-only here made the store
rebuild the index and retry transcript writes against a structurally corrupt database (#97940).
Úmessages_ftsTN)Ú	SessionDB)r   ÚlowerÚsqlite3r¦   r  r2   ÚDatabaseErrorÚ_is_fts_write_corruption_error)rŸ   r  r  s   &  r   r×   Ú/SessionTranscriptMixin._is_fts_corruption_errorÅ  sE   € ð œS ›XŸ^™^Ó-Ô-ÙÛÝ*Ü˜#×4Ñ4Ó5×gÐg¸)×:bÑ:bÐcfÓ:gÐgr   c               ó   € V ^8„  d   QhRR/# rË   r   )r   s   "r   r   rX   Ö  s   € ÷ "ñ " 4ñ "r   c                ó   € \         P                  ! 4       pV P                  pVe   W,
          V P                  8  d   R# V P                  pVe   \        VR4      '       g   R# Wn        Rp\        VR4      '       d   VP                  4       pV'       d   \        P                  RV4       R#  VP                  4       pT'       d   \        P                  RT4       T^ 8„  #   \         d"   p\        P                  RT4        Rp?R# Rp?ii ; i)a  Attempt FTS5 ``rebuild``, at most once per ``_FTS_REBUILD_COOLDOWN_SECONDS`` window;
True if any index was rebuilt.

A permanent one-shot flag meant a single rebuild failure (e.g. a transient WAL
split-brain guard hit) permanently disabled recovery for the life of the process, even
though later corruption on the same store could be fixable. Retrying on a cooldown lets
the store try again after the underlying condition (e.g. a foreign holder) has likely
cleared, without hammering a database that is corrupt on every write.
NFÚrebuild_ftsÚ_foreign_state_db_holdersz�Skipping Session DB FTS rebuild while foreign processes hold the database or WAL sidecars (%s); canonical transcript writes remain available.z!Session DB FTS rebuild failed: %sz;Rebuilt %d Session DB FTS index(es) after append corruption)ÚtimeÚ	monotonicÚ_fts_rebuild_last_attempt_atÚ_FTS_REBUILD_COOLDOWN_SECONDSr   Úhasattrr  r^   r˜   r  r,   )r   ÚnowÚlast_attemptra   Úforeign_holdersÚrebuiltrŸ   s   &      r   rØ   Ú(SessionTranscriptMixin._rebuild_fts_onceÖ  sê   € ô �nŠnÓˆØ×8Ñ8ˆØÒ#¨Õ);¸t×?aÑ?aÔ(aÙØ�X‰XˆØŠ:œW R¨×7Ò7ÙØ,/Ô)àˆÜ�2Ð2×3Ò3Ø ×:Ñ:Ó<ˆOßÜ�N‰NðSØTcôeñ ð	Ø—n‘nÓ&ˆG÷ Ü�N‰NÐXÐZaÔbØ˜‰{Ðøô ô 	Ü�N‰NÐ>ÀÔDÝûð	ús   Â.C! Ã!DÃ,DÄDc               ó    € V ^8„  d   QhRRRR/# r   r   )r   s   "r   r   rX   ú  s   € ÷ Cñ C°#ð C¸$ñ Cr   c                óØ   € V P                   ;_uu_ 4        V P                  P                  VR4       V P                  P                  VR4       RRR4       R#   + '       g   i     R# ; i)zHDrop queued pending messages so a rewrite/rewind doesn't re-insert them.N)r¤   r’   r—   r¥   )r   r   s   &&r   Ú_clear_dirty_transcriptÚ.SessionTranscriptMixin._clear_dirty_transcriptú  sI   € à×(×(Ó(Ø×#Ñ#×'Ñ'¨
°DÔ9Ø×,Ñ,×0Ñ0°¸TÔB÷ )×(×(Ò(ús   •9AÁA)	c               ó$   € V ^8„  d   QhRRRRRR/# )r   r   r   rE   r   rM   r   )r   s   "r   r   rX      s"   € ÷ ñ °#ð ÈCð ÐTXñ r   c                ó®   € V P                  V4      pV'       g   R#  VP                  W4      #   \         d    \        P	                  RRR7        R# i ; i)a  Whether a message with this platform_message_id is persisted (False without a DB).

Thin wrapper over SessionDB.has_platform_message_id(). Returns False when no DB is available
(in-memory sessions). Used by the gateway's transient-failure dedupe guard (#47237).
Fz%has_platform_message_id lookup failedTrZ   )r\   Úhas_platform_message_idr,   r^   r_   )r   r   rE   ra   s   &&& r   r  Ú.SessionTranscriptMixin.has_platform_message_id   sS   € ð ×$Ñ$ ZÓ0ˆßÙð	Ø×-Ñ-¨jÓNÐNøÜô 	Ü�L‰LÐ@È4ˆLÔPÚð	ús   �. ®"AÁAc               ó    € V ^8„  d   QhRRRR/# )r   r   r   r   rW   r   )r   s   "r   r   rX     s   € ÷ ñ ¨sð °}ñ r   c                óð   € V P                  V P                  V4      4      pV P                  V4      pV'       g   R#  VP                  V4      #   \         d    \
        P                  RTRR7        R# i ; i)u¯   Role of the newest live conversation row on the route ``load_transcript`` reads (``None``
when empty, no DB, or the read fails â€” the boundary write would fail the same way).Nz$transcript tail lookup failed for %sTrZ   )rb   r�   r\   Úlatest_conversation_roler,   r^   r_   r`   s   && r   Útranscript_tail_roleÚ+SessionTranscriptMixin.transcript_tail_role  sr   € ð ×9Ñ9¸$×:OÑ:OÐPZÓ:[Ó\ˆ
Ø×$Ñ$ ZÓ0ˆßÙð	Ø×.Ñ.¨zÓ:Ð:øÜô 	Ü�L‰LÐ?ÀÐVZˆLÔ[Úð	ús   ½A Á#A5Á4A5c          
     ó,   € V ^8„  d   QhRRRRRRRRRR/# )	r   r   r   Úmessagesúlist[dict[str, Any]]Úactive_onlyrM   Úreject_active_turn_leaser   r   )r   s   "r   r   rX     s4   € ÷  ñ  Øð Ø)=ð ØLPð à"&ð à37ñ r   c           	     ób  € V P                  V4      pV'       g   R# V P                  4       ;_uu_ 4         VP                  WVVR7       T P                  T4        RRR4       R#   \         d*   p\        P                  RT4        Rp?RRR4       R# Rp?ii ; i  + '       g   i     R# ; i)uâ  Replace a session's transcript (/retry, /compress). DESTRUCTIVE by default:
``active_only=False`` DELETEs every row incl. soft-archived compaction history (pass
``active_only=True`` for sessions that may carry archived rows). True when the write lands
or there is no DB, False on failure â€” callers committing a destructive change on top
(/compress repointing) must check it. ``reject_active_turn_lease`` is for user-initiated
rewrites that do not own the cross-process turn lease.T)r)  r*  z&Failed to rewrite transcript in DB: %sNF)r\   r{   Úreplace_messagesr,   r^   r_   r  )r   r   r'  r)  r*  ra   Úes   &&&&&  r   Úrewrite_transcriptÚ)SessionTranscriptMixin.rewrite_transcript  sŸ   € ð ×$Ñ$ ZÓ0ˆßÙØ×,Ñ,×.Õ.ðð ×#Ñ#Ø°kØ-Eð $ô Gð ×(Ñ(¨Ô4Ø÷) /Ñ.øô  ô Ü—‘ÐEÀqÔIÛ÷% /Ñ.ûð ú÷! /×.Ð.ús4   ´B¶A&Á
BÁ&BÁ1BÂBÂBÂBÂB.	c               ó$   € V ^8„  d   QhRRRRRR/# )r   Úparent_session_idr   Úchild_session_idr   rM   r   )r   s   "r   r   rX   >  s#   € ÷ ñ Àð ÐWZð Ð_cñ r   c                óf  € V'       d	   V'       g   R# V P                  V4      pVf   R#  VP                  V4      pV'       d   VP                  R4      V8w  d   R# VP                  V4      '       g   R# VP	                  V4      ^ 8„  #   \
         d    \        P                  RTRR7        R# i ; i)an  True when *child_session_id* is an atomically-published compression continuation of
*parent_session_id*: ``publish_compression_child()`` wrote the handoff (plus any cloned
foreign-tail rows) in the SAME transaction that ended the parent with
``end_reason='compression'``, so the child transcript is already durable on disk.

Rewriting such a child is redundant AND destructive: the in-memory handoff lacks the rows
cloned during publication, and a failed rewrite reports a false "failed to persist
compressed transcript" over a committed compression. Fails open (False) on any DB error so
callers fall back to the rewrite.Fr1  z/published-compression-child probe failed for %sTrZ   )r\   r¯   rK   Ú_is_compression_child_rowÚget_active_message_watermarkr,   r^   r_   )r   r1  r2  ra   Úchilds   &&&  r   Úis_published_compression_childÚ5SessionTranscriptMixin.is_published_compression_child>  s¤   € ÷ !×(8Ùà×$Ñ$Ð%6Ó7ˆØŠ:Ùð		Ø—N‘NÐ#3Ó4ˆEß˜EŸI™IÐ&9Ó:Ð>OÔOÙØ×/Ñ/°×6Ò6ÙØ×2Ñ2Ð3CÓDÀqÑHÐHøÜô 	Ü�L‰LÐJÐL\ÐgkˆLÔlÚð	ús#   «B	 ÁB	 ÁB	 Á5B	 Â	#B0Â/B0c               ó(   € V ^8„  d   QhRRRRRRRR/# )r   r1  r   r2  r'  r(  r   rM   r   )r   s   "r   r   rX   Y  s2   € ÷ Hñ HØ%(ðHØ<?ðHØK_ðHØdhñHr   c                óV   € V P                  W4      ;'       g    V P                  W#4      # )z¬Make a rotated compression child durable before the live entry is repointed: a published
child already is, anything else gets *messages* written by the destructive rewrite.)r7  r.  )r   r1  r2  r'  s   &&&&r   Ú!persist_rotated_compression_childÚ8SessionTranscriptMixin.persist_rotated_compression_childY  s4   € ð ×3Ñ3Ð4EÓX÷ Gð GØ×*Ñ*Ð+;ÓFð	Hr   c               ó$   € V ^8„  d   QhRRRRRR/# )r   r   r   Úownerr   rM   r   )r   s   "r   r   rX   `  s!   € ÷ 9ñ 9¨#ð 9°cð 9¸dñ 9r   c                óÀ  €  V P                  V4      pV P                  V4      pVP                  V4      ;'       g    Tp\        4       pV'       do   W59  di   VP	                  V4       VP                  W24      '       d   R# VP                  V4      pV'       d   VP                  V4      '       g    R# VR,          pKv  R#   \         d   p\        T4      ThRp?ii ; i)zðFind this accepted input on the canonical live continuation and its ancestors.

Content and unrelated writers cannot establish ownership. Query only existence;
compaction archives can contain many megabytes that replay never needs to load.
Tr1  FN)
r�   r\   r]   r‰   rŠ   Úhas_gateway_input_ownerr¯   r4  r,   r   )r   r   r>  Úcurrentra   rŒ   Úrowr-  s   &&&     r   Úhas_input_ownerÚ&SessionTranscriptMixin.has_input_owner`  sÂ   € ð	9Ø×+Ñ+¨JÓ7ˆGØ×(Ñ(¨Ó1ˆBØ×,Ñ,¨WÓ5×@Ð@¸ˆGÜ“5ˆDß˜gÔ1Ø—‘˜Ô!Ø×-Ñ-¨g×=Ò=ÙØ—n‘n WÓ-�ß "×">Ñ">¸s×"CÒ"CØáð Ð1Õ2’ÙøÜô 	9Ü% jÓ1°qÐ8ûð	9ús:   ‚9C ¼C Á.C ÂC ÂC Â1C Â4C ÃCÃCÃCc               ó    € V ^8„  d   QhRRRR/# )r   r   r   r   r(  r   )r   s   "r   r   rX   w  s   € ÷ 9ñ 9¨#ð 9Ð2Fñ 9r   c                óÞ  € V P                  V4      '       g   . # V P                  V4      p\        P                  ! \        4      ;_uu_ 4        V P                  V4      pVP                  V4      ;'       g    TpRRR4        V P                  V4      P                  VRR7      #   + '       g   i     L3; i  \         d*   p\        P                  RYRR7       \        T4      ThRp?ii ; i)u  Load all messages from a session's transcript (state.db is canonical). Reads follow the
same routing writes use â€” the in-memory reroute map, then the durable compression tip â€”
otherwise the transcript "vanishes" while every message sits under the child.NT)Úrepair_alternationzVTranscript read failed for session %s; refusing to treat the conversation as empty: %srZ   )
r\   r�   Ú
contextlibÚsuppressr,   r]   Úget_messages_as_conversationr^   r¢   r   )r   r   ra   r-  s   &&  r   Úload_transcriptÚ&SessionTranscriptMixin.load_transcriptw  sÜ   € ð ×&Ñ& z×2Ò2ØˆIØ×*Ñ*¨:Ó6ˆ
Ü× Ò ¤×+Õ+à×(Ñ(¨Ó4ˆBØ×/Ñ/°
Ó;×IÐI¸zˆJ÷ ,ð
	9à×*Ñ*¨:Ó6×SÑSØ¨tð Tó 5ð 5÷ ,×+ûô ô 	9ô �L‰LðØ'°Tð ô ;ô & jÓ1°qÐ8ûð	9ús$   Á-B%Â!B8 Â%B5	Â8C,Ã$C'Ã'C,Úrequire_retryable_compositec               ó(   € V ^8„  d   QhRRRRRRRR/# )	r   r   r   Únr4   rM  rM   r   zOptional[dict[str, Any]]r   )r   s   "r   r   rX   Ž  s,   € ÷ 6ñ 6Øð6Ø"%ð6ØKOð6à	!ñ6r   c          	     óB  € V P                  V4      pV'       g   R# ^ RIHp V P                  4       ;_uu_ 4         VP	                  V\        V^4      ) VVR7      pT P                  T4       RTP                  RTP                  RTP                  /uuRRR4       #   T d*   p\        P                  RT4        Rp?RRR4       R# Rp?i\         d    h \         d*   p\        P                  RT4        Rp?RRR4       R# Rp?ii ; i  + '       g   i     R# ; i)	uý  Back up ``n`` user turns via soft-delete (``active=0``), mirroring CLI ``/undo [N]``.
Returns ``{"rewound_count", "turns_undone", "target_text"}`` or ``None`` (no DB / no rewindable
turn / persistence failure); ``n`` clamps to the oldest user turn. ``require_retryable_composite``
is the gateway ``/retry`` guard: the selected turn must be a composite carrier whose live payload
is losslessly replayable as text â€” that replay-policy ``ValueError`` propagates so /retry can
explain why the carrier is unsafe.N)ÚRewindTargetUnavailableError)Úrequire_retryableÚrequire_compositezrewind_session: %sz!rewind_session: rewind failed: %sÚrewound_countÚturns_undoneÚtarget_text)r\   Úhermes_state_rewindrQ  r{   Úrewind_user_turnr¹   r^   r_   r8   r,   r  rT  rU  Ú	live_text)r   r   rO  rM  ra   rQ  Úoutcomer-  s   &&&$    r   Úrewind_sessionÚ%SessionTranscriptMixin.rewind_sessionŽ  sÿ   € ð ×$Ñ$ ZÓ0ˆßÙÝDØ×,Ñ,×.Õ.ðØ×-Ñ-Ø¤ Q¨£ 
Ð>YØ&Að .ó C�ð ×(Ñ(¨Ô4Ø# W×%:Ñ%:¸NÈG×L`ÑL`Ø! 7×#4Ñ#4ð6÷ /Ò.øð
 0ô Ü—‘Ð1°1Ô5Û÷ /Ñ.ûô ô ØÜô Ü—‘Ð@À!ÔDÛ÷ /Ñ.ûðú÷ /×.Ð.úsR   ºD¼ BÁ6DÂD
Â$CÂ:DÃD
Ã
D
Ã D
Ã!DÃ7DÄD
Ä
DÄD	)r  N)F)FF)é   )%r   r    r!   r"   r#   r–   r  rÙ   rb   rj   rt   r{   r‚   r�   r›   r©   r³   r½   rÅ   r€   rÚ   rÓ   rû   rÔ   Ústaticmethodr×   rØ   r  r  r$  r.  r7  r;  rC  rK  r[  r$   r   r   r   rU   rU   `   sÑ   † ñTð  #Ðð %(Ð!ð 78Ð3õ
õõò(E÷^õõõ.õ4õõ.PõiõVõ* õDJõLð ôhó ðhõ "õHCõõ÷ õDõ6Hõ9õ.9ñ.6ØRW÷6ô 6r   rU   )Ú	reasoningÚreasoning_contentÚreasoning_detailsÚcodex_reasoning_itemsÚcodex_message_items)r=   rB   rD   r_  r`  rE   )r#   Ú
__future__r   rH  r5   Úloggingry   r  Úagent.turn_contextr   Útypingr   r   r   r   r   Úgateway.sessionr	   Ú	getLoggerr^   rò   r   r-   rL   rN   r9   rS   rU   r   r   r   Ú<module>rj     sƒ   ðñ,õ #ã Û Û Û Û Ý :ß ;Õ ;çÝ,ð 
×	Ò	Ð,Ó	-€ôM˜,ô MõðÐ ð rÐ õ	ðÐ]a÷ ÷DJ	6ó J	6r   