+
    jHàj´ ã                  óJ  € R t ^ RIH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HtHtHtHt ^ RIHt ^ RIHt ^ RIHtHt ^ R	IHtHt ^ R
IHt ^ RIHtH t  ^ RI!H"t" ]'       d   ^ RI#H$t$ ^ RI%H&t& ]PN                  ! R4      t(Rt)R R lt*R R lt+ ! R R4      t,R# )a  Agent cache, session model overrides, turn leases, run generations and conversation-scope reset
for GatewayRunner (MRO mixin). ``gateway.run`` internals are imported lazily inside method bodies
(import cycle), so ``patch("gateway.run.X")`` keeps intercepting them at call time.)ÚannotationsN)ÚnullcontextÚsuppress)ÚPath)ÚTYPE_CHECKINGÚAnyÚDictÚListÚOptional)Ú_accepts_keyword)ÚPlatform)ÚSessionSourceÚbuild_session_context_prompt)ÚPROMPT_PIN_VERSIONÚsanitize_prompt_pin)Ú_log_suppressed)ÚDEFAULT_CONFIGÚcfg_get)ÚLLAMACPP_ALIASES)ÚGatewayRunner)Ú
TurnRunnerzgateway.runc               ó    € V ^8„  d   QhRRRR/# ©é   Úentryr   Úreturn© )Úformats   "Ú</home/ubuntu/.hermes/hermes-agent/gateway/run_agent_cache.pyÚ__annotate__r   $   s   € ÷ Eñ E˜ð E ñ Eó    c                óT   € \        V \        4      '       d   V '       d
   V ^ ,          # T # )zNUnwrap a cache entry (``(agent, sig, ...)`` tuple or bare agent) to its agent.©Ú
isinstanceÚtuple©r   s   &r   Ú_first_agentr&   $   s   € ä! %¬×/Ò/·Eˆ5��8ÐD¸uÐDr    c               ó    € V ^8„  d   QhRRRR/# r   r   )r   s   "r   r   r   )   s   € ÷ Dñ D˜ð D ñ Dr    c                óT   € \        V \        4      '       d   V '       d
   V ^ ,          # R# )zMAgent of a ``(agent, sig, ...)`` cache tuple; None for any other entry shape.Nr"   r%   s   &r   Ú_tuple_agentr)   )   s   € ä! %¬×/Ò/·Eˆ5��8ÐC¸tÐCr    c                  óè  € ] tR t^.t$ Rt]R R l4       t/ tR]R&   ]R R l4       t	]
RqR
 R ll4       tR R ltR R ltR R ltR R ltRrR R lltR R ltR R ltRR/R R lltRR/R R lltR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//R0 R1 lltR2 R3 ltR4 R5 ltR6 R7 ltR8R/R9 R: llt R;R</R= R> llt!R? R@ lt"RA RB lt#RC RD lt$RE RF lt%RG RH lt&RI RJ lt'RKR	/RL RM llt(RN RO lt)]
RP RQ l4       t*RRR	RSR	/RT RU llt+RV RW lt,RXR/RY RZ llt-R[ R\ lt.RsR] R^ llt/RsR_ R` llt0Ra Rb lt1Rc t2Rd Re lt3Rf Rg lt4Rh Ri lt5Rj Rk lt6Rl Rm lt7Rn Ro lt8Rpt9R# )tÚGatewayAgentCacheMixinzrAgent cache, session model overrides, turn leases, run generations and conversation-scope reset for GatewayRunner.c               ó    € V ^8„  d   QhRRRR/# )r   Úuser_configúdict | Noner   Údictr   )r   s   "r   r   Ú#GatewayAgentCacheMixin.__annotate__2   s   € ÷ ñ ¸ð Èñ r    c                ó  € / p\        V\        4      '       d   TM/ pV P                   Fk  w  rE\        \        WE4      pVP                  V4      pVR8X  d+   \        V\        4      '       d   VR8X  d   TMTW$ RV 2&   KW  \        W4WVR7      W$ RV 2&   Km  	   ^ RIHp \        VRR4      VR&   V P                  \        VR	R
4      4      P                  4        F  w  rYW’RV 2&   K  	  V#   \         d	    RTR&    LNi ; i)u¿  Values that must bust the cached agent, as a flat dict keyed by 'section.key'. ``user_config``
is the raw file (no DEFAULT_CONFIG merge), so absent keys and non-dict sections take the
DEFAULT_CONFIG value â€” what the agent was actually built with â€” while an explicit ``null`` stays
None so opting out of a non-None default still rebuilds. Includes the live tool registry
generation: MCP reloads mutate the registry without touching config.yaml.ÚcheckpointsÚenabledÚ.)Údefault)ÚregistryÚ_generationNztools.registry_generationÚmemoryÚproviderzmemory.)r#   r/   Ú_CACHE_BUSTING_CONFIG_KEYSr   r   ÚgetÚboolÚtools.registryr6   ÚgetattrÚ	ExceptionÚ#_memory_provider_identity_signatureÚitems)
Úclsr-   ÚoutÚcfgÚsectionÚkeyr5   Úsection_valr6   Úvalues
   &&        r   Ú_extract_cache_busting_configÚ4GatewayAgentCacheMixin._extract_cache_busting_config1   s  € ð !ˆÜ'¨´T×:Ò:‰kÀˆØ×:Ô:‰LˆGÜœn¨gÓ;ˆGØŸ'™' 'Ó*ˆKØ˜-Ô'¬J°{ÄD×,IÒ,Ià9<À	Ô9I©+Èw��i˜q  Ð&Ó'ä*1°#ÀÔ*U��i˜q  Ð&Ó'ñ ;ð	4Ý/Ü/6°xÀÐPTÓ/UˆCÐ+Ñ,ð ×AÑAÄ'È#ÈxÐYcÓBdÓe×kÑkÖm‰JˆCØ#(�'˜#˜�Ó ñ nàˆ
øô	 ô 	4Ø/3ˆCÐ+Ó,ð	4ús   ÂC+ Ã+C>Ã=C>údict[str, Any]Ú_MEMORY_IDENTITY_PROVIDER_MEMOc               ó    € V ^8„  d   QhRRRR/# )r   Úprovider_namer   r   rK   r   )r   s   "r   r   r0   O   s   € ÷ ñ Àð Èñ r    c                óô  € \        V\        4      '       d   VP                  4       '       g   / # VP                  4       p V P                  P	                  V4      pVfC   ^ RIHp ^ RIHp V! 4       ;_uu_ 4        V! VRR7      pRRR4       Vf   / # W0P                  V&   VP                  4       p\        V\        4      '       d   \        V4      # / #   + '       g   i     LW; i  \         d    / u # i ; i)z~The active memory provider's ``identity_signature()``. ``{}`` when there is no provider,
it fails to load, or the hook raises.N)Úload_memory_provider)Úbounded_load_waitF)Úregister_skills)r#   ÚstrÚstriprL   r;   Úplugins.memoryrP   Úplugins.plugin_loaderrQ   Úidentity_signaturer/   r?   )rB   rN   ÚnameÚinstancerP   rQ   Ú	signatures   &&     r   r@   Ú:GatewayAgentCacheMixin._memory_provider_identity_signatureN   sÓ   € ô ˜-¬×-Ò-°]×5HÑ5H×5JÒ5JØˆIØ×"Ñ"Ó$ˆð	Ø×9Ñ9×=Ñ=¸dÓCˆHØÒÝ?ÝCÙ&×(Õ(Ù3°DÈ%ÔP�H÷ )àÒ#Ø�IØ;C×2Ñ2°4Ñ8Ø ×3Ñ3Ó5ˆIÜ&0°¼D×&AÒ&A”4˜	“?ÐIÀrÐI÷ )×(ûô ô 	ØŠIð	ús6   Á :C' Á:CÂC' Â>C' ÃC' ÃC$	ÃC' Ã'C7Ã6C7NFc               ó<   € V ^8„  d   QhRRRRRRRRRR	R
RRRRRRR/	# )r   ÚmodelrS   Úruntimer/   Úenabled_toolsetsÚlistÚephemeral_promptÚ
cache_keysr.   Úuser_idú
str | NoneÚuser_id_altÚskip_context_filesr<   r   r   )r   s   "r   r   r0   e   sX   € ÷ (>ñ (>Øð(>Ø!ð(>Ø59ð(>ØMPð(>àð(>à1;ð(>àQ[ð(>ð !ð(>ð 
ñ	(>r    c                ó2  € ^ RI p^ RIp	\        VP                  RR4      ;'       g    R4      p
T	P	                  T V
'       d.   VP                  V
P                  4       4      P                  4       MRVP                  RR4      VP                  RR4      VP                  RR4      VP                  RR4      \        VP                  R4      ;'       g    / P                  4       4      V'       d   \        V4      M. T;'       g    R\        T;'       g    / P                  4       4      \        T;'       g    R4      \        T;'       g    R4      \        V4      .R	\        R
7      pVP                  VP                  4       4      P                  4       R,          # )u  Stable key from agent config: change â†’ cached AIAgent rebuilt; unchanged â†’ reused (frozen
prompt + schemas for cache hits). ``user_id`` / ``user_id_alt`` participate because Honcho
freezes them at init; omitting them in shared-thread keys would cross-attribute messages.

``user_id`` and ``user_id_alt`` are the runtime user identities carried by the current message's
gateway source. They participate in the cache key because memory providers freeze them at
first-message init (the Honcho plugin resolves its user peer from them once). Without them in the signature, a
shared-thread session_key (one in which ``build_session_key`` intentionally omits the participant
ID, e.g. ``thread_sessions_per_user=False``) would reuse the cached AIAgent across distinct users,
causing the second user's messages to be attributed to the first user's resolved Honcho peer. This
broke #27371's per-user-peer contract in multi-user gateways. Per-user agent rebuilds in shared
threads trade prompt-cache warmth for correct memory attribution.
NÚapi_keyÚ Úbase_urlr9   Úrequested_providerÚapi_modeÚcapabilitiesT)Ú	sort_keysr5   :Né   N)ÚhashlibÚjsonrS   r;   ÚdumpsÚsha256ÚencodeÚ	hexdigestÚsortedrA   r<   )r]   r^   r_   ra   rb   rc   re   rf   rp   Ú_jÚ_api_keyÚblobs   &&&&&&&&    r   Ú_agent_config_signatureÚ.GatewayAgentCacheMixin._agent_config_signatured   s?  € ÷& 	#ô �w—{‘{ 9¨bÓ1×7Ð7°RÓ8ˆØ�x‰xàßAI�—‘˜xŸ™Ó0Ó1×;Ñ;Ô=ÈrØ—‘˜J¨Ó+¨W¯[©[¸ÀRÓ-HØ—‘Ð0°"Ó5°w·{±{À:ÈrÓ7RÜ˜Ÿ™ NÓ3×9Ð9°r×@Ñ@ÓBÓCß,<”Ð'Ô(À"à ×&Ð& BÜ˜
×(Ð( b×/Ñ/Ó1Ó2Ü�G—M�M˜rÓ"¤C¨×(9Ð(9°rÓ$:ô Ð'Ó(ðð ¤Cð! ó 
ˆð$ �~‰~˜dŸk™k›mÓ,×6Ñ6Ó8¸Õ=Ð=r    c               ó    € V ^8„  d   QhRRRR/# )r   Úsession_keyrS   r   úOptional[dict]r   )r   s   "r   r   r0   �   s   € ÷ Dñ D°3ð D¸>ñ Dr    c                ód   € V P                  V4      pV'       d   VP                  P                  # R# )zICurrent in-memory /model override for ``session_key`` (None when absent).N)Ú_peek_session_stateÚconversationÚmodel_override©Úselfr}   Ústates   && r   Ú_session_model_overrideÚ.GatewayAgentCacheMixin._session_model_override�   s+   € à×(Ñ(¨Ó5ˆß49ˆu×!Ñ!×0Ñ0ÐC¸tÐCr    c               ó    € V ^8„  d   QhRRRR/# ©r   r}   rS   r   ÚNoner   )r   s   "r   r   r0   ”   s   € ÷ 0
ñ 0
¸Sð 0
ÀTñ 0
r    c                óú  € ^ RI Hp \        V RR4      pV P                  V4      f   Vf   R#  VP	                  V4      pT'       g   R# R Uu/ uF  qUTP                  T4      bK  	  ppTP                  R4      p^ R
I	H
p T! YvP                  R	4      4      '       d   RTR	&   T'       Ed+    T! YtP                  R4      ;'       g    RR7      p	R F  pT	P                  T4      Ye&   K  	  \        T	P                  R4      ;'       g    / 4      TR&   \        T	P                  R4      ;'       g    / 4      TR&   TP                  R	4      '       d(   TP                  4       P                  4       \        9   d   T	P                  R	4      TR	&   ^ RIHp
Hp T! T4      e:   TP                  R	4      '       d#   T
! YvP                  R4      TR	,          4      TR	&   Y`P%                  T4      P&                  n        \        P+                  RYP                  R4      T;'       g    R4       R#   \
         d    \        P                  RRR7        R# i ; iu upi   \
         d    \        P                  RTRR7        L¤i ; i)a  Lazily restore a persisted /model override after a gateway restart: non-secret parts
(model/provider/base_url) are written through on /model and read back on first use; api_key
is never persisted and is re-resolved. No-op when an in-memory override or nothing exists.)Ú*_resolve_runtime_agent_kwargs_for_providerÚsession_storeNz/Failed to read persisted session model overrideT©Úexc_infor]   r9   rj   )Úis_foreign_provider_endpoint)Útarget_modelrl   Úrequest_overridesrm   )Únormalize_opencode_base_urlÚopencode_provider_familyzdCredential re-resolution failed for persisted override (provider=%s); using credential-less overridezIRehydrated persisted /model override for session=%s: model=%s provider=%sri   )r]   r9   rj   )rh   rl   Úcredential_poolrk   Ú
max_tokens)Úgateway.runrŒ   r>   r†   Úget_model_overrider?   ÚloggerÚdebugr;   Úhermes_cli.runtime_providerr�   r/   rT   Úlowerr   Úhermes_cli.modelsr“   r”   Ú_session_stater�   r‚   Úinfo)r„   r}   rŒ   ÚstoreÚ	persistedÚkÚoverrider9   r�   r^   r“   r”   s   &&          r   Ú!_rehydrate_session_model_overrideÚ8GatewayAgentCacheMixin._rehydrate_session_model_override”   s=  € õ 	KÜ˜˜o¨tÓ4ˆØ×'Ñ'¨Ó4Ò@ÀEÂMÙð	Ø×0Ñ0°Ó=ˆI÷ ÙÙAbÓ#cÑAb¸A y§}¡}°QÓ'7Ò$7ÑAbˆÐ#cØ—=‘= Ó,ˆÝLÙ'¨·,±,¸zÓ2J×KÒKØ#'ˆH�ZÑ ßˆ8ðÙDÀX×\iÑ\iÐjqÓ\r×\zÐ\zÐvzÔ{�Ûg�AØ")§+¡+¨a£.�H“Kñ hä04°W·[±[ÐATÓ5U×5[Ð5[ÐY[Ó0\�Ð,Ñ-Ü+/°·±¸NÓ0K×0QÐ0QÈrÓ+R�˜Ñ(Ø—|‘| J×/Ò/°8·>±>Ó3C×3IÑ3IÓ3KÔO_Ô3_ð ,3¯;©;°zÓ+B�H˜ZÑ(ßcÙ+¨HÓ5ÒAÀhÇlÁlÐS]×F^ÒF^ñ ,GÀx×Q]ÑQ]Ð^hÓQiÐksÐt~Õkó  ,A�H˜ZÑ(ð HP×Ñ˜KÓ(×5Ñ5ÔDÜ�‰ØWØŸ™ gÓ.°·°¸Bö	
øôG ô 	Ü�L‰LÐJÐUYˆLÔZÚð	üò
 $døô0 ô Ü—‘ðDØEMÐX\ð ö ðúsI   ®H& ÁIÂ,I ÃA I Ä&I Ä. I ÅA#I Æ3"I È&"IÉIÉ#I:É9I:c               ó(   € V ^8„  d   QhRRRRRRRR/# )r   r}   rS   r]   Úruntime_kwargsr/   r   r$   r   )r   s   "r   r   r0   Æ   s*   € ÷ %ñ %¸ð %ÀSð %ÐZ^ð %Ðchñ %r    c                ó  € ^ RI Hp V P                  V4      pV'       g   W#3# VP                  RV4      p\         F  pVP                  V4      pVf   K  WsV&   K   	  RV9   d@   VP                  R4      p\        V\        4      '       d   V'       d   \        V4      MTVR&   VP                  R4      '       dE   VP                  R4      f2   VP                  R4      '       d   V! VP                  R4      4      VR&   W#3# )z®Apply /model session overrides (precedence over config.yaml defaults; ``None`` fields skipped
so partial overrides don't clobber defaults), returning (model, runtime_kwargs).)Ú_credential_pool_for_providerr]   r’   rh   r•   r9   )r—   r©   r†   r;   Ú_OVERRIDE_APPLY_KEYSr#   r/   )	r„   r}   r]   r§   r©   r£   rF   ÚvalÚros	   &&&&     r   Ú_apply_session_model_overrideÚ4GatewayAgentCacheMixin._apply_session_model_overrideÆ   sç   € õ 	>Ø×/Ñ/°Ó<ˆßØÐ(Ð(Ø—‘˜W eÓ,ˆß'ˆCØ—,‘,˜sÓ#ˆCØŒØ&)˜sÓ#ñ (ð  (Ô*Ø—‘Ð1Ó2ˆBÜ>HÈÌT×>RÒ>R×WY´$°r´(Ð_aˆNÐ.Ñ/à×Ñ˜y×)Ò)Ø×"Ñ"Ð#4Ó5Ò=Ø—‘˜Z×(Ò(á0MÈhÏlÉlÐ[eÓNfÓ0gˆNÐ,Ñ-ØÐ$Ð$r    c               ó    € V ^8„  d   QhRRRR/# )r   r}   rS   r   r/   r   )r   s   "r   r   r0   à   s   € ÷ tñ t¸Cð tÀDñ tr    c                óT   € V P                  V4      pRVRJRVe   \        V4      /# R/# )z<Capture a gateway session override before a one-turn switch.Úhad_overrideNr£   )r†   r/   )r„   r}   r£   s   && r   Ú _snapshot_session_model_overrideÚ7GatewayAgentCacheMixin._snapshot_session_model_overrideà   s9   € à×/Ñ/°Ó<ˆØ °Ð 4°jÐT\ÒThÄ$ÀxÃ.ÐsÐsÐnrÐsÐsr    c               ó$   € V ^8„  d   QhRRRRRR/# )r   r}   rS   Úsnapshotr~   r   rŠ   r   )r   s   "r   r   r0   å   s'   € ÷ Cñ C°3ð CÀ.ð CÐ\`ñ Cr    c                ó®   € V P                  V4      P                  pVP                  '       g(   Ve   \        V4      MV P	                  V4      Vn        R# R# )a…  Arm the one-shot restore snapshot for ``/model --once`` / ``/moa``. A repeated one-shot
command before the turn runs keeps the EARLIEST snapshot: the later command's snapshot is
the first temporary model, not the user's standing override. Pass *snapshot* when the
caller captured the pre-switch state earlier (``/model --once`` applies its override before
arming); omit it to snapshot now.N)rž   r�   Úone_turn_restorer/   r²   )r„   r}   rµ   Úconvs   &&& r   Ú_claim_one_turn_restoreÚ.GatewayAgentCacheMixin._claim_one_turn_restoreå   sS   € ð ×"Ñ" ;Ó/×<Ñ<ˆØ×$×$Ð$Ø6>Ò6J¤D¨¤NÐPT×PuÑPuð  wBó  QCˆDÖ!ñ %r    c               ó$   € V ^8„  d   QhRRRRRR/# )r   r}   rS   rµ   r/   r   rŠ   r   )r   s   "r   r   r0   ï   s"   € ÷ .ñ .¸3ð .È$ð .ÐSWñ .r    c                ó<  € V'       g   R# VP                  R4      '       dD   \        VP                  R4      ;'       g    / 4      V P                  V4      P                  n        M&V P                  V4      ;pe   RVP                  n        V P                  V4       R# )z?Restore the session override captured before a one-turn switch.Nr±   r£   )r;   r/   rž   r�   r‚   r€   Ú_evict_cached_agent)r„   r}   rµ   r…   s   &&& r   Ú_restore_session_model_overrideÚ6GatewayAgentCacheMixin._restore_session_model_overrideï   s}   € çÙØ�<‰<˜×'Ò'ÜKOÐPX×P\ÑP\Ð]gÓPh×PnÐPnÐlnÓKoˆD×Ñ Ó,×9Ñ9ÕHØ×/Ñ/°Ó<Ð<ˆeÒIØ04ˆE×ÑÔ-Ø× Ñ  Ö-r    c               ó(   € V ^8„  d   QhRRRRRRRR/# )r   r}   rS   Úagentr   Úconfig_modelr   r<   r   )r   s   "r   r   r0   ù   s0   € ÷ 	Yñ 	Y¸ð 	YÀCð 	YÐWZð 	YÐ_cñ 	Yr    c                ó¦   € V P                  V4      pVe#   VP                  R4      VP                  8X  d   R# \        VRR4      W2P                  38H  # )a  True when *agent* running a model other than *config_model* is deliberate: a /model session
override names that model, or the Nous gateway moved the session off the ``nous/welcome``
alias that *config_model* still carries (``anon_auth.apply_model_switch``).Nr]   TÚ_nous_model_switch)r†   r;   r]   r>   )r„   r}   rÁ   rÂ   r£   s   &&&& r   Ú_is_intentional_model_switchÚ3GatewayAgentCacheMixin._is_intentional_model_switchù   sO   € ð ×/Ñ/°Ó<ˆØÒ H§L¡L°Ó$9¸U¿[¹[Ô$HÙô �uÐ2°DÓ9¸lÏKÉKÐ=XÑXÐXr    Úpolicy_modelc          
     ó,   € V ^8„  d   QhRRRRRRRRR	R/# )
r   r}   rS   ÚsourcezOptional[SessionSource]rÁ   r   rÇ   úOptional[str]r   r   )r   s   "r   r   r0     s3   € ÷ "ñ "°Cð "ÐAXð "Ðadð "Ø2?ð"ØKNñ"r    c               óð  € ^ RI Hp \        VRR4      ;'       g    / pVP                  R\        VRR4      4      ;'       g    RpV P	                  V4      ;'       g    / pVP                  R4      '       d$   VP                  R4      RRV39   d   VR,          p	M­V'       d   Tp	M¢Ve˜   T P                  VP                  VP                  '       d   \        VP                  4      MR\        VRR4      '       d   \        VP                  4      MR\        VRR4      '       d   \        VP                  4      MRR	7      p	MV! 4       p	\        \        4      ;_uu_ 4        ^ R
IHp
Hp V'       d   Wz9  d	   V! W—4      p	RRR4       \        \        4      ;_uu_ 4        ^ RIHp V! WvP                  R\        VRR4      4      V	4      p	RRR4       V	#   + '       g   i     L\; i  + '       g   i     T	# ; i)a•  The model *agent* was built to run, for the post-turn fallback check: what
``_resolve_session_agent_runtime`` chose (session /model, then a LOCAL session's frozen launch
policy model, then channel_overrides on the chat, thread or parent, then the global model),
canonicalized as ``AIAgent.__init__`` did on the agent's PRIMARY route. The route a fallback
moved it to would make that fallback look primary.)Ú_resolve_gateway_modelÚ_primary_runtimeNr9   ri   r]   Ú	thread_idÚparent_chat_id)rÎ   Ú	parent_id)Ú_AGGREGATOR_PROVIDERSÚnormalize_model_for_provider)Úpin_model_for_routerj   )r—   rÌ   r>   r;   r†   Ú_resolve_model_for_channelÚplatformÚchat_idrS   rÎ   rÏ   r   r?   Úhermes_cli.model_normalizerÑ   rÒ   Úhermes_cli.anon_authrÓ   )r„   r}   rÉ   rÁ   rÇ   rÌ   Úprimaryr9   r£   r]   rÑ   rÒ   rÓ   s   &&&&$        r   Ú_fallback_baseline_modelÚ/GatewayAgentCacheMixin._fallback_baseline_model  s‘  € õ 	7Ü˜%Ð!3°TÓ:×@Ð@¸bˆØ—;‘;˜z¬7°5¸*ÀbÓ+IÓJ×PÐPÈbˆà×/Ñ/°Ó<×BÐBÀˆØ�<‰<˜× Ò  X§\¡\°*Ó%=À$ÈÈHÐAUÔ%UØ˜WÕ%‰EßØ ‰EØÒØ×3Ñ3Ø—‘¸¿¿¸¤ V§^¡^Ô!4ÈBÜ3:¸6À;ÐPT×3UÒ3Uœ#˜f×.Ñ.Ô/Ð[_Ü8?ÀÐHXÐZ^×8_Ò8_œ#˜f×3Ñ3Ô4Ðeið 4ó ‰Eñ +Ó,ˆEô ”i× Õ ßfß˜HÔAÙ4°UÓE�÷ !ô
 ”i× Õ Ý@Ù'¨·+±+¸jÌ'ÐRWÐYcÐeiÓJjÓ2kÐmrÓsˆE÷ !ð ˆ÷ !× ú÷
 !Ö ð ˆús   ÅGÆ+G$ÇG!	Ç$G5	Úrun_generationc               ó$   € V ^8„  d   QhRRRRRR/# )r   r}   rS   rÜ   úOptional[int]r   r<   r   )r   s   "r   r   r0   (  s$   € ÷ ñ ØðØ3@ðà	ñr    c          	     ó`  € V'       d   Ve   V P                  W4      '       g   R# V P                  V4      pVe¼   VP                  P                  e&    VP                  P                  P	                  4        VP                  P                  4        VP                  P                  . uqCP                  n	        V F7  pV P                  V P                  V3R\        V4      R,           2RVR7       K9  	  V P                  4        R#   \
         d    \        P                  RRR7        L´i ; i)uS  Pop ALL per-running-agent state for ``session_key`` (call at every site that ends a running
turn); True when cleared. Persistent state (model overrides, voice mode, approvals) is NOT
touched. With ``run_generation``, only clear if still current â€” a stale async unwind bumped
by /stop or /new must not clobber a newer run (returns False).Fz%Failed to release active session slotTrŽ   zagent-retire-ºNé   N©Úinline_fallbackr}   )Ú_is_session_run_currentr€   ÚturnÚleaseÚreleaser?   r™   rš   ÚclearÚretired_agentsÚ_spawn_release_threadÚ_release_evicted_agent_softrS   Ú_persist_active_agents)r„   r}   rÜ   r…   ÚretiredrÁ   s   &&$   r   Ú_release_running_agent_stateÚ3GatewayAgentCacheMixin._release_running_agent_state(  s
  € ÷ ØÒ&¨t×/KÑ/KÈK×/hÒ/háØ×(Ñ(¨Ó5ˆØÒØ�z‰z×ÑÒ+ðYØ—J‘J×$Ñ$×,Ñ,Ô.ð
 �J‰J×ÑÔØ16·±×1JÑ1JÈBÐ.ˆG—Z‘ZÔ.Û �à×*Ñ*¨4×+KÑ+KÈeÈXØ-:¼3¸{Ó;KÈCÕ;PÐ:QÐ+RÐdhØ7Bð +ö Dñ !ð 	×#Ñ#Ô%Ùøô !ô YÜ—L‘LÐ!HÐSW�LÖXðYús   Á$D Ä"D-Ä,D-c               ó$   € V ^8„  d   QhRRRRRR/# )r   r}   rS   rÜ   rÞ   r   rŠ   r   )r   s   "r   r   r0   H  s"   € ÷ ,ñ ,¨3ð ,À=ð ,Ð\`ñ ,r    c          	     ó  € V P                  WR7       V P                  V4       V P                  V4      p\        V RR4      pVe   Vf   R# \	        VP
                  P                  ;'       g    ^ 4      pVP                  P                  pV Uu. uF  p\	        V4      V8  g   K  VNK  	  up F&  pVP                  V4      p	 VP                  V	4       K(  	  R# u upi   \         d    \        P                  RY�RR7        KW  i ; i)aÓ  Release the running-agent slot and evict the cached instance (/stop, eviction, reaper).
``_interrupt_requested`` is cleared only by the turn finalizer, so on a hung/still-draining
run the flag would survive and silently kill the session's NEXT message (interrupted=True,
api_calls=0, empty response); the next message rebuilds from history while the old agent
keeps its flag so a hung drain still dies (#44212). With ``run_generation`` (the post-bump
value ``_interrupt_running_turn`` returns), the release is generation-guarded: an async
path awaits between bump and release, so a successor claiming the slot in that window must
not have its sentinel/lease wiped by the displaced path's tail. Then sweep lease tokens
from generations OLDER than the current one: a hung evicted turn's finalizer may never run,
and each such generation would otherwise pin its token (and its ``_SessionLease``) forever.
Identity-checked + idempotent, so a live successor's token is never affected.©rÜ   Ú_turn_leasesNz4Failed to release displaced turn lease gen %s for %sTrŽ   )rî   r½   r€   r>   ÚintÚ
persistentrÜ   rå   Úlease_tokensÚpoprç   r?   r™   rš   )
r„   r}   rÜ   r…   r6   ÚcurrentÚtokensÚgÚgenÚtokens
   &&$       r   Ú_drop_turn_slotÚ&GatewayAgentCacheMixin._drop_turn_slotH  sï   € ð 	×)Ñ)¨+Ð)ÔUØ× Ñ  Ô-Ø×(Ñ(¨Ó5ˆÜ˜4 °Ó6ˆØŠ=˜HÒ,ÙÜ�e×&Ñ&×5Ñ5×:Ð:¸Ó;ˆØ—‘×(Ñ(ˆÙ%Ó:™v˜!¬¨Q«°'Ñ)9—A�A™vÔ:ˆCØ—J‘J˜s“OˆEð,Ø× Ñ  Ö'ó ;ùÒ:øô ô ,Ü—‘ÐSÐUXØ&*ð ÷ ,ð,ús   ÂCÂ&CÃC Ã #DÄDc               ó    € V ^8„  d   QhRRRR/# )r   r}   rS   rÜ   rô   r   )r   s   "r   r   r0   d  s   € ÷  ñ  ¨Cð  Àñ  r    c                ó°   € \        V RR4      pV'       d   Ve   V P                  V4      MRpVe   VP                  P                  MRpVe   W%9  d   R# W53# )zªReturn ``(registry, lease_tokens)`` when ``session_key`` holds a lease token for
``run_generation``, else None. Callers ``get``/``pop`` the token from the map themselves.ró   N)r>   r€   rå   rö   )r„   r}   rÜ   r6   r…   rù   s   &&&   r   Ú_held_turn_leaseÚ'GatewayAgentCacheMixin._held_turn_leased  sX   € ô ˜4 °Ó6ˆß9DÈÒI]�×(Ñ(¨Ô5ÐcgˆØ,1Ò,=�—‘×(Ò(À4ˆØŠ>˜^Ô9ÙØÐÐr    c               ó$   € V ^8„  d   QhRRRRRR/# )r   r}   rS   rÜ   rô   r   r<   r   )r   s   "r   r   r0   n  s!   € ÷ ñ ¨sð ÀCð ÈDñ r    c                óÐ   € V P                  W4      pVf   R# Vw  rEVP                  V4      p VP                  V4      #   \         d    \        P                  RRR7        R# i ; i)zíRelease the turn lease acquired by (``session_key``, ``run_generation``). Keyed by (routing
key, run generation) so a stale unwind pops only ITS token; the registry's identity check
refuses it if a newer turn holds the lease. Idempotent.FzFailed to release turn leaseTrŽ   )r  r÷   rç   r?   r™   rš   )r„   r}   rÜ   Úheldr6   rù   rü   s   &&&    r   Ú_release_turn_leaseÚ*GatewayAgentCacheMixin._release_turn_leasen  sk   € ð ×$Ñ$ [ÓAˆØŠ<ÙØÑˆØ—
‘
˜>Ó*ˆð	Ø×#Ñ# EÓ*Ð*øÜô 	Ü�L‰LÐ7À$ˆLÔGÚð	ús   ®? ¿"A%Á$A%c               ó(   € V ^8„  d   QhRRRRRRRR/# )r   r}   rS   rÜ   rô   Únew_session_idr   r<   r   )r   s   "r   r   r0   }  s*   € ÷ ñ ¨cð À3ð ÐX[ð Ð`dñ r    c                óÐ   € V'       d   V P                  W4      MRpVf   R# Vw  rV VP                  Wb,          V4      #   \         d    \        P	                  RRR7        R# i ; i)zÞFollow a mid-turn session_id rotation (compression) with the held turn lease, or an alias
key resolving the new id could start a concurrent turn the lease never sees. Call at every
mid-turn reassignment; no-op if no token.NFzFailed to rebind turn leaseTrŽ   )r  Úrebindr?   r™   rš   )r„   r}   rÜ   r	  r  r6   rù   s   &&&&   r   Ú_rebind_turn_leaseÚ)GatewayAgentCacheMixin._rebind_turn_lease}  sg   € ÷ FTˆt×$Ñ$ [ÔAÐY]ˆØŠ<ÙØÑˆð	Ø—?‘? 6Õ#9¸>ÓJÐJøÜô 	Ü�L‰LÐ6ÀˆLÔFÚð	ús   §? ¿"A%Á$A%c               ó$   € V ^8„  d   QhRRRRRR/# )r   r}   rS   Úreasonr   rŠ   r   )r   s   "r   r   r0   ‹  s&   € ÷ Tñ T°Sð TÀSð TÈTñ Tr    c               ón  € ^ RI Hp V'       g   R# V P                  V4      pVe   VP                  P	                  4        ^ RIHp V! VR4       V F9  p\        WR4      p\        V\        4      '       g   K'  VP                  VR4       K;  	  V P                  V4       \        P                  RW4       R# )u‡  THE single conversation-boundary funnel (/new, /resume, suspension replacement,
compression-exhausted reset). New conversation-scoped dicts go in _CONVERSATION_SCOPED_STATE
so every boundary picks them up. Turn-scoped state (_running_agents/_ts, slot leases, turn-
lease tokens) is owned by _release_running_agent_state and NOT cleared. Idle agent-cache
eviction is NOT a boundary (a resumed turn rebuilds from these). getattr-guarded.

Why a funnel: these boundaries used to each carry a hand-copied pop-list of the per-session dicts,
and the lists drifted every time a new dict was added (#48031, #58403, #10702, #35809 were all
"boundary X forgot dict Y" bugs â€” e.g. /new cleared the /model override but not the /model --once
restore snapshot). Adding a new conversation-scoped dict now means adding its attribute name to
_CONVERSATION_SCOPED_STATE below; every boundary picks it up automatically.
)Ú_CONVERSATION_SCOPED_STATEN)Úset_session_backendz&Cleared conversation scope for %s (%s))r—   r  r€   r�   rè   Úagent.delegation_backendsr  r>   r#   r/   r÷   Ú&_clear_session_boundary_security_stater™   rš   )r„   r}   r  r  r…   r  Úattrr    s   &&$     r   Ú_clear_conversation_scopeÚ0GatewayAgentCacheMixin._clear_conversation_scope‹  s”   € õ 	;ßÙØ×(Ñ(¨Ó5ˆØÒØ×Ñ×$Ñ$Ô&åAÙ˜K¨Ô.ó /ˆDÜ˜D¨Ó-ˆEÜ˜%¤×&Ô&Ø—	‘	˜+ tÖ,ñ /ð 	×3Ñ3°KÔ@Ü�‰Ð=¸{ÖSr    c               ó    € V ^8„  d   QhRRRR/# r‰   r   )r   s   "r   r   r0   «  s   € ÷ uñ uÀ#ð uÈ$ñ ur    c                ó‚  € V'       g   R# \        V RR4      p\        V\        4      '       d   VP                  VR4       V P	                  V4      pVe#   RVP
                  n        RVP
                  n        R	 F0  w  rEp \        \        P                  ! V4      V4      p T! T4       K2  	  \        V RR4      p	V	e    V	P                  VR4       R# R#   \         d     Kj  i ; i  \         d#   p\        P                  RYaT4        Rp?K–  Rp?ii ; i  \         d    \        P                  RTRR7        R# i ; i)
zHClear per-session control state that must not survive a boundary switch.NÚ_pending_skills_reload_notesFz4Failed to clear %s state for session boundary %s: %sr�   z6Failed to clear persisted yolo for session boundary %sTrŽ   ))ztools.slash_confirmrè   zslash-confirm)ztools.approvalÚclear_sessionÚapproval)r>   r#   r/   r÷   r€   rõ   Ú	approvalsÚupdate_prompt_pendingÚ	importlibÚimport_moduler?   r™   rš   Úset_session_yoloÚwarning)
r„   r}   Úpending_skills_reload_notesr…   Úmodr  Úwhatrè   Úer    s
   &&        r   r  Ú=GatewayAgentCacheMixin._clear_session_boundary_security_state«  s8  € çÙÜ&-¨dÐ4RÐTXÓ&YÐ#ÜÐ1´4×8Ò8Ø'×+Ñ+¨K¸Ô>Ø×(Ñ(¨Ó5ˆØÒØ)-ˆE×ÑÔ&Ø5:ˆE×ÑÔ2ó 
‰OˆC�tðÜ¤	× 7Ò 7¸Ó <¸dÓC�ðkÙ�kÖ"ñ 
ô ˜˜o¨tÓ4ˆØÒðuØ×&Ñ& {°DÖ9ñ øô ô Úðûô ô kÜ—‘ÐSÐUYÐhi×jÒjûðkûô ô uä—‘ÐWÐYdÐos�×tðuús<   Â  CÂ!C'Â?D ÃC$Ã#C$Ã'DÃ2DÄDÄ#D>Ä=D>c               ó    € V ^8„  d   QhRRRR/# ©r   r}   rS   r   rô   r   )r   s   "r   r   r0   Ì  s   € ÷ )ñ )¸ð )Àñ )r    c                ó¦   € V'       g   ^ # V P                  V4      P                  p\        VP                  4      ^,           Vn        VP                  # )zœClaim a fresh, monotonically increasing run generation token (NEVER reset): a late result
from a worker /stop or /new invalidated is recognized and dropped.)rž   rõ   rô   rÜ   )r„   r}   rõ   s   && r   Ú_begin_session_run_generationÚ4GatewayAgentCacheMixin._begin_session_run_generationÌ  sD   € ÷ ÙØ×(Ñ(¨Ó5×@Ñ@ˆ
ä$'¨
×(AÑ(AÓ$BÀQÕ$Fˆ
Ô!Ø×(Ñ(Ð(r    r  ri   c               ó$   € V ^8„  d   QhRRRRRR/# )r   r}   rS   r  r   rô   r   )r   s   "r   r   r0   Ö  s"   € ÷ 	ñ 	¸cð 	Ècð 	Ð[^ñ 	r    c               óˆ   € V P                  V4       V P                  V4      pV'       d   \        P                  RWV4       V# )zßInvalidate any in-flight run token for ``session_key``.

Settles a pending one-shot model override first: the displaced turn's finalizer is
generation-guarded and would otherwise leave ``/moa`` / ``/model --once`` in force.u-   Invalidated run generation for %s â†’ %d (%s))Ú(_restore_pending_one_turn_model_overrider+  r™   rŸ   )r„   r}   r  Ú
generations   &&$ r   Ú"_invalidate_session_run_generationÚ9GatewayAgentCacheMixin._invalidate_session_run_generationÖ  s=   € ð
 	×5Ñ5°kÔBØ×7Ñ7¸ÓDˆ
ßÜ�K‰KÐGÈÐbhÔiØÐr    c               ó    € V ^8„  d   QhRRRR/# r)  r   )r   s   "r   r   r0   á  s   € ÷ Pñ P¸3ð PÀ3ñ Pr    c                ón   € V P                  V4      pVe    \        VP                  P                  4      # ^ # )zJCurrent run generation for ``session_key`` (0 when the key tracks no run).)r€   rô   rõ   rÜ   rƒ   s   && r   Ú_current_session_run_generationÚ6GatewayAgentCacheMixin._current_session_run_generationá  s3   € à×(Ñ(¨Ó5ˆØ7<Ò7HŒs�5×#Ñ#×2Ñ2Ó3ÐOÈaÐOr    c               ó$   € V ^8„  d   QhRRRRRR/# )r   r}   rS   r0  rô   r   r<   r   )r   s   "r   r   r0   æ  s&   € ÷ Tñ T°3ð TÀCð TÈDñ Tr    c                óP   € V'       g   R# V P                  V4      \        V4      8H  # )zEReturn True when ``generation`` is still current for ``session_key``.T)r5  rô   )r„   r}   r0  s   &&&r   rä   Ú.GatewayAgentCacheMixin._is_session_run_currentæ  s"   € çÙØ×3Ñ3°KÓ@ÄCÈ
ÃOÑSÐSr    c               ó(   € V ^8„  d   QhRRRRRRRR/# )	r   Úadapterr   r}   rS   r0  z
int | Noner   rŠ   r   )r   s   "r   r   r0   ì  s0   € ÷ Iñ I°Cð IÀcð IÐWað IÐfjñ Ir    c                óú   € V'       d   V'       d   Vf   R# \        \        4      ;_uu_ 4        \        VR/ 4      P                  V4      pVe   \	        V4      Vn        RRR4       R#   + '       g   i     R# ; i)zDBind a gateway run generation to the adapter's active-session event.NÚ_active_sessions)r   r?   r>   r;   rô   Ú_hermes_run_generation)r„   r;  r}   r0  Úinterrupt_events   &&&& r   Ú_bind_adapter_run_generationÚ3GatewayAgentCacheMixin._bind_adapter_run_generationì  sU   € çŸk¨ZÒ-?ÙÜ”i× Õ Ü% gÐ/AÀ2ÓF×JÑJÈ;ÓWˆOØÒ*Ü9<¸Z»�Ô6÷ !× × Ò ús   ®1A)Á)A:	Útool_reasonc          
     ó,   € V ^8„  d   QhRRRRRRRRRR/# )	r   r}   rS   Úinterrupt_reasonÚinvalidation_reasonrB  rd   r   rô   r   )r   s   "r   r   r0   õ  s4   € ÷ $(ñ $(Øð$(Ø58ð$(ØORð$(Øakð$(à	ñ$(r    c          
     óR  a aa€ ^ RI Hp ^ RIHpHpHp S P                  S4      p	V	'       d   V	P                  P                  MRp
RRrËV
'       dX   W¦JdS   \        \        P                  RSRR7      ;_uu_ 4        V! W¢VR7       RRR4       \        V
R	R4      p\        V
R
R4      pS P                  SVR7      oV'       dS   VeO   \        P                  ! V! 4       P                   W{V3RRRVV V3R l/RVR,           2RR7      P#                  4        S#   + '       g   i     L™; i)a7  Sync core shared by /stop, /new and eviction: request a hard interrupt on the in-flight
agent, invalidate its run generation, and reap the tool processes that turn spawned.
``tool_reason`` names a system issuer (eviction); ``None`` keeps the user attribution of /stop and /new.
Returns the post-bump generation.)Úcopy_context)Ú_AGENT_PENDING_SENTINELÚ_reap_gateway_turn_processesÚrequest_hard_interruptNri   z4Failed to interrupt running agent for %s; continuingTrŽ   )rB  Ú_gateway_turn_process_task_idÚ_gateway_turn_process_baseline)r  rÉ   Úgateway_turn_interruptÚis_still_currentc                 ó(   <€ SP                  SS 4      # ©N)rä   )Ú_generation_at_interruptr„   r}   s   €€€r   Ú<lambda>Ú@GatewayAgentCacheMixin._interrupt_running_turn.<locals>.<lambda>  s   ø€ °×0LÑ0LÈ[ÐZrÔ0sr    zgateway-turn-reaper-:Né   N)ÚtargetÚargsÚkwargsrX   Údaemon)ÚcontextvarsrG  r—   rH  rI  rJ  r€   rå   rÁ   r   ÚloggingÚWARNINGr>   r1  Ú	threadingÚThreadÚrunÚstart)r„   r}   rD  rE  rB  rG  rH  rI  rJ  r…   Úrunning_agentÚ_process_task_idÚ_process_baselinerQ  s   ff$$$        @r   Ú_interrupt_running_turnÚ.GatewayAgentCacheMixin._interrupt_running_turnõ  s  ú€ õ 	-ßmÑmØ×(Ñ(¨Ó5ˆß,1˜Ÿ
™
×(Ò(°tˆØ.0°$Ð+ß˜]ÓIô !¤§¡Ð2hØ!,°t÷=ö =á& }ÐT_Õ`÷=ô  ' }Ð6UÐWYÓZÐÜ '¨Ð7WÐY]Ó ^Ðð
 $(×#JÑ#JÈ;Ð_rÐ#JÓ#sÐ ßÐ 1Ò =Ü×ÒÙ#“~×)Ñ)Ø2ÐFWÐXàÐ6Ø&Ö(sðð ,Ð,<¸SÕ,AÐ+BÐCØô	÷ ‰eŒgØ'Ð'÷+=÷ =ús   Á:DÄD&	Úrelease_running_stateTc               ó0   € V ^8„  d   QhRRRRRRRRRRR	R
/# )r   r}   rS   rÉ   r   rD  rE  re  r<   r   rŠ   r   )r   s   "r   r   r0     sN   € ÷ DWñ DWØðDWØ(5ðDWØLOðDWà ðDWà9=ðDWð 
ñDWr    c             ƒ  óò  "  € V'       g   R# V P                  V4      pV'       d   VP                  P                  MRpV P                  WVR7      p^ RIHp	 ^ RIHp
 T
! Y\        \        VRR4      ;'       g    R4      R7       V'       dB   WyJd=    ^ RI
Hp T! R	TVP                  '       d   VP                  P                  MRVVR
7       V P#                  V4      p\        \%        V4      RR4      pV'       d~   \'        V4      '       dm   V P)                  V4      p\+        VR4      '       d'   VP-                  WP.                  VR7      G Rj  x€L
  M#VP-                  WP.                  4      G Rj  x€L
  V'       d•   \1        VR4      '       dƒ   VP3                  V4      p\        VRR4      '       d   TMRpVfD   V P5                  V4      ;'       g    . p\7        R V 4       R4      pVe   VP9                  V4       Ve   VVP:                  V&   Ve   RVP<                  n        V'       d   V PA                  WR7       R# R#   \         d    \        P!                  RRR7        EL i ; i EL! Lÿ5i)zFInterrupt the current run and clear queued session state consistently.N)rD  rE  ©rH  )Úinterrupt_for_sessionÚ
session_idri   )r}   r  Úparent_session_id)Úinvoke_hookÚagent_loop_stopped)r}   rÕ   r  rE  z'agent_loop_stopped hook dispatch failedTrŽ   Úinterrupt_session_activityÚmetadata)ro  Úget_pending_messageÚinternalFc              3  óP   "  € T F  p\        VR R4      '       g   K  Vx € K  	  R# 5i)rq  FN)r>   )Ú.0r&  s   & r   Ú	<genexpr>ÚFGatewayAgentCacheMixin._interrupt_and_clear_session.<locals>.<genexpr>U  s   é € ÐR© 1´G¸A¸zÈ5×4QŸQšQ«ùs   ‚&œ
&rò   )!r€   rå   rÁ   rc  r—   rH  Útools.async_delegationri  rS   r>   Úhermes_cli.pluginsrl  rÕ   rH   r?   r™   rš   Ú_delivery_adapter_forÚtypeÚcallableÚ_thread_metadata_for_sourcer   rn  rÖ   Úhasattrrp  Ú_overflow_queueÚnextÚremoveÚ_pending_messagesrõ   Úpending_command_textrý   )r„   r}   rÉ   rD  rE  re  r…   r`  rQ  rH  ri  Ú_invoke_hookr;  rn  ro  ÚparkedÚwakeÚoverflows   &&&$$$            r   Ú_interrupt_and_clear_sessionÚ3GatewayAgentCacheMixin._interrupt_and_clear_session  s0  é € ÷
 ÙØ×(Ñ(¨Ó5ˆß,1˜Ÿ
™
×(Ò(°tˆØ#'×#?Ñ#?ØÐPcð $@ó $
Ð õ 	8õ 	AÙØ#Ü!¤'¨-¸ÀrÓ"J×"PÐ"PÈbÓQõ	S÷ ˜]ÓIð
WÝJáØ(Ø +Ø6<·o·o°o˜VŸ_™_×2Ò2È2Ø+Ø(;õð ×,Ñ,¨VÓ4ˆÜ%,¬T°'«]Ð<XÐZ^Ó%_Ð"ß”xÐ :×;Ò;Ø×7Ñ7¸Ó?ˆHÜÐ :¸J×GÒGØ×8Ñ8¸ÇnÁnÐ_gÐ8Óh×hÑhà×8Ñ8¸ÇnÁnÓU×UÐUß”w˜wÐ(=×>Ò>ð ×0Ñ0°Ó=ˆFÜ$ V¨Z¸×?Ò?‘6ÀTˆDØŠ|Ø×/Ñ/°Ó<×BÐBÀ�ÜÑR©ÓRÐTXÓY�ØÒ#Ø—O‘O DÔ)ØÒØ9=�×)Ñ)¨+Ñ6ØÒØ48ˆE×ÑÔ1ß ð × Ñ  Ð ÖVñ !øô= ô WÜ—‘ÐFÐQU�×VðWúò iáUùsn   ‚#I7¦A&I7ÂI7ÂI	 Â/I	 ÃBI7ÅI2Å#I7Å5I5Å6I7ÆAI7ÇAI7È3I7É	"I/É+I7É.I/É/I7É5I7c               ó$   € V ^8„  d   QhRRRRRR/# )r   r}   rS   rj  rÊ   r   rŠ   r   )r   s   "r   r   r0   a  s(   € ÷  vñ  vÀCð  vÐUbð  vÐgkñ  vr    c              ƒ  óø  "  € ^ RI Hp \        V RR4      p\        V RR4      pV P                  e   V'       d   V'       d   Vf   R#  V P                  P	                  V4      G Rj  x€L
 pV'       d   VP                  R^ 4      MRpTf   R# T;_uu_ 4        TP                  T4      p\        T\        4      '       d   \        T4      ^8”  d   T^ ,          TJg    RRR4       R# \        T4      ^8”  d
   T^,          MRp	T	e   Y’8w  g   T^,          T8X  d    RRR4       R# T^ ,          T^,          T3T	f   RMT	3,           YQ&   RRR4       R#  Lë  \         d     R# i ; i  + '       g   i     R# ; i5i)uç  Re-baseline a cached agent's stored message_count after THIS turn â€” the coherence guard
rebuilds on mismatch, so without this every turn would rebuild and destroy prompt caching.
Only the count is refreshed, only if the same agent is still cached. DB errors leave the
snapshot as-is (one spare rebuild).

But the snapshot is taken at agent-BUILD time â€” before this turn writes its own user + assistant (+
tool) rows â€” and the cache entry is never rewritten on a reuse. See #45966.
rh  Ú_agent_cache_lockNÚ_agent_cacheÚmessage_countr   )
r—   rH  r>   Ú_session_dbÚget_sessionr;   r?   r#   r$   Úlen)
r„   r}   rj  rH  Ú_cache_lockÚ_cacheÚ	_sess_rowÚ_liveÚcachedÚ_snapshot_sids
   &&&       r   Ú"_refresh_agent_cache_message_countÚ9GatewayAgentCacheMixin._refresh_agent_cache_message_counta  sF  é € õ 	8Ü˜dÐ$7¸Ó>ˆÜ˜˜~¨tÓ4ˆØ×ÑÒ#¯:¿[ÈFÊNÙð	Ø"×.Ñ.×:Ñ:¸:ÓF×FˆIß9B�I—M‘M /°1Ô5ÈˆEð Š=ÙßŠ[Ø—Z‘Z Ó,ˆFô ˜v¤u×-Ò-´#°f³+À´/ÀfÈQÅiÐWnÓFnØ÷ ‰[ô *-¨V«°q¬˜F 1žI¸dˆMØÒ)¨mÔ.IÈfÐUVÍiÐ[`ÔN`Ø÷ ‰[ð $*¨!¥9¨f°Q­i¸Ð"?ÈÒI^Á2ÐerÐdtÕ"uˆFÑ÷ ‰[ñ Gøäô 	Úð	ú÷ �[ˆ[üs}   ‚6E:¹E:ÁE:ÁE Á&EÁ'E Á3E ÂE:ÂAE&Ã
E:Ã'4E&Ä
E:Ä%#E&Å
E:ÅE ÅE#ÅE:Å"E#Å#E:Å&E7	Å1	E:c               ó$   € V ^8„  d   QhRRRRRR/# )r   r}   rS   Únotesú	list[str]r   rŠ   r   )r   s   "r   r   r0   ƒ  s'   € ÷ Rñ R¸3ð RÀyð RÐUYñ Rr    c                ó|   € V'       d	   V'       g   R# \        V4      V P                  V4      P                  n        R# )zDStage per-turn must-deliver notes for the next agent run (one-shot).N)r`   rž   r�   Úsidecar_notes)r„   r}   r™  s   &&&r   Ú_set_pending_turn_sidecar_notesÚ6GatewayAgentCacheMixin._set_pending_turn_sidecar_notesƒ  s'   € ç§%ÙÜFJÈ5Ãkˆ×Ñ˜KÓ(×5Ñ5ÖCr    c               ó    € V ^8„  d   QhRRRR/# )r   r}   rS   r   rš  r   )r   s   "r   r   r0   ‰  s   € ÷ @ñ @¸sð @Àyñ @r    c                	óØ   € V'       d   V P                  V4      MR pVf   . # VP                  P                  . uq2P                  n        \        V\        4      '       d   \	        V4      # . # rP  )r€   r�   rœ  r#   r`   )r„   r}   r…   Ústageds   &&  r   Ú#_consume_pending_turn_sidecar_notesÚ:GatewayAgentCacheMixin._consume_pending_turn_sidecar_notes‰  s[   € ß9D�×(Ñ(¨Ô5È$ˆØŠ=ØˆIØ38×3EÑ3E×3SÑ3SÐUWÐ0ˆ×"Ñ"Ô0Ü)¨&´$×7Ò7Œt�F‹|Ð?¸RÐ?r    c               ó$   € V ^8„  d   QhRRRRRR/# )r   rÉ   r   r}   rS   r   rÊ   r   )r   s   "r   r   r0   �  s(   € ÷ Vñ V¸ð VÐUXð VÐ]jñ Vr    c                ó  € VP                   \        P                  8w  d   R# V P                  V4      pV P	                  V4      pV'       d   V'       d   \        VR4      '       g   R#  VP                  V4      ;'       g    RpRpT'       d9   T P                  T4      pTP                  P                  TuqxP                  n        Yge   TMR8X  d   R# RT;'       g    R R	2#   \         d    \        P                  RRR7        R# i ; i)
zŠ``[Voice channel now: ...]`` note when VC state changed; ``None`` when unchanged so per-turn
member/speaking churn can't touch the prompt.NÚget_voice_channel_contextri   z!voice-channel context read failedTrŽ   z[Voice channel now: z not connected to a voice channelÚ])rÕ   r   ÚDISCORDrx  Ú_get_guild_idr|  r¦  r?   r™   rš   rž   r�   Úvc_last)	r„   ÚeventrÉ   r}   r;  Úguild_idÚvc_nowÚvc_prevÚ	_vc_states	   &&&&     r   Ú_voice_channel_sidecar_noteÚ2GatewayAgentCacheMixin._voice_channel_sidecar_note�  sô   € ð �?‰?œh×.Ñ.Ô.ÙØ×,Ñ,¨VÓ4ˆØ×%Ñ% eÓ,ˆßŸW¬°Ð:U×)VÒ)VÙð	Ø×6Ñ6°xÓ@×FÐFÀBˆFð ˆßØ×+Ñ+¨KÓ8ˆIØ6?×6LÑ6L×6TÑ6TÐV\Ð3ˆG×+Ñ+Ô3ØÒ!4‘g¸"Ô=ÙØ% f×&RÐ&RÐ0RÐ%SÐSTÐUÐUøô ô 	Ü�L‰LÐ<ÀtˆLÔLÚð	ús   Á)C$ ÂC$ Ã$"D
Ä	D
c               ó$   € V ^8„  d   QhRRRRRR/# )r   r}   rS   Úexpected_session_idrÊ   r   rŠ   r   )r   s   "r   r   r0   ¦  s(   € ÷ Vñ V¸ð VÐR_ð VÐdhñ Vr    c              ƒ  óî  "  € V P                  V4      pVe   VP                  P                  e   R#  \        V P                  P                  WR7      G Rj  x€L
 4      pTf   R# T P                  T4      P                  pTR,          TR,          TR,          3Tn        TP                  f   TR	,          TR
,          3Tn
        R# R#  Lq  \         d    \        P                  RTRR7        R# i ; i5i)a±  Adopt the durable pin snapshot for an internal turn when this process holds no context pin
for *session_key*: a restart, or an eviction (/stop, /undo, /model), which clears only
``ephemeral_pin``. Without it the wake renders from its origin-only source (no chat or user
names) and the next human turn re-keys back, rewriting the system bytes twice. Human turns
never call this, so an evicted agent's next human turn still re-renders.N©r³  z*Failed to read persisted prompt pin for %sTrŽ   Úcontext_keyÚcontext_promptÚ
redact_piiÚchannel_promptrÏ   )r€   r�   Úephemeral_pinr   Úasync_session_storeÚget_prompt_pinr?   r™   rš   rž   Úchannel_pin)r„   r}   r³  r…   Úpinr�   s   &&&   r   Ú_rehydrate_prompt_pinsÚ-GatewayAgentCacheMixin._rehydrate_prompt_pins¦  sú   é € ð ×(Ñ(¨Ó5ˆØÒ ×!3Ñ!3×!AÑ!AÒ!MÙð	Ü%¨D×,DÑ,D×,SÑ,SØð -Tó -F÷ 'Fó GˆCð Š;ÙØ×*Ñ*¨;Ó7×DÑDˆØ&)¨-Õ&8¸#Ð>NÕ:OÐQTÐUaÕQbÐ%cˆÔ"Ø×#Ñ#Ò+Ø(+Ð,<Õ(=¸sÐCSÕ?TÐ'UˆLÖ$ñ ,ñ'Føäô 	ä�L‰LÐEÀ{Ð]aˆLÔbÚð	üs;   ‚0C5³$C ÁC	ÁC Á A)C5Ã	C Ã#C2Ã.C5Ã1C2Ã2C5c               ó$   € V ^8„  d   QhRRRRRR/# )r   r}   rÊ   r³  r   rŠ   r   )r   s   "r   r   r0   ½  s(   € ÷ \ñ \°mð \ÐZgð \Ðlpñ \r    c              ƒ  óÈ  "  € V'       d   V P                  V4      MRpVf   R# VP                  P                  VP                  P                  rTVe   Vf   R# R\        RV^ ,          RV^,          RV^,          RV^ ,          RV^,          /p V P
                  P                  WVR7      G Rj  x€L
  R#  L  \         d    \        P                  R	TR
R7        R# i ; i5i)z‡Persist this conversation's pins before the agent runs; the store no-ops an unchanged
snapshot and refuses a session that has moved on.NÚversionr¶  r·  r¸  r¹  rÏ   rµ  z#Failed to persist prompt pin for %sTrŽ   )
r€   r�   rº  r½  r   r»  Úset_prompt_pinr?   r™   rš   )r„   r}   r³  r…   rº  r½  rµ   s   &&&    r   Ú_persist_prompt_pinsÚ+GatewayAgentCacheMixin._persist_prompt_pins½  sâ   é € ÷ :E�×(Ñ(¨Ô5È$ˆØŠ=ÙØ%*×%7Ñ%7×%EÑ%EÀu×GYÑGY×GeÑGe�{ØÒ  KÒ$7ÙàÔ)¨=¸-ÈÕ:JØ˜m¨AÕ.°¸mÈAÕ>NØ˜k¨!�nÐ.>ÀÈAÅð
ˆð
	\Ø×*Ñ*×9Ñ9ØÐ;Nð :ó P÷ Pô Pøäô 	\ä�L‰LÐ>ÀÐVZˆL×[ð	\üs<   ‚BC"Â B8 Â/B6Â0B8 Â4C"Â6B8 Â8#CÃC"ÃCÃC"rq  c               ó(   € V ^8„  d   QhRRRRRRRR/# )r   r¸  r<   r}   rÊ   rq  r   rS   r   )r   s   "r   r   r0   Ò  s,   € ÷ ñ Ø#'ðØ6CðØRVðà	ñr    c               ó’  € V'       d   V P                  V4      MRpV'       d   VP                  P                  MRpVe   V^,          V8w  d   RpV'       d   Ve
   V^,          # V P                  W4      pVe   V^ ,          V8X  d
   V^,          # \	        WR7      pV'       d#   WxV3V P                  V4      P                  n        V# )u  Session-context prompt pinned per session: key hit â†’ pinned bytes reused VERBATIM (immune
to renderer nondeterminism); key miss â†’ re-render and re-pin (rename, topic edit, /sethome).

``internal`` events (kanban wakes, delegation completions, watch notifications) carry a
source rebuilt from the persisted origin, without chat_name/user_name/message_id. Rendering
from it re-keyed the pin, and the next human turn re-keyed it back (Aâ†’Bâ†’A), rewriting
already-sent system bytes each time. An internal event is never a real metadata change, so
it reuses an existing pin verbatim (restored by ``_rehydrate_prompt_pins`` after a restart or an eviction); with
no pin yet it renders and pins as usual. The pin records the ``privacy.redact_pii`` it was
rendered under: bytes from another privacy policy are never reused, even by an internal
event. Callers pass ``event.internal or event.inherit_channel_pin`` (synthetic
goal/heartbeat/resume turns strip ``message_id``) so this pin and ``_pinned_channel_inputs``
reuse on the same decision.N)r¸  )r€   r�   rº  Ú_ephemeral_change_keyr   rž   )	r„   Úcontextr¸  r}   rq  Ú
_pin_stateÚ_eph_pinÚ_eph_keyÚtexts	   &&&&$    r   Ú_pinned_session_context_promptÚ5GatewayAgentCacheMixin._pinned_session_context_promptÒ  s²   € ÷  ?J�T×-Ñ-¨kÔ:Ètˆ
ß<F�:×*Ñ*×8Ò8ÈDˆØÒ H¨Q¥K°:Ô$=ØˆHß˜Ò,Ø˜A•;ÐØ×-Ñ-¨gÓBˆØÒ H¨Q¥K°8Ô$;Ø˜A•;ÐÜ+¨GÔKˆßØKSÐ[eÐJfˆD×Ñ Ó,×9Ñ9ÔGØˆr    c               ó(   € V ^8„  d   QhRRRRRRRR/# )r   r}   rÊ   r¹  rÉ   r   rq  r<   r   )r   s   "r   r   r0   ð  s,   € ÷ %ñ %Ø(ð%Ø:Gð%ØQ^ð%Ømqñ%r    c               óT  € V'       g   W#3# V'       g/   W#P                   3V P                  V4      P                  n        W#3# V P	                  V4      pV'       d   VP                  P                  MRpVf   W#3# Vw  rxV'       d"   VP                   '       g   ^ RIHp	 V	! W8R7      pWs3# )u|  ``(channel_prompt, source)`` for this turn's agent run.

The ephemeral system prompt also appends ``channel_prompt`` and the ``channel_overrides``
prompt (looked up by chat/thread/``parent_chat_id``). Events with no channel inputs of
their own (internal events, and synthetic goal/heartbeat/resume turns â€” see
``MessageEvent.inherit_channel_pin``) carry ``channel_prompt=None`` and a source without
``parent_chat_id``, so they dropped both and toggled the system prompt like the context pin
did. Human turns record their inputs; turns that ask to reuse the pin get them back
(``_rehydrate_prompt_pins`` restores both after a restart).N)Úreplace_source)rÏ   )rÏ   rž   r�   r½  r€   Úgateway.session_identityrÓ  )
r„   r}   r¹  rÉ   rq  r…   r¾  Úpinned_promptÚpinned_parentrÓ  s
   &&&&$     r   Ú_pinned_channel_inputsÚ-GatewayAgentCacheMixin._pinned_channel_inputsð  s�   € ÷ Ø!Ð)Ð)ßØIW×YnÑYnÐHoˆD×Ñ Ó,×9Ñ9ÔEØ!Ð)Ð)Ø×(Ñ(¨Ó5ˆß05ˆe× Ñ ×,Ò,¸4ˆØŠ;Ø!Ð)Ð)Ø'*Ñ$ˆß ×!6×!6Ð!6Ý?Ù# FÔIˆFØÐ$Ð$r    c               ó    € V ^8„  d   QhRRRR/# )r   r¸  r<   r   rS   r   )r   s   "r   r   r0     s   € ÷ +Kñ +K°4ð +K¸Cñ +Kr    c                óN  a€ ^ RI pV P                  pR R loRpRpVP                  \        P                  8X  d^   ^ RIHp V! 4       '       d   RMRpS! VP                  4      S! VP                  4      S! VP                  4      S! VP                  4      3pRpVP                  \        P                  8X  d   ^ RIHp V! 4       '       d   RMRp ^ R	IHp	 \        V	! 4       4      p
VP                  '       d   VP                  P"                  MRS! VP                  4      S! VP                  4      S! VP$                  4      S! VP&                  4      S! VP(                  4      S! VP*                  4      S! VP,                  4      S! \/        VR
R4      4      \1        V P2                  4      YET\4        ;QJ d    . R V P6                   4       F  NK  	  5M! R V P6                   4       4      \4        ;QJ d/    . V3R lV P8                  P;                  4        4       F  NK  	  5M(! V3R lV P8                  P;                  4        4       4      \1        V4      V
3pVP=                  \?        V4      PA                  R4      4      PC                  4       #   \          d    Rp
 EL¼i ; i)uê   Hash the exact inputs ``build_session_context_prompt`` renders. Invariant
(test_prompt_tail_freeze.py): any input whose change alters the rendered bytes MUST appear
here â€” omission means a stale pinned prompt; extras only re-render.Nc               ó   € V ^8„  d   QhRR/# )r   r   rS   r   )r   s   "r   r   ÚBGatewayAgentCacheMixin._ephemeral_change_key.<locals>.__annotate__  s   € ÷ 	 ñ 	 �Sñ 	 r    c                ó,   € \        T ;'       g    R 4      # )ri   )rS   )Úvs   &r   Ú_sÚ8GatewayAgentCacheMixin._ephemeral_change_key.<locals>._s  s   € Ü�q—w�w˜B“<Ðr    ri   )Ú_discord_tools_loadedÚ1Ú0)Ú_slack_tools_loaded)Údisplay_hermes_homeÚprofilec              3  ó8   "  € T F  qP                   x € K  	  R # 5irP  )rH   )rs  Úps   & r   rt  Ú?GatewayAgentCacheMixin._ephemeral_change_key.<locals>.<genexpr>0  s   é € Ð?Ñ#>˜a—'–'Ó#>ùs   ‚c           
   3  óŠ   <"  € T F8  w  rVP                   S! \        VR R4      4      S! \        VRR4      4      3x € K:  	  R# 5i)rX   ri   rÖ   N)rH   r>   )rs  rè  Úhcrß  s   &  €r   rt  ré  1  sB   øé € ð á:‘E�Að —‘™"œW R¨°Ó4Ó5±r¼'À"ÀiÐQSÓ:TÓ7UÕVÛ:ùs   ƒA Azutf-8r   )"rp   rÉ   rÕ   r   r¨  Úgateway.sessionrá  r¬  rÏ   rÎ   rÖ   ÚSLACKrä  Úhermes_constantsrå  rS   r?   rH   Ú	chat_typeÚ	chat_nameÚ
chat_topicÚ	user_namerc   r>   r<   Úshared_multi_user_sessionr$   Úconnected_platformsÚhome_channelsrA   rs   Úreprrt   ru   )rÊ  r¸  rp   ÚsrcÚdiscord_idsÚdiscord_toolsrá  Úslack_toolsrä  rå  Úhome_displayÚ	key_tuplerß  s   &&          @r   rÉ  Ú,GatewayAgentCacheMixin._ephemeral_change_key  s  ø€ ó
 	Ø�n‰nˆõ	 ð  ˆØˆØ�<‰<œ8×+Ñ+Ô+Ý=Ù#8×#:Ò#:™CÀˆMñ �3—<‘<Ó ¡" S×%7Ñ%7Ó"8¹"¸S¿]¹]Ó:KÉRÐPS×P[ÑP[Ë_ðˆKð ˆØ�<‰<œ8Ÿ>™>Ô)Ý;Ù!4×!6Ò!6™#¸CˆKð	Ý<ÜÑ2Ó4Ó5ˆLð #&§,§, ,ˆC�L‰L×Ò°BÙˆs�{‰{‹O™R §¡Ó.±°3·=±=Ó0AÁ2ÀcÇmÁmÓCTÑVXÐY\×YgÑYgÓVhÙˆs�}‰}Ó™r #§+¡+›±´7¸3À	È4Ó3PÓ0QÜ�×2Ñ2Ó3°[ÐQ\ßŒEÑ? 7×#>Ò#>Ó?�E‰EÑ? 7×#>Ò#>Ó?Ó?ßŒEô à$×2Ñ2×8Ñ8Ô:ó�E‰Eô à$×2Ñ2×8Ñ8Ô:óó ô �Ó˜lð
ˆ	ð �~‰~œd 9›o×4Ñ4°WÓ=Ó>×HÑHÓJÐJøô ô 	Ø‹Lð	ús   ÃJ ÊJ$Ê#J$Úcommit_memoryÚrelease_after_turnc               ó(   € V ^8„  d   QhRRRRRRRR/# )r   r}   rS   rþ  r<   rÿ  r   rŠ   r   )r   s   "r   r   r0   9  s*   € ÷ 0<ñ 0<¨sð 0<Àdð 0<Ø04ð0<ØAEñ0<r    c               óä  € ^ RI Hp V P                  V4      pVe#   RVP                  n        RVP                  n        \        V RR4      pRpV'       d1   V;_uu_ 4        V P                  P                  VR4      pRRR4       M#\        V RR4      pVe   VP                  VR4      p\        V4      p	V	e   W”J d   R# \        V	4      V P                  4       9   d4   V'       d*   Ve&   VP                  P                  P                  V	4       R# V'       d   V P                  W‘R3rºMV P                   V	3rºV P#                  W«R\%        V4      R,           2RVR7       R#   + '       g   i     LÇ; i)	uó  Remove a cached agent (/new, /model, ...) and soft-release its LLM client pool (AIAgent
holds reference cycles; without it RSS grows across /new). Soft = frees clients and child
subagents but PRESERVES terminal sandbox / browser / bg processes since the session may
resume; true boundaries call ``_cleanup_agent_resources`` first. Cleanup runs on a daemon
thread so ``_agent_cache_lock`` never spans slow socket teardown.

Pops the entry AND soft-releases the evicted agent's LLM client pool so the httpx connection
(sockets + held buffers) is freed promptly rather than waiting on CPython GC â€” AIAgent holds
reference cycles (callbacks, tool state) that delay refcount collection, so a manual release is
required to keep gateway RSS flat across many /new, /model, undo and reset operations (#29298, same
leak class as #25315).

``release_after_turn``: an agent still mid-turn is released when that turn's running slot
clears (``_release_running_agent_state``) instead of being left to the garbage collector.
rh  NrŠ  r‹  Tzagent-evict-rà   râ   )r—   rH  r€   r�   rº  rª  r>   r‹  r÷   r&   ÚidÚ_running_agent_idsrå   ré   ÚappendÚ_commit_then_release_softrë   rê   rS   )r„   r}   rþ  rÿ  rH  r…   Ú_lockÚevictedr‘  rÁ   rU  rV  s   &&$$        r   r½   Ú*GatewayAgentCacheMixin._evict_cached_agent9  sJ  € õ" 	8ð ×(Ñ(¨Ó5ˆØÒØ/3ˆE×ÑÔ,Ø)-ˆE×ÑÔ&ô ˜Ð1°4Ó8ˆØˆßß’Ø×+Ñ+×/Ñ/°¸TÓB�÷ �ô ˜T >°4Ó8ˆFØÒ!Ø Ÿ*™* [°$Ó7�Ü˜WÓ%ˆàŠ=˜EÓ<ÙÜˆe‹9˜×/Ñ/Ó1Ô1ß! eÒ&7Ø—
‘
×)Ñ)×0Ñ0°Ô7ÙßØ×9Ñ9¸EÐPTÐ;U‘Dà×;Ñ;¸e¸X�DØ×"Ñ" 6°<ÄÀKÓ@PÐQTÕ@UÐ?VÐ1WÐimØ/:ð 	#ö 	<÷% —ús   ÁEÅE/	c               ó    € V ^8„  d   QhRRRR/# r‰   r   )r   s   "r   r   r0   k  s   € ÷ Bñ B¸3ð BÀ4ñ Br    c                ó,   € V P                  VRR7       R# )z¯Reset and compress end the conversation the provider was tracking, so the old agent's
transcript is committed (``on_session_end``) before its clients go; a plain evict is not.T)rþ  N)r½   )r„   r}   s   &&r   Ú_evict_cached_agent_at_boundaryÚ6GatewayAgentCacheMixin._evict_cached_agent_at_boundaryk  s   € ð 	× Ñ  ¸DÐ ÖAr    r}   c          
     ó,   € V ^8„  d   QhRRRRRRRRR	R
/# )r   rV  r$   rX   rS   rã   r<   r}   rÊ   r   rŠ   r   )r   s   "r   r   r0   p  s9   € ÷ Wñ W°%ð W¸sð WÐX\ð WØ+8ðWØDHñWr    c          	     óˆ  € ^ RI pVP                  4       p \        P                  ! VP                  V P
                  WV3RVR7      P                  4        R#   \         d`    T'       g   h \        \        4      ;_uu_ 4        TP	                  T P
                  YT4       RRR4        R#   + '       g   i      R# ; ii ; i)a  Run a release on a daemon thread. ``inline_fallback`` runs it inline (best-effort) when no
thread can start (interpreter shutdown); otherwise a spawn failure propagates, as on main.
The thread runs inside the owning profile's scope (see ``_run_release_in_profile_scope``).NT©rU  rV  rX  rX   )	rY  rG  r\  r]  r^  Ú_run_release_in_profile_scoper_  r?   r   )r„   rU  rV  rX   rã   r}   rY  Úctxs   &&&&$$  r   rê   Ú,GatewayAgentCacheMixin._spawn_release_threadp  s“   € ó
 	Ø×&Ñ&Ó(ˆð	WÜ×Ò C§G¡G°4×3UÑ3UÐW]ÐepÐ2qØ$(¨tô5ß5:±U¶WøÜô 	Wß"ØÜœ)×$Õ$Ø—‘˜×:Ñ:¸FÈ+ÔV÷ %×$×$Ô$úð	Wús/   –?A ÁCÁ*CÂB+Â CÂ+B=Â6CÂ=Cc               ó$   € V ^8„  d   QhRRRRRR/# )r   rV  r$   r}   rÊ   r   rŠ   r   )r   s   "r   r   r0   €  s"   € ÷ ñ ¸%ð Èmð Ð`dñ r    c                óð  € ^ RI HpHp \        4       pV! 4       '       d�   ^ RIHp ^ RIHpHp	H	p
 Rp\        V RR4      pV'       d   Ve    VP                  V4      pV'       d   \        V4      MV! 4       pV! 4       e   V
! V	! 4       4      V
! V4      8w  d	   V! V4      pV;_uu_ 4        V! V!   RRR4       R#   \         d    \        P                  RTRR7        Lƒi ; i  + '       g   i     R# ; i)	uœ  Call ``target(*args)`` under the profile that OWNS ``session_key``.

Threads start with an EMPTY context, so a bare thread would commit end-of-session memory
(provider ``on_session_end`` reads credentials/home at call time) under the launch profile.
And the LRU-cap eviction runs inside the REQUESTING turn, whose agent may belong to another
profile â€” so "some scope is present" is not enough either. The owner comes from the session
key: a named profile's home, else the DEFAULT profile (``agent:main:`` keys), which is the
root Hermes dir even when the gateway was launched under a named profile. Its scope is
entered unless the current one already is the owner's.)Úcurrent_secret_scopeÚis_multiplex_active)Ú_profile_runtime_scope)Úget_default_hermes_rootÚget_hermes_homeÚhermes_home_keyNr�   zPCould not resolve the owning profile for %s; releasing under the default profileTrŽ   )Úagent.secret_scoper  r  r   r—   r  rî  r  r  r  r>   Ú_profile_home_for_keyr?   r™   r"  r   )r„   rU  rV  r}   r  r  Úscoper  r  r  r  Úownerr    Ú
owner_homes   &&&&          r   r  Ú4GatewayAgentCacheMixin._run_release_in_profile_scope€  sÔ   € ÷ 	QÜ“ˆÙ× Ò Ý:ßbÑbØˆEÜ˜D /°4Ó8ˆEß˜uÒ0ð?Ø!×7Ñ7¸ÓD�E÷ ).œ˜eœÑ3JÓ3LˆJÙ#Ó%Ò-±ÁÓARÓ1SÑWfÐgqÓWrÔ1rÙ.¨zÓ:�ßŠUÙ�DŠM÷ ‰Uøô !ô ?Ü—N‘NÐ#uØ#.¸ð #ö ?ð?ú÷ �UˆUús   ÁB; Â*C$Â;#C!Ã C!Ã$C5	c               ó(   € V ^8„  d   QhRRRRRRRR/# ©	r   rÁ   r   rF   rS   Úboundaryr<   r   rŠ   r   )r   s   "r   r   r0   �  s/   € ÷ Oñ O°cð OÀð OÈtð OÐ`dñ Or    c                ó¢  € Ve   \        VR4      '       g   R# \        VRR4      RJpT;'       d    \        VRR4      RJpV'       g   V'       g   R#  \        VRR4      pTP                  \        V\        4      '       d   TMR4       \
        P                  RV4       R#   \         d"   p\
        P                  RY'4        Rp?R# Rp?ii ; i)zÂCommit the live transcript to memory providers before resource-only eviction. A session
boundary (reset, compress) also ends the context engine's session; that engine can run without a provider.NÚcommit_memory_sessionÚ_memory_managerÚcontext_compressorÚ_session_messageszWCommitted on_session_end extraction before soft-evicting session=%s (resource eviction)z)Pre-evict memory commit failed for %s: %s)r|  r>   r%  r#   r`   r™   rš   r?   )r„   rÁ   rF   r#  Úhas_providerÚ
has_engineÚmessagesÚ_es   &&&&    r   Ú _commit_memory_before_soft_evictÚ7GatewayAgentCacheMixin._commit_memory_before_soft_evict�  s¾   € ð Š=¤¨Ð/F× GÒ GÙÜ˜uÐ&7¸Ó>ÀdÐJˆØ×XÐX¤'¨%Ð1EÀtÓ"LÐTXÐ"Xˆ
ß§JÙð	OÜ˜uÐ&9¸4Ó@ˆHØ×'Ñ'´J¸xÌ×4NÒ4N©ÐTXÔYÜ�L‰Lð1Ø25öøô ô 	OÜ�L‰LÐDÀc×NÒNûð	Oús   ÁAB" Â"CÂ-C	Ã	Cc               ó(   € V ^8„  d   QhRRRRRRRR/# r"  r   )r   s   "r   r   r0   °  s)   € ÷ 0ñ 0¨sð 0¸ð 0Èð 0ÐY]ñ 0r    c                óL   € V P                  WV4       V P                  V4       R# )u±   Commit end-of-session memory (if warranted), then soft-release â€” on the daemon eviction
thread. Order matters: commit needs the live memory manager before ``release_clients``.N)r-  rë   )r„   rÁ   rF   r#  s   &&&&r   r  Ú0GatewayAgentCacheMixin._commit_then_release_soft°  s"   € ð 	×-Ñ-¨e¸(ÔCØ×(Ñ(¨Ö/r    c               ó    € V ^8„  d   QhRRRR/# )r   rÁ   r   r   rŠ   r   )r   s   "r   r   r0   ¶  s   € ÷ /ñ /°ð /¸ñ /r    c                óH  € Vf   R# \        \        4      ;_uu_ 4        \        VR4      '       d   VP                  4        MV P	                  V4       RRR4       \        VR4      '       d   . Vn        \        VR4      '       d
   RVn        R# R#   + '       g   i     LF; i)z²Soft cleanup for cache-evicted agents: unlike _cleanup_agent_resources, the session may
resume, so terminal sandbox, browser daemon and bg processes outlive the AIAgent instance.NÚrelease_clientsr(  Ú_db_flush_scan_prefix)r   r?   r|  r4  Ú_cleanup_agent_resourcesr(  r5  )r„   rÁ   s   &&r   rë   Ú2GatewayAgentCacheMixin._release_evicted_agent_soft¶  s„   € ð Š=ÙÜ”i× Õ Ü�uÐ/×0Ò0Ø×%Ñ%Õ'ð ×-Ñ-¨eÔ4÷ !ô �5Ð-×.Ò.Ø&(ˆEÔ#ô �5Ð1×2Ò2Ø*.ˆEÖ'ñ 3÷ !× ús   ž5BÂB!	c                óÔ   € ^ RI Hp \        V RR4      pVf   ^ RIHp  V! V! 4       4      pW n        V#   \
         d)   p\        P                  RT4       T! / 4      p Rp?L6Rp?ii ; i)z¢Operator-configured agent-cache bounds, resolved once per process (lazily, not in
``__init__``, so ``__new__``-constructed test / slash-command runners work too).)Ú_load_gateway_configÚ_agent_cache_bounds_cacheN)Úresolve_agent_cache_boundsz)Agent cache bounds config read failed: %s)	r—   r9  r>   Úgateway.agent_cache_pressurer;  r?   r™   rš   r:  )r„   r9  Úboundsr;  r,  s   &    r   Ú_agent_cache_boundsÚ*GatewayAgentCacheMixin._agent_cache_boundsÌ  sk   € õ 	5Ü˜Ð:¸DÓAˆØŠ>ÝOð8Ù3Ñ4HÓ4JÓK�ð .4Ô*Øˆøô ô 8Ü—‘ÐHÈ"ÔMñ 4°BÓ7•ûð8ús   Ÿ4 ´A'¿A"Á"A'c               ó   € V ^8„  d   QhRR/# ©r   r   rô   r   )r   s   "r   r   r0   Þ  s   € ÷ Lñ L #ñ Lr    c                óV   € ^ RI Hp V P                  4       P                  ;'       g    T# )u@   Effective LRU cap â€” the configured override, else the default.)Ú_AGENT_CACHE_MAX_SIZE)r—   rC  r>  Úmax_size)r„   rC  s   & r   Ú_agent_cache_capÚ'GatewayAgentCacheMixin._agent_cache_capÞ  s#   € å5Ø×'Ñ'Ó)×2Ñ2×KÐKÐ6KÐKr    c               ó   € V ^8„  d   QhRR/# )r   r   Úfloatr   )r   s   "r   r   r0   ã  s   € ÷ Vñ V uñ Vr    c                óV   € ^ RI Hp V P                  4       P                  ;'       g    T# )uD   Effective idle TTL in seconds â€” configured override, else default.)Ú_AGENT_CACHE_IDLE_TTL_SECS)r—   rJ  r>  Úidle_ttl_secs)r„   rJ  s   & r   Ú_agent_cache_idle_ttlÚ,GatewayAgentCacheMixin._agent_cache_idle_ttlã  s#   € å:Ø×'Ñ'Ó)×7Ñ7×UÐUÐ;UÐUr    c               ó   € V ^8„  d   QhRR/# rA  r   )r   s   "r   r   r0   è  s   € ÷ Iñ I°3ñ Ir    c           
     óŒ  aaaa€ ^ RI Ho ^ RIHpHpHo V P                  4       p\        V RR4      p\        V RR4      pVP                  '       d   V'       d   Vf   ^ # V! 4       pVe   WcP                  8  d   ^ # V P                  4       oR VV3R lloR VV3R	 llpT;_uu_ 4        VP                  4        UU	u. uF  w  r‰V\        V	4      3NK  	  p
pp	V! W§VP                  VP                  R
7      pV F  w  rŒVP                  VR4       K  	  RRR4       X'       gl   \        V3R lX
 4       4      p\        VV3R lV
 4       4      p\         P#                  RYcP                  \%        V
4      YÞV'       d   V'       g   RMR4       ^ # \%        V4      p\         P#                  RWcP                  VRP'                  R V 4       4      4        \(        P*                  ! V P,                  V3RRR7      P/                  4        V# u up	pi   + '       g   i     EL; i  \0         d    T P-                  T4        T# i ; i)aÊ  Shed cached transcripts once the gateway heap nears its budget; returns count evicted.

The LRU cap counts entries and the idle sweep counts seconds; neither knows one cached agent
pins a full ``_session_messages`` transcript (tens of MB), so RSS climbs until the cgroup
throttles. Above the anonymous-RSS budget this soft-evicts LRU agents (transcript rebuilt
from the persisted session next turn). Never touched: agents mid-turn, the most recently
used sessions, and transcripts not yet on disk.

A gateway serving many chats can hold every warm transcript for the TTL window.
Pressure eviction bounds that heap before the cgroup throttles and SIGTERM can
no longer flush inside systemd's stop timeout (#80764).
rh  )Úplan_pressure_evictionsÚread_anon_rss_mbÚ transcript_persistence_caught_upr‹  NrŠ  c               ó    € V ^8„  d   QhRRRR/# )r   rÁ   r   r   r<   r   )r   s   "r   r   ÚNGatewayAgentCacheMixin._sweep_agent_cache_under_pressure.<locals>.__annotate__  s   € ÷ 	oñ 	o˜Cð 	o Dñ 	or    c                óP   <€ V R J;'       d    V SJ;'       d    \        V 4      S9  # rP  ©r  )rÁ   rH  Úrunning_idss   &€€r   Ú_is_liveÚJGatewayAgentCacheMixin._sweep_agent_cache_under_pressure.<locals>._is_live  s1   ø€ Ø Ð$×nÐn¨Ð6MÐ)M×nÐnÔRTÐUZÓR[ÐcnÑRnÐnr    c               ó$   € V ^8„  d   QhRRRRRR/# )r   rF   rS   rÁ   r   r   r<   r   )r   s   "r   r   rT    s&   € ÷ 	Oñ 	O˜sð 	O¨3ð 	O°4ñ 	Or    c                ó4   <€ S! V4      ;'       d	    S! V4      # rP  r   )rF   rÁ   rX  rR  s   &&€€r   Ú_is_evictableÚOGatewayAgentCacheMixin._sweep_agent_cache_under_pressure.<locals>._is_evictable  s   ø€ Ù˜E“?×NÐNÑ'GÈÓ'NÐNr    )Úis_evictableÚmax_evictionsÚprotect_recentc              3  ó\   <"  € T F!  w  rVf   K  \        V4      S9   g   K  ^x € K#  	  R # 5irP  rV  )rs  Ú_ÚarW  s   &  €r   rt  ÚKGatewayAgentCacheMixin._sweep_agent_cache_under_pressure.<locals>.<genexpr>  s%   øé € Ð\©'¡$ !°QœAÄrÈ!ÃuÐP[ÑG[ŸAšA«'ùs   ƒ,�,¢
,c              3  ól   <"  € T F)  w  rS! V4      '       g   K  S! V4      '       d   K%  ^x € K+  	  R# 5i)é   Nr   )rs  rb  rc  rX  rR  s   &  €€r   rt  rd    s&   øé € Ðn©7¡4 1±h¸q·kœQÑJjÐkl×JmŸQšQ«7ùs   ƒ4š4ª
4zŽAgent cache pressure: anon RSS %dMB over budget %dMB but no evictable session (%d cached, %d mid-turn, %d blocked on un-flushed persistence)%su–    â€” transcripts are not reaching the session DB (session persistence disabled or failing?); the memory valve cannot shed sessions until they persist.u8    â€” memory will keep climbing until those turns finish.uW   Agent cache pressure: anon RSS %dMB over budget %dMB â€” evicting %d LRU session(s): %sz, c              3  ó*   "  € T F	  w  rVx € K  	  R # 5irP  r   )rs  rF   rb  s   &  r   rt  rd  '  s   é € ÐC[ÑVZÉFÈCÅCÓVZùs   ‚Tzagent-cache-pressurer  )r—   rH  r<  rP  rQ  rR  r>  r>   Úmemory_high_mbr  rA   r&   Úmax_evictions_per_passr`  r÷   Úsumr™   r"  r�  Újoinr\  r]  Ú_release_pressure_batchr_  r?   )r„   rP  rQ  r=  r‘  r  Úrss_mbr\  rF   r   ÚorderedÚplanrb  Ú	_mid_turnÚ
_unflushedÚevicted_countrH  rX  rW  rR  s   &               @@@@r   Ú!_sweep_agent_cache_under_pressureÚ8GatewayAgentCacheMixin._sweep_agent_cache_under_pressureè  s  û€ õ 	8÷	
ñ 	
ð ×)Ñ)Ó+ˆÜ˜˜~¨tÓ4ˆÜ˜Ð1°4Ó8ˆð ×$×$Ð$¯F°e²mÙÙ!Ó#ˆØŠ>˜V×&;Ñ&;Ô;ÙØ×-Ñ-Ó/ˆ÷	oñ 	o÷	Oñ 	O÷ ŠUØDJÇLÁLÄNÔSÁN±j°c˜œ\¨%Ó0Ó1ÁNˆGÑSÙ*ØÀ6×C`ÑC`Ø%×4Ñ4ôˆDó ‘�Ø—
‘
˜3 Ö%ñ ÷ ÷ ÜÔ\©'Ó\Ó\ˆIÜÕn©7ÓnÓnˆJÜ�N‰Nð,ð ×-Ñ-¬s°7«|¸Y÷
 "¯)ñEð Tôñ Ü˜D›	ˆÜ�‰ØeØ×)Ñ)¨=¸$¿)¹)ÑC[ÑVZÓC[Ó:[ô	
ð	/Ü×Ò D×$@Ñ$@ÈÀwÐW[Ø"8ô:ß:?¹%¼'ð ÐùóK T÷ �UˆUûôB ô 	/à×(Ñ(¨Õ.ð Ðð	/ús0   Â*HÂ>H	
Ã?HÇ3H# È	HÈH 	È#IÉIc               ó    € V ^8„  d   QhRRRR/# )r   ro  zlist[tuple]r   rŠ   r   )r   s   "r   r   r0   3  s   € ÷ Cñ C¨Kð C¸Dñ Cr    c                ód  € V'       d6   VP                  ^ 4      w  r# V P                  V P                  W23V4       ?K=  \        \        4      ;_uu_ 4        ^ RIHp V! RRR7       RRR4       R#   \         d!   p\        P                  RY$4        Rp?L[Rp?ii ; i  + '       g   i     R# ; i)a  Release a pressure-evicted batch sequentially on one daemon thread, then ``malloc_trim`` so
RSS actually falls. The plan is drained (``pop`` + ``del``), not iterated, so no local
reference pins evicted agents during ``gc.collect`` + trim (else the valve over-evicts).z"Pressure release failed for %s: %sN)Útrim_memoryTÚagent_cache_pressure)Úforcer  )	r÷   r  r  r?   r™   rš   r   Úhermes_cli.mem_trimrw  )r„   ro  rF   rÁ   r,  rw  s   &&    r   rl  Ú.GatewayAgentCacheMixin._release_pressure_batch3  s‘   € ÷ ØŸ™ !›‰JˆCðLà×2Ñ2°4×3QÑ3QÐTYÐS_ÐadÔeò Ü”i× Õ Ý7Ù˜dÐ+AÕB÷ !Ñ øô ô LÜ—‘ÐAÀ3×KÑKûðLú÷ !× Ð ús#   �A0 ÁBÁ0BÁ;BÂBÂB/	c               ó   € V ^8„  d   QhRR/# )r   r   rŠ   r   )r   s   "r   r   r0   C  s   € ÷ !Sñ !S¨$ñ !Sr    c           	     ó  € \        V RR4      pVe   \        VR4      '       g   R# V P                  4       pV P                  4       p\	        VP                  4       4      R\        ^ \        V4      V,
          4        Uu. uF  qD\        VP                  V4      4      3NK   	  ppV UUu. uF  w  rFVe   \        V4      V9  g   K  WF3NK   	  pppV F  w  rHVP                  VR4       K  	  \        V4      V,
          p	V	^ 8”  d!   \        P                  R\        V4      W94       V FV  w  rF\        P                  RV\        V4      4       Vf   K+  V P                  V P                   Wd3RVR,           2RVR	7       KX  	  R# u upi u uppi )
z¸Evict oldest cached agents past the LRU cap (requires _agent_cache_lock); cleanup on a
daemon thread. Mid-turn agents are SKIPPED, so the cache may stay over cap until the next
insert.r‹  NÚmove_to_enduk   Agent cache over cap (%d > %d); %d excess slot(s) held by mid-turn agents â€” will re-check on next insert.z;Agent cache at cap; evicting LRU session=%s (cache_size=%d)zagent-cache-evict-rà   Frâ   )r>   r|  r  rE  r`   ÚkeysÚmaxr�  r)   r;   r  r÷   r™   r"  rŸ   rê   r  )
r„   r‘  rW  ÚcaprF   Ú
candidatesrÁ   Ú
evict_planrb  Úremaining_over_caps
   &         r   Ú_enforce_agent_cache_capÚ/GatewayAgentCacheMixin._enforce_agent_cache_capC  s  € ô ˜˜~¨tÓ4ˆð Š>¤¨°×!?Ò!?Ùð ×-Ñ-Ó/ˆð ×#Ñ#Ó%ˆÜFJÈ6Ï;É;Ë=ÓFYÐZtÔ[^Ð_`ÔbeÐflÓbmÐpsÕbsÓ[tÑFuÓvÑFu¸sœL¨¯©°C«Ó9Ó:ÑFuˆ
ÐvÙ5?Ôq±Z¡z sÀ5Â=ÔTVÐW\ÓT]ÐepÑTp”l�s“l±Zˆ
ÑqÛ ‰FˆCØ�J‰J�s˜DÖ!ñ !ä  ›[¨3Õ.ÐØ Ô!Ü�N‰NðDä�F“˜Sôó
 %‰JˆCÜ�K‰KÐUÐWZÔ\_Ð`fÓ\gÔhØÔ ð ×*Ñ*¨4×+IÑ+IÈEÈ<Ð[mÐnqÐruÕnvÐmwÐYxØ;@Ècð +ö Só %ùò wùÛqs   Á>$FÂ)F	ÃF	c               ó   € V ^8„  d   QhRR/# rA  r   )r   s   "r   r   r0   f  s   € ÷ ñ ¨3ñ r    c                óú  € \        V RR4      p\        V RR4      pVe   Vf   ^ # \        P                  ! 4       pV P                  4       p. pV P                  4       pT;_uu_ 4        \	        VP                  4       4       FX  w  rx\        V4      p	V	e   \        V	4      V9   d   K&  \        V	RR4      p
V
e   W:,
          V8:  d   KF  VP                  Wy34       KZ  	  V F  w  r{VP                  VR4       K  	  RRR4       V FX  w  ry\        P                  RWs\        V	RV4      ,
          4       V P                  V P                  W—3RVR,           2RVR	7       KZ  	  \        V4      #   + '       g   i     Ly; i)
z–Evict cached agents idle past the idle TTL (lock acquired internally; cleanup on daemon
threads; mid-turn agents SKIPPED); returns the number evicted.r‹  NrŠ  Ú_last_activity_tsz3Agent cache idle-TTL evict: session=%s (idle=%.0fs)zagent-cache-idle-rà   Frâ   )r>   ÚtimerL  r  r`   rA   r)   r  r  r÷   r™   rŸ   rê   r  r�  )r„   r‘  r  ÚnowÚidle_ttlÚto_evictrW  rF   r   rÁ   Úlast_activityrb  s   &           r   Ú_sweep_idle_cached_agentsÚ0GatewayAgentCacheMixin._sweep_idle_cached_agentsf  sl  € ô ˜˜~¨tÓ4ˆÜ˜Ð1°4Ó8ˆØŠ>˜Uš]ÙÜ�iŠi‹kˆØ×-Ñ-Ó/ˆØ "ˆØ×-Ñ-Ó/ˆßŠUÜ" 6§<¡<£>Ö2‘
�Ü$ UÓ+�Ø’=¤B u£I°Ô$<ÙÜ '¨Ð/BÀDÓ I�Ø Ò(¨SÕ-@ÀXÔ,MÙØ—‘  Ö-ñ 3ó #‘�Ø—
‘
˜3 Ö%ñ #÷ ó #‰JˆCÜ�K‰KÐMÈsÔZaÐbgÐi|ð  Bó  [Cõ  UCô  DØ×&Ñ& t×'EÑ'EÈÀ|ÐWhÐilÐmpÕiqÐhrÐUsØ7<È#ð 'ö Oñ #ô �8‹}Ð÷ �Uús   Á&BE*Å*E:	)r:  )NNNFrP  )F):Ú__name__Ú
__module__Ú__qualname__Ú__firstlineno__Ú__doc__ÚclassmethodrI   rL   Ú__annotations__r@   Ústaticmethodrz   r†   r¤   r­   r²   r¹   r¾   rÅ   rÚ   rî   rý   r  r  r  r  r  r+  r1  r5  rä   r@  rc  r†  r–  r�  r¢  r°  r¿  rÅ  rÏ  r×  rÉ  r½   r  rê   r  r-  r  rë   r>  rE  rL  rs  rl  r…  r�  Ú__static_attributes__r   r    r   r+   r+   .   s¹  ‡ Ù|àôó ðð4 68Ð" NÓ7àôó ðð* ö(>ó ð(>õTDõ
0
õd%õ4t÷
Cõ.õ	Yð"ØBF÷"ðHØCG÷ð@,ÐSW÷ ,õ8 õõõTõ@uõB)ð	ÐTV÷ 	õPõ
TõIð$(Ønr÷$(ðLDWà@D÷DWõL võDRõ@õVõ,Võ.\ð*ØY^÷õ<%ð6 ô+Kó ð+KðZ0<ÈUð 0<Ø7<÷0<õdBð
WØ;?÷Wõ ÷:O÷&0õ/ò,õ$Lõ
Võ
IõVCõ !S÷Fñ r    r+   )r9   rk   rh   rj   rl   r•   rm   r–   )-r•  Ú
__future__r   r  rZ  r\  rŠ  Ú
contextlibr   r   Úpathlibr   Útypingr   r   r   r	   r
   Úagent.interrupt_compatr   Úgateway.configr   rì  r   r   Úgateway.session_prompt_pinr   r   Úgateway.run_shutdownr   Úhermes_cli.configr   r   Ú!hermes_cli.local_runtime.endpointr   r—   r   Úgateway.run_turn_runnerr   Ú	getLoggerr™   rª   r&   r)   r+   r   r    r   Ú<module>r¦     sx   ðñWõ #ã Û Û Û ß ,Ý ß ;Õ ;å 3Ý #ß Gß NÝ 0ß 5Ý >çÝ)Ý2ð 
×	Ò	˜=Ó	)€ðÐ õ
Eõ
D÷
Ró Rr    