+
    i*                       R t ^ RIt^ RIt^ RIt^ RIt^ RIt^ RIt^ RIt^ RIt^ RI	t	^ RI
t
^ RIt^ RIt^ RIHt ^ RIHt ^ RIHtHtHtHt R R lt]! 4        ]P,                  P/                  ^ ]! ]! ]4      P4                  P4                  4      4       ^ RIHt ^ RIHt ]! 4       t^ R	I H!t! ^ R
I"H#t# ]R,          t$]#! ]]! ]4      PK                  4       PL                  ^,          R,          R7       ]R,          t']'PQ                  4       '       EdM    ^ RI)t*]+! ]'RR7      ;_uu_ 4       t,]*PZ                  ! ],4      ;'       g    / t.RRR4       ^ RI/H0t0 ]0! ].4      t.].Pc                  4        FC  w  t2t3]4! ]3]]5]6]734      '       g   K  ]2]Pp                  9  g   K.  ]! ]34      ]Pp                  ]2&   KE  	  ].Ps                  R/ 4      t:]:'       d   ]4! ]:];4      '       d   / RRbRRbRRbRRbRRbRRbRRbR R!bR"R#bR$R%bR&R'bR(R)bR*R+bR,R-bR.R/bR0R1bR2R3bR4R5R6R7R8R9/Ct<]<Pc                  4        F]  w  t=t>]=]:9   g   K  ]:]=,          t3]4! ]3]?4      '       d"   ]P                  ! ]34      ]Pp                  ]>&   KH  ]! ]34      ]Pp                  ]>&   K_  	  ].Ps                  R:/ 4      tA]A'       Ed   ]4! ]A];4      '       Edz   R;R<R=R>R?R@RARBRC/RDR<RER>RFR@RGRBRH/RIR<RJR>RKR@RLRBRM//tB]BPc                  4        EFD  w  tCtD]APs                  ]C/ 4      tE]4! ]E];4      '       g   K*  ]! ]EPs                  R<RN4      4      P                  4       tG]! ]EPs                  R>RN4      4      P                  4       tH]! ]EPs                  R@RN4      4      P                  4       tI]! ]EPs                  RBRN4      4      P                  4       tJ]G'       d   ]GRO8w  d   ]G]Pp                  ]DR<,          &   ]H'       d   ]H]Pp                  ]DR>,          &   ]I'       d   ]I]Pp                  ]DR@,          &   ]J'       g   EK.  ]J]Pp                  ]DRB,          &   EKG  	  ].Ps                  RP/ 4      tK]K'       dg   ]4! ]K];4      '       dX   RQ]K9   d   ]! ]KRQ,          4      ]Pp                  RR&   RS]K9   d.   RT]Pp                  9  d   ]! ]KRS,          4      ]Pp                  RT&   ].Ps                  RURN4      tL]L'       d>   ]4! ]L]4      '       d/   RV]Pp                  9  d   ]LP                  4       ]Pp                  RV&   ].Ps                  RW/ 4      tM]4! ]M];4      '       d9   ]MPs                  RX4      tN]Ne$   ]! ]N4      P                  4       ]Pp                  RY&    ^ RZI/HQtQ ]Q! 4        R[]Pp                  R\&   R[]Pp                  R]&   ]Pp                  Ps                  RRN4      tR]R'       d   ]RR9   dA   ]P                  ! R^4      ;'       g    ]! ]P                  ! 4       4      tU]U]Pp                  R&   ^ R_IVHWtWHXtXHYtY ^ R`IZH[t[H\t\H]t]H^t^H_t_H`t` ^ RaIaHbtb ^ RbIcHdtdHeteHftf Rc Rd ltgRe Rf lth]P                  ! ]j4      tk]l! 4       tmRg Rh ltnRi Rj ltoRk Rl ltpRm Rn ltqRo Rp ltrRq Rr ltsRRs Rt llttRu Rv ltu ! Rw Rx4      tvRRy Rz lltwRR{ R| lltxR} ty]jR~8X  d
   ]y! 4        R# R#   + '       g   i     ELh; i  ]P d     ELei ; i  ]P d     ELei ; i)a<  
Gateway runner - entry point for messaging platform integrations.

This module provides:
- start_gateway(): Start all configured platform adapters
- GatewayRunner: Main class managing the gateway lifecycle

Usage:
    # Start the gateway
    python -m gateway.run
    
    # Or from CLI
    python cli.py --gateway
NPathdatetime)DictOptionalAnyListc                    V ^8  d   QhRR/#    returnN )formats   "(/home/ubuntu/hermes-agent/gateway/run.py__annotate__r   $   s     # #4 #    c                    R\         P                  9   d   R# ^ RIp V P                  4       pVP                  VP
                  3 FH  pV'       g   K  \         P                  P                  V4      '       g   K4  V\         P                  R&    R# 	   ^ RIpVP                  4       \         P                  R&   R#   \         d     Mi ; iR F>  p\         P                  P                  T4      '       g   K*  T\         P                  R&    R# 	  R# )zBSet SSL_CERT_FILE if the system doesn't expose CA certs to Python.SSL_CERT_FILEN)z"/etc/ssl/certs/ca-certificates.crtz /etc/pki/tls/certs/ca-bundle.crtz1/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pemz/etc/ssl/ca-bundle.pemz/etc/ssl/cert.pemz/etc/pki/tls/cert.pemz#/usr/local/etc/openssl@1.1/cert.pemz&/opt/homebrew/etc/openssl@1.1/cert.pem)osenvironsslget_default_verify_pathscafileopenssl_cafilepathexistscertifiwhereImportError)r   paths	candidater   s       r   _ensure_ssl_certsr"   $   s    "**$ ((*EllE$8$89	9	22*3BJJ' :&-mmo

?# 		 77>>)$$*3BJJ'	s   %B8 8CC)get_hermes_home)atomic_yaml_write)load_dotenv)load_hermes_dotenvz.env)hermes_homeproject_envconfig.yamlutf-8encoding)_expand_env_varsterminalbackendTERMINAL_ENVcwdTERMINAL_CWDtimeoutTERMINAL_TIMEOUTlifetime_secondsTERMINAL_LIFETIME_SECONDSdocker_imageTERMINAL_DOCKER_IMAGEdocker_forward_envTERMINAL_DOCKER_FORWARD_ENVsingularity_imageTERMINAL_SINGULARITY_IMAGEmodal_imageTERMINAL_MODAL_IMAGEdaytona_imageTERMINAL_DAYTONA_IMAGEssh_hostTERMINAL_SSH_HOSTssh_userTERMINAL_SSH_USERssh_portTERMINAL_SSH_PORTssh_keyTERMINAL_SSH_KEYcontainer_cpuTERMINAL_CONTAINER_CPUcontainer_memoryTERMINAL_CONTAINER_MEMORYcontainer_diskTERMINAL_CONTAINER_DISKcontainer_persistentTERMINAL_CONTAINER_PERSISTENTdocker_volumesTERMINAL_DOCKER_VOLUMESsandbox_dirTERMINAL_SANDBOX_DIRpersistent_shellTERMINAL_PERSISTENT_SHELL	auxiliaryvisionproviderAUXILIARY_VISION_PROVIDERmodelAUXILIARY_VISION_MODELbase_urlAUXILIARY_VISION_BASE_URLapi_keyAUXILIARY_VISION_API_KEYweb_extractAUXILIARY_WEB_EXTRACT_PROVIDERAUXILIARY_WEB_EXTRACT_MODELAUXILIARY_WEB_EXTRACT_BASE_URLAUXILIARY_WEB_EXTRACT_API_KEYapprovalAUXILIARY_APPROVAL_PROVIDERAUXILIARY_APPROVAL_MODELAUXILIARY_APPROVAL_BASE_URLAUXILIARY_APPROVAL_API_KEY autoagent	max_turnsHERMES_MAX_ITERATIONSgateway_timeoutHERMES_AGENT_TIMEOUTtimezoneHERMES_TIMEZONEsecurityredact_secretsHERMES_REDACT_SECRETS)print_config_warnings1HERMES_QUIETHERMES_EXEC_ASKMESSAGING_CWD)PlatformGatewayConfigload_gateway_config)SessionStoreSessionSourceSessionContextbuild_session_contextbuild_session_context_promptbuild_session_key)DeliveryRouter)BasePlatformAdapterMessageEventMessageTypec                0    V ^8  d   QhR\         R\         /# )r   valuer   str)r   s   "r   r   r      s      # # r   c                    \        T ;'       g    R4      P                  4       P                  RR^4      P                  R^4      ^ ,          P                  R^4      ^ ,          # )zDStrip WhatsApp JID/LID syntax down to its stable numeric identifier.rk   +:@)r   stripreplacesplitr   s   &r   _normalize_whatsapp_identifierr      sR     	EKKR		b!		sAq	 
sAq		r   c                0    V ^8  d   QhR\         R\        /# )r   
identifierr   )r   set)r   s   "r   r   r      s      c c r   c           	     $   \        V 4      pV'       g   \        4       # \        R,          R,          p\        4       pV.pV'       d   VP                  ^ 4      pV'       d   WS9   d   K)  VP	                  V4       R F}  pVRV V R2,          pVP                  4       '       g   K*   \        \        P                  ! VP                  RR7      4      4      pT'       g   Kd  Y9  g   Kl  TP                  T4       K  	  K  V#   \         d     K  i ; i)zFResolve WhatsApp phone/LID aliases using bridge session mapping files.whatsappsessionzlid-mapping-.jsonr*   r+   )rk   _reverse)r   r   _hermes_homepopaddr   jsonloads	read_text	Exceptionappend)	r   
normalizedsession_dirresolvedqueuecurrentsuffixmapping_pathmappeds	   &        r   _expand_whatsapp_auth_aliasesr      s    /
;Ju+i7KuHLE
))A,'-W&F&<y)NNL&&((7JJ|55w5GH
 v&0V$ ' O  s   &/D  DDc                $    V ^8  d   QhR\         /# r   r   dict)r   s   "r   r   r   #  s      t r   c                    ^ RI Hp Hp  V ! \        P                  ! R4      R7      pRTP                  R4      RTP                  R4      RTP                  R4      RTP                  R4      R	TP                  R	4      R
\        TP                  R
4      ;'       g    . 4      RTP                  R4      /#   \
         d   p\        T! T4      4      ThRp?ii ; i)zCResolve provider credentials for gateway-created AIAgent instances.)resolve_runtime_providerformat_runtime_provider_errorHERMES_INFERENCE_PROVIDER)	requestedNr_   r]   rY   api_modecommandargscredential_pool)	hermes_cli.runtime_providerr   r   r   getenvr   RuntimeErrorgetlist)r   r   runtimeexcs       r   _resolve_runtime_agent_kwargsr   #  s    
H*ii ;<
 	7;;y)GKK
+GKK
+GKK
+7;;y)W[[(..B/7;;'89   H8=>CGHs   B3 3C>CCc                $    V ^8  d   QhR\         /# r   r   )r   s   "r   r   r   <  s      s r   c                   . p\        V RR4      ;'       g    . p\        V RR4      ;'       g    . p\        V4       F  w  rEV\        V4      8  d	   W4,          MRpVP                  R4      '       g!   \        V RR4      \        P
                  8X  d   VP                  RV R24       Km  VP                  R	4      '       d   VP                  R
V R24       K  VP                  RV R24       K  	  RP                  V4      # )aS  Build a text placeholder for media-only events so they aren't dropped.

When a photo/document is queued during active processing and later
dequeued, only .text is extracted.  If the event has no caption,
the media would be silently lost.  This builds a placeholder that
the vision enrichment pipeline will replace with a real description.

media_urlsNmedia_typesrk   image/message_typez[User sent an image: ]audio/z[User sent audio: z[User sent a file: 
)getattr	enumeratelen
startswithr   PHOTOr   join)eventpartsr   r   iurlmtypes   &      r   _build_media_placeholderr   <  s     Ed399rJ%5;;KJ'"#c+&6"6BH%%)MQ\QbQb)bLL0Q78h''LL-cU!45LL.se156 ( 99Ur   c                >    V ^8  d   QhR\         R\         R,          /# r   session_keyr   Nr   )r   s   "r   r   r   R  s       d
 r   c                    V P                  V4      pV'       g   R# VP                  pV'       g   \        VRR4      '       d   \        V4      pV# )zConsume and return the text of a pending queued message.

Preserves media context for captionless photo/document events by
building a placeholder so the message isn't silently dropped.
Nr   )get_pending_messagetextr   r   )adapterr   r   r   s   &&  r   _dequeue_pending_textr   R  sC     ''4E::DGE<66'.Kr   c                >    V ^8  d   QhR\         R\         R,          /# )r   command_namer   Nr   )r   s   "r   r   r   a  s     - -3 -3: -r   c                D   V P                  4       P                  RR4      p ^ RIHp ^ RIHp V! 4       pV! 4        F  pVP                  4       '       g   K  VP                  R4       F  p\        ;QJ d&    R VP                   4       F  '       g   K   RM	  RM! R VP                   4       4      '       d   KS  VP                  P                  P                  4       P                  RR4      pWq8X  g   K  Wt9   g   K  R	V  R
2u u # 	  K  	  ^ RIHpHp	 \        \         4      P#                  4       P                  P                  p
V	! V
R,          4      pVP                  4       '       d   VP                  R4       F  pVP                  P                  P                  4       P                  RR4      pWq8X  g   K?  VP                  P%                  V4      p\'        VP                  4      pRRP)                  V4       2pR	V  RV R2u # 	  R#   \*         d     R# i ; i)zCheck if a command matches a known-but-inactive skill.

Returns a helpful message if the skill exists but is disabled or only
available as an optional install. Returns None if no match found.
_-)_get_disabled_skill_names)get_all_skills_dirszSKILL.mdc              3   *   "   T F	  qR9   x  K  	  R# 5i).gitN)r   z.githubz.hubr   .0parts   & r   	<genexpr>+_check_unavailable_skill.<locals>.<genexpr>s  s     V~t::~   TFThe **zJ** skill is installed but disabled.
Enable it with: `hermes skills config`)r#   get_optional_skills_dirzoptional-skillsz	official//zQ** skill is available but not installed.
Install it with: `hermes skills install `N)lowerr   tools.skills_toolr   agent.skill_utilsr   r   rglobanyr   parentnamehermes_constantsr#   r   r   __file__resolverelative_tor   r   r   )r   r   r   r   disabled
skills_dirskill_mdr   r#   r   	repo_rootoptional_dirrelr   install_paths   &              r   _check_unavailable_skillr  a  s    ##%--c37J$?9,. ./J$$&&&,,Z83Vx~~V333Vx~~VVV++113;;CE%$*:  /A B 9 0 	NN**,33::	.y;L/LM  (..z:++113;;CE%"//55lCC OE%.sxx.?#@L  /CCO.PQS ;   s>   A/H $H 99H 7H ?	H 	B/H =AH H HHc                (    V ^8  d   QhRRR\         /# )r   platformr|   r   r   )r   s   "r   r   r     s     C C: C# Cr   c                H    V \         P                  8X  d   R# V P                  # )uN   Map a Platform enum to its config.yaml key (LOCAL→"cli", rest→enum value).cli)r|   LOCALr   r  s   &r   _platform_config_keyr    s    .5BHNNBr   c                $    V ^8  d   QhR\         /# r   r   )r   s   "r   r   r     s     
 
d 
r   c                 ^    \         R,          p V P                  4       '       dA   ^ RIp\        V RRR7      ;_uu_ 4       pVP	                  V4      ;'       g    / uuRRR4       #  / #   + '       g   i     / # ; i  \
         d&    \        P                  R\         R,          4        / # i ; i)z@Load and parse ~/.hermes/config.yaml, returning {} on any error.r)   Nrr*   r+   z%Could not load gateway config from %s)r   r   yamlopen	safe_loadr   loggerdebug)config_pathr  fs      r   _load_gateway_configr    s    \"]2k399Q~~a(..B :9   I	 :9 I  \<l]>Z[I\s3   "A< A< A(
A< (A9	3A< 9A< <,B,+B,c                >    V ^8  d   QhR\         R,          R\        /# )r   configNr   )r   r   )r   s   "r   r   r     s      4$; # r   c                   V e   T M	\        4       pVP                  R/ 4      p\        V\        4      '       d   V# \        V\        4      '       d5   VP                  R4      ;'       g    VP                  R4      ;'       g    R# R# )u   Read model from config.yaml — single source of truth.

Without this, temporary AIAgent instances (memory flush, /compress) fall
back to the hardcoded default which fails when the active provider is
openai-codex.
r[   defaultrk   )r  r   
isinstancer   r   )r  cfg	model_cfgs   &  r   _resolve_gateway_modelr     so     &&,@,BC$I)S!!	It	$	$}}Y'GG9==+AGGRGr   c                P    V ^8  d   QhR\         \        \        ,          ,          /# r   )r   r   r   )r   s   "r   r   r     s      Xd3i0 r   c                     ^ RI p V P                  R4      pV'       d   V.#  ^ RIpVP                  P	                  R4      e   \
        P                  RR.#  R#   \         d     R# i ; i)u[  Resolve the Hermes update command as argv parts.

Tries in order:
1. ``shutil.which("hermes")`` — standard PATH lookup
2. ``sys.executable -m hermes_cli.main`` — fallback when Hermes is running
   from a venv/module invocation and the ``hermes`` shim is not on PATH

Returns argv parts ready for quoting/joining, or ``None`` if neither works.
Nhermes
hermes_cliz-mzhermes_cli.main)shutilwhichimportlib.utilutil	find_specsys
executabler   )r%  
hermes_bin	importlibs      r   _resolve_hermes_binr.    sp     h'J|>>##L1=NND*;<< >
   s   3A A('A(c                     a  ] tR tRt o Rt/ tRV 3R lR lltV 3R lR lt]R,          t	V 3R	 lR
 lt
V 3R lR ltV 3R lR ltV 3R lR ltV 3R lR ltV 3R lR lt]V 3R lR l4       t]V 3R lR l4       t]V 3R lR l4       tV 3R lR ltV 3R lR ltV 3R lR  ltV 3R! lR" lt]V 3R# lR$ l4       t]V 3R% lR& l4       t]V 3R' lR( l4       t]V 3R) lR* l4       t]V 3R+ lR, l4       t]V 3R- lR. l4       t]V 3R/ lR0 l4       t]V 3R1 lR2 l4       t V 3R3 lR4 lt!RV 3R6 lR7 llt"V 3R8 lR9 lt#V 3R: lR; lt$V 3R< lR= lt%V 3R> lR? lt&V 3R@ lRA lt'V 3RB lRC lt(V 3RD lRE lt)V 3RF lRG lt*V 3RH lRI lt+V 3RJ lRK lt,V 3RL lRM lt-V 3RN lRO lt.V 3RP lRQ lt/V 3RR lRS lt0V 3RT lRU lt1V 3RV lRW lt2V 3RX lRY lt3V 3RZ lR[ lt4V 3R\ lR] lt5V 3R^ lR_ lt6V 3R` lRa lt7]V 3Rb lRc l4       t8V 3Rd lRe lt9V 3Rf lRg lt:V 3Rh lRi lt;V 3Rj lRk lt<V 3Rl lRm lt=RV 3Rn lRo llt>V 3Rp lRq lt?V 3Rr lRs lt@V 3Rt lRu ltAV 3Rv lRw ltBV 3Rx lRy ltCV 3Rz lR{ ltDV 3R| lR} ltEV 3R~ lR ltFV 3R lR ltGV 3R lR ltHV 3R lR ltIV 3R lR ltJV 3R lR ltKV 3R lR ltLV 3R lR ltMV 3R lR ltNV 3R lR ltOR5tPV 3R lR ltQV 3R lR ltR]S! ]TP                  ]TP                  ]TP                  ]TP                  ]TP                  ]TP                  ]TP                  ]TP                  ]TP                  ]TP                  ]TP                  ]TP                  ]TP                  ]TP                  04      tcV 3R lR ltdV 3R lR lteRV 3R lR lltfV 3R lR ltgV 3R lR lthV 3R lR ltiV 3R lR ltjV 3R lR ltkV 3R lR ltl^tm]V 3R lR l4       tnV 3R lR ltoRV 3R lR lltpV 3R ltqRtrV tsR# )GatewayRunneri  zq
Main gateway controller.

Manages the lifecycle of all platform adapters and routes
messages to/from the agent.
Nc                0   < V ^8  d   QhRS[ S[,          /# )r   r  )r   r}   )r   __classdict__s   "r   r   GatewayRunner.__annotate__  s     `, `,x6 `,r   c                  a T;'       g    \        4       T n        / V n        V P                  4       V n        V P                  4       V n        V P                  4       V n        V P                  4       V n
        V P                  4       V n        V P                  4       V n        V P                  4       V n        ^ RIHo \'        V P                  P(                  V P                  V3R lR7      V n        \-        V P                  4      V n        RV n        \2        P4                  ! 4       V n        RV n        RV n        RV n        / V n        / V n         / V n!        ^ RI"p/ V n#        VPI                  4       V n%        RV n&        RV n'        / V n(        / V n)        / V n*        / V n+         ^ RI,H-p V! RR7       RV n/         ^ RI0H1p V! 4       V n/        ^ R
I4H5p V! 4       V n6        ^ RI7H8p V! 4       V n9        V Pu                  4       V n;        \y        4       V n=        R#   \\         d     Lqi ; i  \\         d!   p\d        Pg                  R	T4        Rp?LRp?ii ; i)    process_registryc                 &   < SP                  V 4      # N)has_active_for_session)keyr7  s   &r   <lambda>(GatewayRunner.__init__.<locals>.<lambda>  s    0@0W0WX[0\r   )has_active_processes_fnFN)ensure_installed)log_failures	SessionDBz&SQLite session store not available: %s)PairingStore)HookRegistry)>r~   r  adapters_load_prefill_messages_prefill_messages_load_ephemeral_system_prompt_ephemeral_system_prompt_load_reasoning_config_reasoning_config_load_show_reasoning_show_reasoning_load_provider_routing_provider_routing_load_fallback_model_fallback_model_load_smart_model_routing_smart_model_routingtools.process_registryr7  r   sessions_dirsession_storer   delivery_router_runningasyncioEvent_shutdown_event_exit_cleanly_exit_with_failure_exit_reason_running_agents_running_agents_ts_pending_messages	threading_agent_cacheLock_agent_cache_lock_effective_model_effective_provider_session_model_overrides_pending_approvals_failed_platforms_update_prompt_pendingtools.tirith_securityr?  r   _session_dbhermes_staterB  r  r  gateway.pairingrC  pairing_storegateway.hooksrD  hooks_load_voice_modes_voice_moder   _background_tasks)	selfr  
_threadingr?  rB  erC  rD  r7  s	   &&      @r   __init__GatewayRunner.__init__  s   55 3 5=? "&!<!<!>(,(J(J(L%!%!<!<!>#88:!%!<!<!>#88:$($B$B$D! 	<)KK$$dkk$\
  .dkk:&}}""'+/ 024613 	'.0!+!2
 0426  DF% >@ BD 8:#	>%0
  	F.({D
 	1)^ 	/!^
 ,0+A+A+C '*e/  		  	FLLA1EE	Fs*    H 7H$ H! H!$I/I

Ic                    < V ^8  d   QhRS[ /# r   bool)r   r2  s   "r   r   r3  A  s      $ r   c                H     ^ RI Hp V! R4      RJ#   \         d     R# i ; i)z3Check if the hermes-agent-setup skill is installed.)_find_skillzhermes-agent-setupNF)tools.skill_manager_toolr  r   )rv  r  s   & r   _has_setup_skillGatewayRunner._has_setup_skillA  s-    	<34D@@ 		s    !!zgateway_voice_mode.jsonc                6   < V ^8  d   QhRS[ S[S[3,          /# r   )r   r   )r   r2  s   "r   r   r3  M  s     
 
4S> 
r   c                `    \         P                  ! V P                  P                  4       4      p\        T\        4      '       g   / # 0 RmpTP                  4        UUu/ uF  w  r4YB9   g   K  \        T4      TbK  	  upp#   \        \         P
                  \        3 d    / u # i ; iu uppi )off>   allr  
voice_only)r   r   _VOICE_MODE_PATHr   FileNotFoundErrorJSONDecodeErrorOSErrorr  r   itemsr   )rv  datavalid_modeschat_idmodes   &    r   rs  GatewayRunner._load_voice_modesM  s    	::d33==?@D $%%I2 "&
!-" CL$!-
 	
 "4#7#7A 	I	
s   .B 
B*.B*"B'&B'c                   < V ^8  d   QhRR/# r   r   )r   r2  s   "r   r   r3  ]  s     @ @4 @r   c                *    V P                   P                  P                  R R R7       V P                   P                  \        P
                  ! V P                  ^R7      4       R#   \         d"   p\        P                  RT4        Rp?R# Rp?ii ; i)T)parentsexist_ok)indentzFailed to save voice modes: %sN)
r  r   mkdir
write_textr   dumpsrt  r  r  warning)rv  rx  s   & r   _save_voice_modesGatewayRunner._save_voice_modes]  su    	@!!((..td.K!!,,

4++A6  	@NN;Q??	@s   A"A& &B1BBc                *   < V ^8  d   QhRS[ RS[RR/# )r   r  r   r   N)r   r}  )r   r2  s   "r   r   r3  f  s#     , ,s ,d ,W[ ,r   c                    \        VRR4      p\        V\        4      '       g   R# V'       d   VP                  V4       R# VP	                  V4       R# )zBUpdate an adapter's in-memory auto-TTS suppression set if present._auto_tts_disabled_chatsN)r   r  r   r   discard)rv  r   r  r   disabled_chatss   &&&& r   _set_adapter_auto_tts_disabled,GatewayRunner._set_adapter_auto_tts_disabledf  s@     *DdK.#..w'""7+r   c                   < V ^8  d   QhRR/# r   r   )r   r2  s   "r   r   r3  p  s     
 
D 
r   c                    \        VRR4      p\        V\        4      '       g   R# VP                  4        VP	                  R V P
                  P                  4        4       4       R# )z@Restore persisted /voice off state into a live platform adapter.r  Nc              3   <   "   T F  w  rVR 8X  g   K  Vx  K  	  R# 5i)r  Nr   )r   r  r  s   &  r   r   BGatewayRunner._sync_voice_mode_state_to_adapter.<locals>.<genexpr>v  s      
)ATU]GG)As   
)r   r  r   clearupdatert  r  )rv  r   r  s   && r   !_sync_voice_mode_state_to_adapter/GatewayRunner._sync_voice_mode_state_to_adapterp  sW     *DdK.#.. 
)-)9)9)?)?)A
 	
r   c                    < V ^8  d   QhRS[ /# r   old_session_idr   )r   r2  s   "r   r   r3  |  s     h` h`h`r   c                T   V'       d0   VP                  R4      '       d   \        P                  RV4       R#  V P                  P	                  V4      pV'       d   \        V4      ^8  d   R# ^ RIHp \        4       pVP                  R4      '       g   R# \        4       pV! R/ VBRVR^RR	R
R	RRR.RV/B pR Vn        V Uu. uFX  pVP                  R4      R 9   g   K  VP                  R4      '       g   K4  RVP                  R4      RVP                  R4      /NKZ  	  ppRp	 ^ RIHp
 V
! 4       pR! F^  w  rW,          pVP                  4       '       g   K%  VP                  RR7      P!                  4       pV'       g   KO  V	RV RV 2,          p	K`  	  RpV	'       d   VRV	 R2,          pVR,          pVP%                  VVR7       \        P'                  RV4       R# u upi   \"         d     L]i ; i  \"         d#   p\        P                  RTT4        Rp?R# Rp?ii ; i)"u   Prompt the agent to save memories/skills before context is lost.

Synchronous worker — meant to be called via run_in_executor from
an async context so it doesn't block the event loop.
cron_z*Skipping memory flush for cron session: %sNAIAgentr_   r[   max_iterations
quiet_modeTskip_memoryenabled_toolsetsmemoryskills
session_idc                      R # r9  r   akws   *,r   r<  ;GatewayRunner._flush_memories_for_session.<locals>.<lambda>      4r   rolecontentrk   )get_memory_dirr*   r+   z

## Current z:
u  [System: This session is about to be automatically reset due to inactivity or a scheduled daily reset. The conversation context will be cleared after this turn.

Review the conversation above and:
1. Save any important facts, preferences, or decisions to memory (user profile or your notes) that would be useful in future sessions.
2. If you discovered a reusable workflow or solved a non-trivial problem, consider saving it as a skill.
3. If nothing is worth saving, that's fine — just skip.

uA  IMPORTANT — here is the current live state of memory. Other sessions, cron jobs, or the user may have updated it since this conversation ended. Do NOT overwrite or remove entries unless the conversation above reveals something that genuinely supersedes them. Only add new information that is not already captured below.

z]Do NOT respond to the user. Just use the memory and skill_manage tools if needed, then stop.])user_messageconversation_historyz/Pre-reset memory flush completed for session %sz0Pre-reset memory flush failed for session %s: %sr   user	assistant))z	MEMORY.mdzMEMORY (your personal notes))zUSER.mdzUSER PROFILE (who the user is))r   r  r  rV  load_transcriptr   	run_agentr  r   r   r   	_print_fntools.memory_toolr  r   r   r   r   run_conversationinfo)rv  r  historyr  runtime_kwargsr[   	tmp_agentmmsgs_current_memoryr  _mem_dirfnamelabelfpathr  flush_promptrx  s   &&                r   _flush_memories_for_session)GatewayRunner._flush_memories_for_session|  sZ    n77@@LLE~VY	`((88HGc'lQ.):<N!%%i00
 +,E    !  	
 ! #+H!5 *I #8I
 ! A55=$99 E>?eeI>N Ev	1553CD    !O<)+%LE %,E||~~"'//7/"C"I"I"K"7+s7)/TTO%P  & ''t- /L
 &&)%) '  KKI>Zs*  J  	`LLK^]^__	`s}   "G: G: .'G: .G: G$"G$;(G$#G: (/G) %G) G) 	G: #?G: $G: )G74G: 6G77G: :H'H""H'c                    < V ^8  d   QhRS[ /# r  r   )r   r2  s   "r   r   r3    s     

 



r   c                   "   \         P                  ! 4       pVP                  RV P                  V4      G Rj  xL
  R#  L5i)zLRun the sync memory flush in a thread pool so it won't block the event loop.N)rY  get_event_looprun_in_executorr  )rv  r  loops   && r   _async_flush_memories#GatewayRunner._async_flush_memories  s<     
 %%'"",,
 	
 	
s   6A?Ac                    < V ^8  d   QhRS[ /# r   r|  )r   r2  s   "r   r   r3    s     " "T "r   c                    V P                   # r9  )r\  rv  s   &r   should_exit_cleanly!GatewayRunner.should_exit_cleanly  s    !!!r   c                    < V ^8  d   QhRS[ /# r   r|  )r   r2  s   "r   r   r3    s     ' '$ 'r   c                    V P                   # r9  )r]  r  s   &r   should_exit_with_failure&GatewayRunner.should_exit_with_failure  s    &&&r   c                0   < V ^8  d   QhRS[ S[,          /# r   )r   r   )r   r2  s   "r   r   r3    s     ! !Xc] !r   c                    V P                   # r9  )r^  r  s   &r   exit_reasonGatewayRunner.exit_reason  s       r   c                &   < V ^8  d   QhRS[ RS[/# r   sourcer   )r   r   )r   r2  s   "r   r   r3    s     
 
m 
 
r   c           	     >   \        V R4      '       dK   V P                  e=    V P                  P                  V4      p\        V\        4      '       d   V'       d   V# \        V RR4      p\        V\        VRR4      \        VRR4      R7      #   \
         d     L>i ; i)	zUResolve the current session key for a source, honoring gateway config when available.rV  Nr  group_sessions_per_userTthread_sessions_per_userF)r  r  )hasattrrV  _generate_session_keyr  r   r   r   r   )rv  r  r   r  s   &&  r   _session_key_for_source%GatewayRunner._session_key_for_source  s    4))d.@.@.L"00FFvNk3//K&& x. $+F4Mt$T%,V5OQV%W
 	
  s   8B B BBc                2   < V ^8  d   QhRS[ RS[ RS[RS[/# )r   r  r[   r  r   r   r   )r   r2  s   "r   r   r3    s1     d ds d3 dX\ dae dr   c                T   ^ RI Hp RTRVP                  R4      RVP                  R4      RVP                  R4      RVP                  R4      RVP                  R4      R\        VP                  R4      ;'       g    . 4      R	VP                  R	4      /pV! V\	        V R
/ 4      V4      # )r5  )resolve_turn_router[   r_   r]   rY   r   r   r   r   rS  )agent.smart_model_routingr  r   r   r   )rv  r  r[   r  r  primarys   &&&&  r   _resolve_turn_agent_config(GatewayRunner._resolve_turn_agent_config  s    @ U~)))4**:6**:6**:6~)))4D++F399r:~112CD	
 ",>TVX0Y[bccr   c                $   < V ^8  d   QhRS[ RR/# )r   r   r   N)r   )r   r2  s   "r   r   r3    s     ; ;9L ;QU ;r   c                  "   \         P                  RVP                  P                  VP                  ;'       g    RVP
                  ;'       g    R4       V P                  P                  VP                  4      pW!J d[    VP                  4       G Rj  xL
  V P                  P                  VP                  R4       V P                  V P                  n        VP                  '       d   V P                  P                  P                  VP                  4      pV'       d   VP                  V P                  9  dd   RVR^ R\        P                   ! 4       ^,           /V P                  VP                  &   \         P#                  RVP                  P                  4       V P                  '       g   V P                  '       gz   VP
                  ;'       g    R	V n        VP                  '       d   R
V n        \         P                  R4       M\         P                  R4       V P)                  4       G Rj  xL
  R# V P                  '       g   V P                  '       d   VP                  '       dR   VP
                  ;'       g    RV n        R
V n        \         P                  R4       V P)                  4       G Rj  xL
  R# \         P+                  R\-        V P                  4      4       R# R# R#  EL`  T P                  P                  TP                  R4       T P                  T P                  n        i ; i EL L5i)zReact to an adapter failure after startup.

If the error is retryable (e.g. network blip, DNS failure), queue the
platform for background reconnection instead of giving up permanently.
zFatal %s adapter error (%s): %sunknownunknown errorNr  attempts
next_retryz%%s queued for background reconnectionz#All messaging adapters disconnectedTzSNo connected messaging platforms remain. Shutting down gateway for service restart.zGNo connected messaging platforms remain. Shutting down gateway cleanly.z4All messaging platforms failed with retryable errorszuAll messaging platforms failed with retryable errors. Shutting down gateway for service restart (systemd will retry).zSNo connected messaging platforms remain, but %d platform(s) queued for reconnection)r  errorr  r   fatal_error_codefatal_error_messagerE  r   
disconnectr   rW  fatal_error_retryabler  	platformsrj  time	monotonicr  r^  r]  stopr  r   )rv  r   existingplatform_configs   &&  r   _handle_adapter_fatal_error)GatewayRunner._handle_adapter_fatal_error  sr     	-""$$11	''::?		
 ==$$W%5%56>((***!!'"2"2D904$$- ((("kk33778H8HIO7#3#34;Q;Q#Qo $.."2R"7<&&w'7'78
 ;$$**
 }}}T%;%;%; ' ; ; d d?dD,,,*.'rsfg))+4#9#9#9 ,,,$+$?$?$y$yCy!*.'V iik!!i../ $:7 +!!'"2"2D904$$-.  "s   AM1MK8 K5K8 AM-6M$BM4MMM3AM8L>9MM#M5M7M?M 5M5K8 8AL;;MMc                $   < V ^8  d   QhRS[ RR/# )r   reasonr   Nr   )r   r2  s   "r   r   r3  Z  s     # ## #$ #r   c                T    R V n         Wn        V P                  P                  4        R# )TN)r\  r^  r[  r   )rv  r  s   &&r   _request_clean_exit!GatewayRunner._request_clean_exitZ  s"    !"  "r   c                F   < V ^8  d   QhRS[ S[S[S[3,          ,          /# r   )r	   r   r   r   )r   r2  s   "r   r   r3  `  s!     $ $Dc3h$8 $r   c                    ^ RI p \        P                  ! RR4      pV'       gt    ^ RIp\        R,          pVP                  4       '       dL   \        VRR7      ;_uu_ 4       pVP                  V4      ;'       g    / pRRR4       XP                  RR4      pV'       g   . # \        V4      P                  4       pVP                  4       '       g   \        V,          pVP                  4       '       g   \        P                  RV4       . #  \        VR	RR7      ;_uu_ 4       pV P                  V4      pRRR4       \!        X\"        4      '       g   \        P                  R
V4       . # V#   + '       g   i     L; i  \         d     Li ; i  + '       g   i     Ld; i  \         d#   p	\        P                  RYi4       . u Rp	?	# Rp	?	ii ; i)zLoad ephemeral prefill messages from config or env var.

Checks HERMES_PREFILL_MESSAGES_FILE env var first, then falls back to
the prefill_messages_file key in ~/.hermes/config.yaml.
Relative paths are resolved from ~/.hermes/.
NHERMES_PREFILL_MESSAGES_FILErk   r)   r*   r+   prefill_messages_filez#Prefill messages file not found: %sr  z3Prefill messages file must contain a JSON array: %sz+Failed to load prefill messages from %s: %s)r   r   r   r  r   r   r  r  r   r   r   
expanduseris_absoluter  r  loadr  r   )
_json	file_path_ycfg_path_fr  r   r  r  rx  s
             r   rF  $GatewayRunner._load_prefill_messages_  sb    	II<bA	!'-7??$$h99R ll2.44" : #(? DI II))+!!$&D{{}}NN@$GI		dC'22azz!} 3dD))TVZ[	K' :9   32  	NNH$RI	sk   &E? E? !E,=E? F# "F45F# *F# ,E<	7E? ?FFF 	F# #G.GGGc                    < V ^8  d   QhRS[ /# r   r   )r   r2  s   "r   r   r3    s      3 r   c                    \         P                  ! RR4      p V '       d   V #  ^ RIp\        R,          pVP	                  4       '       dt   \        VRR7      ;_uu_ 4       pVP                  V4      ;'       g    / pRRR4       XP                  R/ 4      P                  RR4      ;'       g    RP                  4       #  R#   + '       g   i     LM; i  \         d     R# i ; i)	zLoad ephemeral system prompt from config or env var.

Checks HERMES_EPHEMERAL_SYSTEM_PROMPT env var first, then falls back to
agent.system_prompt in ~/.hermes/config.yaml.
HERMES_EPHEMERAL_SYSTEM_PROMPTrk   Nr)   r*   r+   rm   system_prompt)
r   r   r  r   r   r  r  r   r   r   )promptr#  r$  r%  r  s        r   rH  +GatewayRunner._load_ephemeral_system_prompt  s     ;R@M	#m3H  (W55,,r*00bC 6,00"EKKRRTT !  65  		s5   &C 
C C ;0C ,C  C	C C"!C"c                .   < V ^8  d   QhRS[ R,          /# r   r   )r   r2  s   "r   r   r3    s      D4K r   c                 d   ^ RI Hp  Rp ^ RIp\        R,          pVP	                  4       '       d}   \        VRR7      ;_uu_ 4       pVP                  V4      ;'       g    / pRRR4       \        XP                  R/ 4      P                  RR4      ;'       g    R4      P                  4       pT'       g   \        P                  ! R	R4      pT ! T4      pT'       d1   TP                  4       '       d   Tf   \        P                  R
T4       T#   + '       g   i     L; i  \         d     Li ; i)zLoad reasoning effort from config with env fallback.

Checks agent.reasoning_effort in config.yaml first, then
HERMES_REASONING_EFFORT as a fallback. Valid: "xhigh", "high",
"medium", "low", "minimal", "none". Returns None to use default
(medium).
)parse_reasoning_effortrk   Nr)   r*   r+   rm   reasoning_effortHERMES_REASONING_EFFORTz5Unknown reasoning_effort '%s', using default (medium))r   r/  r  r   r   r  r  r   r   r   r   r   r   r  r  )r/  effortr#  r$  r%  r  results          r   rJ  $GatewayRunner._load_reasoning_config  s     	<	#m3H  (W55,,r*00bC 6SWWWb1556H"MSSQSTZZ\ YY8"=F'/fllnnNNRTZ[ 65  		s4   &D! D! D"5D! D! D	D! !D/.D/c                    < V ^8  d   QhRS[ /# r   r|  )r   r2  s   "r   r   r3    s      $ r   c                 j    ^ RI p \        R,          pVP                  4       '       de   \        VRR7      ;_uu_ 4       pV P	                  V4      ;'       g    / pRRR4       \        XP                  R/ 4      P                  RR4      4      #  R#   + '       g   i     L>; i  \         d     R# i ; i)z<Load show_reasoning toggle from config.yaml display section.Nr)   r*   r+   displayshow_reasoningF)r  r   r   r  r  r}  r   r   r#  r$  r%  r  s       r   rL  "GatewayRunner._load_show_reasoning  s    	#m3H  (W55,,r*00bC 6CGGIr2667GOPP !  65  		s-   &B# B# B2B# B 	B# #B21B2c                    < V ^8  d   QhRS[ /# r   r   )r   r2  s   "r   r   r3    s          r   c                 Z   \         P                  ! RR4      p V '       g    ^ RIp\        R,          pVP	                  4       '       dv   \        VRR7      ;_uu_ 4       pVP                  V4      ;'       g    / pRRR4       XP                  R/ 4      P                  R4      pVR	J d   R
p MVR9  d   \        V4      p T ;'       g    RP                  4       P                  4       p 0 RmpW9  d   \        P                  RV 4       R# V #   + '       g   i     L; i  \         d     Lli ; i)u]  Load background process notification mode from config or env var.

Modes:
  - ``all``    — push running-output updates *and* the final message (default)
  - ``result`` — only the final completion message (regardless of exit code)
  - ``error``  — only the final message when exit code is non-zero
  - ``off``    — no watcher messages at all
HERMES_BACKGROUND_NOTIFICATIONSrk   Nr)   r*   r+   r7   background_process_notificationsFr  r  zBUnknown background_process_notifications '%s', defaulting to 'all')Nrk   >   r  r  r  r3  )r   r   r  r   r   r  r  r   r   r   r   r   r  r  )r  r#  r$  r%  r  rawvalids          r   #_load_background_notifications_mode1GatewayRunner._load_background_notifications_mode  s     yy:B?!'-7??$$h99R ll2.44" :'')R0445WXCe|$J."3x $$&,,.1NNT # :9  s5   &D D D	91D +D 	D	D D*)D*c                    < V ^8  d   QhRS[ /# r   r   )r   r2  s   "r   r   r3    s      D r   c                 L    ^ RI p \        R,          pVP                  4       '       dV   \        VRR7      ;_uu_ 4       pV P	                  V4      ;'       g    / pRRR4       XP                  R/ 4      ;'       g    / #  / #   + '       g   i     L/; i  \         d     / # i ; i)z>Load OpenRouter provider routing preferences from config.yaml.Nr)   r*   r+   provider_routingr  r   r   r  r  r   r   r9  s       r   rN  $GatewayRunner._load_provider_routing  s    	#m3H  (W55,,r*00bC 6ww126<<"< ! 	 65  			3   &B B B B ;B B	B B#"B#c                >   < V ^8  d   QhRS[ S[,          R,          /# r   )r   r   )r   r2  s   "r   r   r3    s      $+"4 r   c                     ^ RI p \        R,          pVP                  4       '       dx   \        VRR7      ;_uu_ 4       pV P	                  V4      ;'       g    / pRRR4       XP                  R4      ;'       g    VP                  R4      ;'       g    RpV'       d   V# R#   + '       g   i     LP; i  \         d     R# i ; i)zLoad fallback provider chain from config.yaml.

Returns a list of provider dicts (``fallback_providers``), a single
dict (legacy ``fallback_model``), or None if not configured.
AIAgent.__init__ normalizes both formats into a chain.
Nr)   r*   r+   fallback_providersfallback_modelrF  )r#  r$  r%  r  fbs        r   rP  "GatewayRunner._load_fallback_model  s    
	#m3H  (W55,,r*00bC 6WW12WWcgg>N6OWWSWI  65
  		s?   &B5 B5 B"B5 :B5 
B5 B5 "B2	-B5 5CCc                    < V ^8  d   QhRS[ /# r   r   )r   r2  s   "r   r   r3    s      t r   c                 L    ^ RI p \        R,          pVP                  4       '       dV   \        VRR7      ;_uu_ 4       pV P	                  V4      ;'       g    / pRRR4       XP                  R/ 4      ;'       g    / #  / #   + '       g   i     L/; i  \         d     / # i ; i)z9Load optional smart cheap-vs-strong model routing config.Nr)   r*   r+   smart_model_routingrF  r9  s       r   rR  'GatewayRunner._load_smart_model_routing
  s    	#m3H  (W55,,r*00bC 6ww4b9??R? ! 	 65  			rH  c                    < V ^8  d   QhRS[ /# r   r|  )r   r2  s   "r   r   r3    s     \ \T \r   c           	       "   \         P                  R4       \         P                  RV P                  P                  4        ^ RIHp V! 4       pV'       d   VR8w  d   \         P                  RV4        ^ RIHp T! RRR	7       \        ;QJ d    R
 R8 4       F  '       g   K   RM	  RM! R
 R8 4       4      p\        P                  ! RR4      P                  4       R99   ;'       g5    \        ;QJ d    R R: 4       F  '       g   K   RM	  RM! R R: 4       4      pT'       g   T'       g   \         P                  R4       T P                  P                  4         ^ RIHp TP%                  4       pT'       d   \         P                  RT4       ^ p	^ p
. p. pT P                  P&                  P)                  4        EFA  w  rTP*                  '       g   K  T
^,          p
T P-                  Y4      pT'       g#   \         P                  RTP.                  4       K^  TP1                  T P2                  4       TP5                  T P6                  4       TP9                  T P:                  4       \         P                  RTP.                  4        TP=                  4       G Rj  xL
 pT'       dL   YP>                  T&   T PA                  T4       T	^,          p	\         P                  RTP.                  4       EK;  \         P                  RTP.                  4       TPB                  '       d   TPD                  '       d   TMTpTPG                  TP.                   RTPH                   24       TPD                  '       d3   RTR^R\J        PL                  ! 4       ^,           /T PN                  T&   EK  EK  TPG                  TP.                   R24       RTR^R\J        PL                  ! 4       ^,           /T PN                  T&   EKD  	  T	^ 8X  d   T'       dL   RPS                  T4      p\         PQ                  RT4        ^ RIHp T! R TR	7       T PU                  T4       R# T
^ 8  dE   RPS                  T4      ;'       g    R!p\         PQ                  R"T4        ^ RIHp T! R TR	7       R# \         P                  R#4       \         P                  R$4       T P>                  T PV                  n        RT n,         ^ RIHp T! R%RR	7       \[        T P                  P\                  4      pT'       d   \         P                  R&T4       T P                  P_                  R'R(T P>                  Pa                  4        Uu. uF  pTP.                  NK  	  up/4      G Rj  xL
  T	^ 8  d   \         P                  R)T	4        ^ R*I1H2p T! T P>                  4      p\g        R+ TPi                  R(/ 4      Pk                  4        4       4      p\         P                  R,T4       T Pm                  4       G Rj  xL
 pT'       g{   \        ;QJ d4    R. \n        R/,          \n        R0,          3 4       F  '       g   K   RM)	  RM%! R. \n        R/,          \n        R0,          3 4       4      '       d   T Pq                  4         ^ RIHp TPr                  '       dh   TPr                  Pu                  ^ 4      p\v        Px                  ! T P{                  T4      4       \         P                  R1TPi                  R24      4       Ky   \v        Px                  ! T P}                  4       4       T PN                  '       dK   \         P                  R4\[        T PN                  4      R5PS                  R6 T PN                   4       4      4       \v        Px                  ! T P                  4       4       \         P                  R74       R#   \         d     ELi ; i  \         d     ELi ; i  \         d"   p\         P                  RT4        Rp?ELRp?ii ; i EL  \         d}   p\         PQ                  RTP.                  T4       TPG                  TP.                   RT 24       RTR^R\J        PL                  ! 4       ^,           /T PN                  T&    Rp?EK  Rp?ii ; i  \         d     ELi ; i  \         d     R# i ; i  \         d     ELi ; iu upi  ELr  \         d"   p\         P                  R-T4        Rp?ELRp?ii ; i EL  \         d"   p\         PQ                  R3T4        Rp?EL2Rp?ii ; i5i);zw
Start the gateway and all configured platform adapters.

Returns True if at least one adapter connected successfully.
zStarting Hermes Gateway...zSession storage: %s)get_active_profile_namer  zActive profile: %s)write_runtime_statusstartingNgateway_stater  c              3   N   "   T F  p\         P                  ! V4      x  K  	  R # 5ir9  )r   r   r   vs   & r   r   &GatewayRunner.start.<locals>.<genexpr>.  s%      
0 IIaLL0   #%TFGATEWAY_ALLOW_ALL_USERSrk   c              3   r   "   T F-  p\         P                  ! VR 4      P                  4       R9   x  K/  	  R# 5i)rk   Ntruerx   yes)r   r   r   r[  s   & r   r   r]  :  s6      	e
0 IIa""$(<<0s   57zNo user allowlists configured. All unauthorized users will be denied. Set GATEWAY_ALLOW_ALL_USERS=true in ~/.hermes/.env to allow open access, or configure platform allowlists (e.g., TELEGRAM_ALLOWED_USERS=your_id).r6  z5Recovered %s background process(es) from previous runzProcess checkpoint recovery: %szNo adapter available for %szConnecting to %s...u   ✓ %s connectedu   ✗ %s failed to connect: r  r  r  z: failed to connectu   ✗ %s error: %sz; z0Gateway hit a non-retryable startup conflict: %sstartup_failedz4all configured messaging platforms failed to connectz?Gateway failed to connect any configured messaging platform: %szNo messaging platforms enabled.z5Gateway will continue running for cron job execution.runningz%s hook(s) loadedzgateway:startupr  z#Gateway running with %s platform(s)build_channel_directoryc              3   8   "   T F  p\        V4      x  K  	  R # 5ir9  )r   )r   chss   & r   r   r]    s     W/V3s88/V   z%Channel directory built: %d target(s)z"Channel directory build failed: %sc              3   B   "   T F  pVP                  4       x  K  	  R # 5ir9  )r   )r   r   s   & r   r   r]    s#       
 KKMMs   .update_pending.json.update_pending.claimed.jsonz(Resumed watcher for recovered process %sr  z!Recovered watcher setup error: %sz;Starting reconnection watcher for %d failed platform(s): %s, c              3   8   "   T F  qP                   x  K  	  R # 5ir9  r   r   ps   & r   r   r]    s     B+Aa''+Ark  zPress Ctrl+C to stop)TELEGRAM_ALLOWED_USERSDISCORD_ALLOWED_USERSWHATSAPP_ALLOWED_USERSSLACK_ALLOWED_USERSSIGNAL_ALLOWED_USERSSIGNAL_GROUP_ALLOWED_USERSEMAIL_ALLOWED_USERSSMS_ALLOWED_USERSMATTERMOST_ALLOWED_USERSMATRIX_ALLOWED_USERSDINGTALK_ALLOWED_USERSFEISHU_ALLOWED_USERSWECOM_ALLOWED_USERSGATEWAY_ALLOWED_USERSra  )TELEGRAM_ALLOW_ALL_USERSDISCORD_ALLOW_ALL_USERSWHATSAPP_ALLOW_ALL_USERSSLACK_ALLOW_ALL_USERSSIGNAL_ALLOW_ALL_USERSEMAIL_ALLOW_ALL_USERSSMS_ALLOW_ALL_USERSMATTERMOST_ALLOW_ALL_USERSMATRIX_ALLOW_ALL_USERSDINGTALK_ALLOW_ALL_USERSFEISHU_ALLOW_ALL_USERSWECOM_ALLOW_ALL_USERS)@r  r  r  rU  hermes_cli.profilesrU  r   gateway.statusrV  r   r   r   r   r  rr  discover_and_loadrT  r7  recover_from_checkpointr  r  enabled_create_adapterr   set_message_handler_handle_messageset_fatal_error_handlerr  set_session_storerV  connectrE  r  has_fatal_errorr  r   r
  r  r  rj  r  r   r  rW  rX  r   loaded_hooksemitkeysgateway.channel_directoryrh  sumr   values_send_update_notificationr   #_schedule_update_notification_watchpending_watchersr   rY  create_task_run_process_watcher_session_expiry_watcher_platform_reconnect_watcher)rv  rU  _profilerV  _any_allowlist
_allow_allr7  	recoveredrx  connected_countenabled_platform_countstartup_nonretryable_errorsstartup_retryable_errorsr  r  r   successtargetr  
hook_countrr  rh  	directorych_countnotifiedwatchers   &                         r   startGatewayRunner.start  s     	01)4;;+C+CD	C.0HH	10(;	; ztL
  
0
 
0
 
 YY8"=CCEI]] 	
 	
adad 	e
0	e
adadad 	e
0	e
 	b

 jNN[ 	

$$&	A?(@@BISU^_ !"13#.0  *.)>)>)D)D)F%H"***"a'"**8EG<hnnM ''(<(<=++D,L,LM%%d&8&89 KK-x~~>+ ' 11.5MM(+::7C#q(OKK 2HNNCNN#=x~~N...  '<<< 5!< 
 '~~.b1L1L0MN #888 (/ *A ,dnn.>.C@D228< 9 177'~~..AB
 %o&($..*:R*?<..x8_ *G| a*#>?OQWXC(7GU[\ ((0%)#;<vv@v^`fgC(7GU[\ NN<=KKOP )-%	; ydK
 001
KK+Z8jjoo/4==+=+=+?@+?a!''+?@2
  	 	 QKK=O	DI/>IWy}}["/M/T/T/VWWHKK?J 7799CC  
 55== 
CCC  
 55== 
 
 
 446	A?"333*;;??B##D$=$=g$FGFT`Hab 4 	D88:; !!!KKMD**+		B4+A+ABB
 	D<<>?*+_  		
  		T  	ANN<a@@	A6 2D  /C(//8>>2B"QC0HI o $.."2R"74&&x00	" !  !   		 A	  	DNN?CC	D
 :"  	ALL<a@@	As&  A e,2_- 6_? 
e,e,%Ae,5e,	e,&e,./e,` <` C;e,a!a "a.Aa6e,91a+a=?a=/a,e,2Aa?e,'e,;c 1e,=e,c 'Ae,6c1 A0e,6de,d!e,9Ad e,*d:+e,7
e,)e,.2e,!e,2d= 
A'd= 16e,(Be,-_<8e,;_<<e,?`
e,`e,`=`82e,8`==e, ac
A0c>e,c

e,ce,ce,c.*e,-c..e,1d <e,?d  	e,d7d2,e,2d77e,=e)e$e,$e))e,,  c                    < V ^8  d   QhRS[ /# )r   interval)int)r   r2  s   "r   r   r3    s     e' e'c e'r   c           	     F	  "   \         P                  ! ^<4      G Rj  xL
  / p^pV P                  '       Ed    V P                  P	                  4        . p\        V P                  P                  P                  4       4       FN  w  rVVP                  '       d   K  V P                  P                  V4      '       g   K<  VP                  WV34       KP  	  V'       d   / pV FL  w  rVP                  R4      p
\        V
4      ^8  d
   V
^,          MRpVP                  V^ 4      ^,           W{&   KN  	  RP                  R \        VP                  4       4       4       4      p\         P#                  R\        V4      V4       V F  w  rV V P%                  VP&                  4      G Rj  xL
  V P(                  P                  V4      pV'       d.   V\*        Jd$    \-        VR4      '       d   VP/                  4        V P                  P2                  ;_uu_ 4        RVn        V P                  P5                  4        RRR4       \         P7                  R	VP&                  4       VP9                  VP&                  R4       K  	  V'       d[   \=        R V 4       4      p\        V4      V,
          pV'       d   \         P#                  RVV4       M\         P#                  RV4       \?        V4       F7  pV P                  '       g    EK  \         P                  ! ^4      G Rj  xL
  K9  	  EK  R#  EL EL  \0         d     ELIi ; i  + '       g   i     EL; i  \0         Ed   pTP                  TP&                  ^ 4      ^,           pYTP&                  &   Y8  d   \         P;                  R
YP&                  T4       T P                  P2                  ;_uu_ 4        RTn        T P                  P5                  4        RRR4       M  + '       g   i     M; iTP9                  TP&                  R4        Rp?EK  \         P7                  RYTP&                  T4        Rp?EK  Rp?ii ; i  \0         d"   p\         P7                  RT4        Rp?ELRp?ii ; i EL}5i)a  Background task that proactively flushes memories for expired sessions.

Runs every `interval` seconds (default 5 min).  For each session that
has expired according to its reset policy, flushes memories in a thread
pool and marks the session so it won't be flushed again.

This means memories are already saved by the time the user sends their
next message, so there's no blocking delay.
Nr   r  ro  c              3   4   "   T F  w  rV R V 2x  K  	  R# 5i)r   Nr   )r   rr  cs   &  r   r   8GatewayRunner._session_expiry_watcher.<locals>.<genexpr>  s       ./Itq1#Qqc
/Is   z)Session expiry: %d sessions to flush (%s)shutdown_memory_providerTz%Memory flush completed for session %szeMemory flush gave up after %d attempts for %s: %s. Marking as flushed to prevent infinite retry loop.z&Memory flush failed (%d/%d) for %s: %sc              3   R   "   T F  w  rVP                   '       g   K  ^x  K  	  R# 5i)   N)memory_flushed)r   r   rx  s   &  r   r   r  H  s       #&6da!:J:J&6s   '
'z1Session expiry done: %d flushed, %d pending retryzSession expiry done: %d flushedz Session expiry watcher error: %s) rY  sleeprX  rV  _ensure_loadedr   _entriesr  r  _is_session_expiredr   r   r   r   r   sortedr  r  r  r  r_  _AGENT_PENDING_SENTINELr  r  r   _lock_saver  r   r  r  range)rv  r  _flush_failures_MAX_FLUSH_RETRIES_expired_entriesr;  entry
_platforms_k_e_parts_plat_plat_summarycached_agentrx  failures_flushed_failedr   s   &&                 r   r  %GatewayRunner._session_expiry_watcher  s     mmB*,mmmRD""113#% "&t'9'9'B'B'H'H'J"KJC+++ --AA%HH $++SL9 #L $ 24J"2!##-0[1_q	),6NN5!,Dq,H
) #3 %)II ./5j6F6F6H/I. %M KKC,-}
 #3JC%"889I9IJJJ'+';';'?'?'D'L@W,W%#*<9S#T#T$0$I$I$K
 "//55537E0 ..446 6 C!,, (++E,<,<dC) #3P $" #&6#  H ""23h>GO$g
 =x 8_}}}mmA&&& %k  	 B K $- % $% 655 % #2#6#6u7G7G#Ka#O<D(8(89#9"NN!U (*:*:A
 "&!3!3!9!9!97; 4 $ 2 2 8 8 : ":!9!9!9 ,//0@0@$GG"LL H (e>N>NPQ B  D?CCD 's	  R!L/R!BQ/ <Q/ B*Q/ M%L2&&M
M"L5:M"M:AM>Q/ 
AQ/ R!Q/ $=R!!R"R!2M5M MMMM	MQ,'A6Q'"P	?	Q'P$Q'7Q/ >"Q' Q/ 'Q,,Q/ /R:RR!RR!c                   < V ^8  d   QhRR/# r   r   )r   r2  s   "r   r   r3  ]  s     d' d'4 d'r   c                  "   ^pRp\         P                  ! ^
4      G Rj  xL
  V P                  '       Ed   V P                  '       gH   \	        ^4       F6  pV P                  '       g    R# \         P                  ! ^4      G Rj  xL
  K8  	  Kl  \
        P                  ! 4       p\        V P                  P                  4       4       EF  pV P                  '       g    R# V P                  V,          pWFR,          8  d   K;  VR,          V8  d8   \        P                  RVP                  VR,          4       V P                  V K  VR,          pVR,          ^,           p\        P                  RVP                  W4        V P                  WW4      p	V	'       g1   \        P                  RVP                  4       V P                  V EK  V	P                  V P                  4       V	P!                  V P"                  4       V	P%                  V P&                  4       V	P)                  4       G Rj  xL
 p
V
'       d   YP*                  V&   V P-                  V	4       V P*                  V P.                  n        V P                  V \        P                  R	VP                  4        ^ R
IHp V! V P*                  4       EK  V	P6                  '       dN   V	P8                  '       g<   \        P                  RVP                  V	P:                  4       V P                  V EKW  \=        ^^V^,
          ,          ,          V4      pWR&   \
        P                  ! 4       V,           VR&   \        P                  RVP                  V4       EK  	  \	        ^
4       F6  pV P                  '       g    R# \         P                  ! ^4      G Rj  xL
  K8  	  EK  R#  EL ELQ EL  \4         d     EK#  i ; i  \4         dr   p\=        ^^T^,
          ,          ,          T4      pYR&   \
        P                  ! 4       T,           TR&   \        P                  RTP                  Y4        Rp?EK  Rp?ii ; i L5i)u   Background task that periodically retries connecting failed platforms.

Uses exponential backoff: 30s → 60s → 120s → 240s → 300s (cap).
Stops retrying a platform after 20 failed attempts or if the error
is non-retryable (e.g. bad auth token).
r  Nr  r  z+Giving up reconnecting %s after %d attemptsr  z"Reconnecting %s (attempt %d/%d)...zGReconnect %s: adapter creation returned None, removing from retry queueu   ✓ %s reconnected successfullyrg  zAReconnect %s: non-retryable error (%s), removing from retry queuez&Reconnect %s failed, next retry in %dsz)Reconnect %s error: %s, next retry in %ds)rY  r  rX  rj  r  r  r  r   r  r  r  r   r  r  r  r  r  r  r  rV  r  rE  r  rW  r  rh  r   r  r  r
  min)rv  _MAX_ATTEMPTS_BACKOFF_CAPr   nowr  r  r  attemptr   r  rh  backoffrx  s   &             r   r  )GatewayRunner._platform_reconnect_watcher]  sw     mmBmmm)))rA===!--*** # .."C !7!7!<!<!>?}}}--h7l++
#}4NNE Z(8 ..x8"&x.z*Q.8NNG
3"228MG"e$NN !228< //0D0DE33D4T4TU--d.@.@A$+OO$55G29h/>>wG8<,,5 228<$Ex~~V!Y3DMMB
 #2227;X;X;X"NN c (0K0K !% 6 6x @&)"gk0B*C\&RG/6,151AG1KD."KK H (} @X 2Y}}}mmA&&& m  	  +P 6  ) ! !$ ! !"gk(:";\JG'.$)-)9G)CD&NNC  	 's   Q1OQ1Q1
<Q1OC<Q1AO0
Q1A$O01O2O0>A'O0&O>Q1O0O0%8O0Q1 A%O0AQ1Q/Q1Q1O0O-(O0)Q1,O--O00Q,;A%Q' Q1'Q,,Q1c                   < V ^8  d   QhRR/# r   r   )r   r2  s   "r   r   r3    s     1' 1'D 1'r   c                  "   \         P                  R4       RV n        \        V P                  P                  4       4       Fe  w  rV\        J d   K   VP                  R4       \         P                  RVR,          4        \        VR4      '       d   VP                  4        Ke  Kg  	  \        V P                  P                  4       4       FW  w  rE VP                  4       G Rj  xL
   VP                  4       G Rj  xL
  \         P                  R
VP                  4       KY  	  \        V P"                  4       F  pVP%                  4        K  	  V P"                  P'                  4        V P                  P'                  4        V P                  P'                  4        V P(                  P'                  4        V P*                  P'                  4        V P,                  P/                  4        ^ RIHpHp V! 4         V! RV P6                  R7       \         P                  R4       R#   \         d"   p\         P                  RT4        Rp?ELRp?ii ; i  \         d     EK(  i ; i EL  \         d-   p\         P                  R	TP                  T4        Rp?ELRp?ii ; i EL  \         d.   p\         P!                  RTP                  T4        Rp?EK  Rp?ii ; i  \         d     Li ; i5i)z-Stop the gateway and disconnect all adapters.zStopping gateway...FzGateway shutting downz8Interrupted running agent for session %s during shutdownN   Nz-Failed interrupting agent during shutdown: %sNr  u'   ✗ %s background-task cancel error: %su   ✓ %s disconnectedu   ✗ %s disconnect error: %s)remove_pid_filerV  stoppedrX  zGateway stopped)r  r  rX  r   r_  r  r  	interruptr  r   r  r  rE  cancel_background_tasksr   r  r  ru  cancelr  ra  ri  r[  r   r  r  rV  r^  )	rv  r   rm   rx  r  r   _taskr  rV  s	   &        r   r  GatewayRunner.stop  sZ    )*"&t';';'A'A'C"DK//Q 78WYdehYij5"<==224 > #E "&dmm&9&9&;!<H[55777O((***18>>B "= $001ELLN 2$$&""$$$&%%'  "H	 ydFWFWX 	%&M  QLaPPQ  
 8 [FXYZZ[ + O:HNNANNO$  		s   AK:.H,"I%.K:I1'I.(I1-J. J+$J.%CK:K) K:,I7IK:IK:I+&K:*I++K:.I11J(<!J#K:#J((K:+J..K&9!K!K:!K&&K:)K74K:6K77K:c                   < V ^8  d   QhRR/# r   r   )r   r2  s   "r   r   r3    s     * * *r   c                V   "   V P                   P                  4       G Rj  xL
  R#  L5i)zWait for shutdown signal.N)r[  waitr  s   &r   wait_for_shutdownGatewayRunner.wait_for_shutdown  s     ""'')))s   )')c                <   < V ^8  d   QhRS[ RS[RS[S[,          /# )r   r  r  r   )r|   r   r   r   )r   r2  s   "r   r   r3    s4     { {{ { 
%	&	{r   c                	   \        VR4      '       d   \        VP                  \        4      '       db   VP                  P	                  RV P
                  P                  4       VP                  P	                  R\        V P
                  RR4      4       V\        P                  8X  d5   ^ RI
HpHp V! 4       '       g   \        P                  R4       R# V! V4      # V\        P                  8X  d5   ^ RIHpHp V! 4       '       g   \        P                  R	4       R# V! V4      # V\        P&                  8X  d5   ^ R
IHpHp V! 4       '       g   \        P                  R4       R# V! V4      # V\        P.                  8X  d5   ^ RIHp	Hp
 V
! 4       '       g   \        P                  R4       R# V	! V4      # V\        P6                  8X  d5   ^ RIHpHp V! 4       '       g   \        P                  R4       R# V! V4      # V\        P>                  8X  d5   ^ RI H!pH"p V! 4       '       g   \        P                  R4       R# V! V4      # V\        PF                  8X  d5   ^ RI$H%pH&p V! 4       '       g   \        P                  R4       R# V! V4      # V\        PN                  8X  d5   ^ RI(H)pH*p V! 4       '       g   \        P                  R4       R# V! V4      # V\        PV                  8X  d5   ^ RI,H-pH.p V! 4       '       g   \        P                  R4       R# V! V4      # V\        P^                  8X  d5   ^ RI0H1pH2p V! 4       '       g   \        P                  R4       R# V! V4      # V\        Pf                  8X  d5   ^ RI4H5pH6p V! 4       '       g   \        P                  R4       R# V! V4      # V\        Pn                  8X  d5   ^ RI8H9pH:p V! 4       '       g   \        P                  R4       R# V! V4      # V\        Pv                  8X  d5   ^ RI<H=pH>p V! 4       '       g   \        P                  R4       R# V! V4      # V\        P~                  8X  d5   ^ R I@HApHBp V! 4       '       g   \        P                  R!4       R# V! V4      # V\        P                  8X  d>   ^ R"IDHEpHFp  V ! 4       '       g   \        P                  R#4       R# V! V4      p!V V!nG        V!# R# )$z.Create the appropriate adapter for a platform.extrar  r  F)TelegramAdaptercheck_telegram_requirementsz+Telegram: python-telegram-bot not installedN)DiscordAdaptercheck_discord_requirementsz!Discord: discord.py not installed)WhatsAppAdaptercheck_whatsapp_requirementsz8WhatsApp: Node.js not installed or bridge not configured)SlackAdaptercheck_slack_requirementszGSlack: slack-bolt not installed. Run: pip install 'hermes-agent[slack]')SignalAdaptercheck_signal_requirementsz8Signal: SIGNAL_HTTP_URL or SIGNAL_ACCOUNT not configured)HomeAssistantAdaptercheck_ha_requirementsz:HomeAssistant: aiohttp not installed or HASS_TOKEN not set)EmailAdaptercheck_email_requirementszQEmail: EMAIL_ADDRESS, EMAIL_PASSWORD, EMAIL_IMAP_HOST, or EMAIL_SMTP_HOST not set)
SmsAdaptercheck_sms_requirementszJSMS: aiohttp not installed or TWILIO_ACCOUNT_SID/TWILIO_AUTH_TOKEN not set)DingTalkAdaptercheck_dingtalk_requirementszLDingTalk: dingtalk-stream not installed or DINGTALK_CLIENT_ID/SECRET not set)FeishuAdaptercheck_feishu_requirementsz?Feishu: lark-oapi not installed or FEISHU_APP_ID/SECRET not set)WeComAdaptercheck_wecom_requirementsz;WeCom: aiohttp not installed or WECOM_BOT_ID/SECRET not set)MattermostAdaptercheck_mattermost_requirementszJMattermost: MATTERMOST_TOKEN or MATTERMOST_URL not set, or aiohttp missing)MatrixAdaptercheck_matrix_requirementsz[Matrix: matrix-nio not installed or credentials not set. Run: pip install 'matrix-nio[e2e]')APIServerAdaptercheck_api_server_requirementsz!API Server: aiohttp not installed)WebhookAdaptercheck_webhook_requirementszWebhook: aiohttp not installed)Hr  r  r  r   
setdefaultr  r  r   r|   TELEGRAMgateway.platforms.telegramr  r  r  r  DISCORDgateway.platforms.discordr  r  WHATSAPPgateway.platforms.whatsappr  r  SLACKgateway.platforms.slackr  r  SIGNALgateway.platforms.signalr  r   HOMEASSISTANTgateway.platforms.homeassistantr  r  EMAILgateway.platforms.emailr  r  SMSgateway.platforms.smsr  r  DINGTALKgateway.platforms.dingtalkr  r  FEISHUgateway.platforms.feishur	  r
  WECOMgateway.platforms.wecomr  r  
MATTERMOSTgateway.platforms.mattermostr  r  MATRIXgateway.platforms.matrixr  r  
API_SERVERgateway.platforms.api_serverr  r  WEBHOOKgateway.platforms.webhookr  r  gateway_runner)"rv  r  r  r  r  r  r  r  r  r  r  r  r   r  r  r  r  r  r  r  r  r	  r
  r  r  r  r  r  r  r  r  r  r  r   s"   &&&                               r   r  GatewayRunner._create_adapter  s    67##
6<<(F(FLL##)33 LL##*%?G
 x(((_.00LM"6**)))\-//BC!&))***_.00YZ"6**'V+--hi''(Y,..YZ ((///c(**[\'//'V+--rs''%P)++klf%%***_.00mn"6**(Y,..`a (('V+--\]'',,,e022kl$V,,(Y,..|} ((,,,d022BC#F++)))\-//?@$V,G%)G"Nr   c                &   < V ^8  d   QhRS[ RS[/# r  )r   r}  )r   r2  s   "r   r   r3  w  s     c- c-- c-D c-r   c                   VP                   \        P                  \        P                  39   d   R# VP                  pV'       g   R# \        P
                  R\        P                  R\        P                  R\        P                  R\        P                  R\        P                  R\        P                  R	\        P                  R
\        P                  R\        P                  R\        P                  R\        P                   R/p\        P
                  R\        P                  R\        P                  R\        P                  R\        P                  R\        P                  R\        P                  R\        P                  R\        P                  R\        P                  R\        P                  R\        P                   R/pVP#                  VP                   R4      pV'       d-   \$        P&                  ! VR4      P)                  4       R#9   d   R# VP                   '       d   VP                   P*                  MRpV P,                  P/                  Wb4      '       d   R# \$        P&                  ! VP#                  VP                   R4      R4      P1                  4       p\$        P&                  ! RR4      P1                  4       pV'       g1   V'       g)   \$        P&                  ! RR4      P)                  4       R#9   # \3        4       p	V'       d(   V	P5                  R VP7                  R4       4       4       V'       d(   V	P5                  R  VP7                  R4       4       4       R!V	9   d   R# V0p
R"V9   d(   V
P9                  VP7                  R"4      ^ ,          4       VP                   \        P                  8X  dv   \3        4       pV	 F  pVP5                  \;        V4      4       K  	  V'       d   Tp	V
P5                  \;        V4      4       \=        V4      pV'       d   V
P9                  V4       \?        W,          4      # )$a'  
Check if a user is authorized to use the bot.

Checks in order:
1. Per-platform allow-all flag (e.g., DISCORD_ALLOW_ALL_USERS=true)
2. Environment variable allowlists (TELEGRAM_ALLOWED_USERS, etc.)
3. DM pairing approved list
4. Global allow-all (GATEWAY_ALLOW_ALL_USERS=true)
5. Default: deny
TFrs  rt  ru  rv  rw  ry  rz  r{  r|  r}  r~  r  r  r  r  r  r  r  r  r  r  r  r  r  rk   r  r_  c              3   p   "   T F,  qP                  4       '       g   K  VP                  4       x  K.  	  R # 5ir9  r   r   uids   & r   r   4GatewayRunner._is_user_authorized.<locals>.<genexpr>  s%     c6SsW`W`Wb{syy{{6S   66,c              3   p   "   T F,  qP                  4       '       g   K  VP                  4       x  K.  	  R # 5ir9  r9  r:  s   & r   r   r<    s%     a6QsU^U^U`{syy{{6Qr=  *r   ra  ) r  r|   r   r2  user_idr  r  r  r  r  r"  r$  r,  r.  r&  r(  r*  r   r   r   r   r   rp  is_approvedr   r   r  r   r   r   r   r}  )rv  r  rA  platform_env_mapplatform_allow_all_mapplatform_allow_all_varplatform_nameplatform_allowlistglobal_allowlistallowed_ids	check_idsnormalized_allowed_ids
allowed_idnormalized_user_ids   &&            r   _is_user_authorized!GatewayRunner._is_user_authorizedw  s0     ??x55x7G7GHH.. 757NN1OO3NN1LL-!;OO37OO3NN1
 979NN3OO5NN3LL/!=OO59OO5NN3"
  "8!;!;FOOR!P!bii0F&K&Q&Q&SWk&k 28--b))-AA  YY'7';';FOOR'PRTU[[]99%<bAGGI!*:996;AACG[[[ ec6H6N6Ns6Scca6F6L6LS6Qaa +I	'>MM'--,Q/0 ??h///%(U")
&--.KJ.WX *%4:7CD!?!H!01I+,,r   c                6   < V ^8  d   QhRS[ S[,          RS[/# )r   r  r   )r   r|   r   )r   r2  s   "r   r   r3    s       hx6H S r   c                v    \        V RR4      pV'       d$   \        VR4      '       d   VP                  V4      # R# )z=Return how unauthorized DMs should be handled for a platform.r  Nget_unauthorized_dm_behaviorpair)r   r  rR  )rv  r  r  s   && r   _get_unauthorized_dm_behavior+GatewayRunner._get_unauthorized_dm_behavior  s4    x.gf&DEE66x@@r   c                6   < V ^8  d   QhRS[ RS[S[,          /# r   r   r   r   r   r   )r   r2  s   "r   r   r3    s#     P: P:< P:HSM P:r   c                ,  "   VP                   pV P                  V4      '       Eg   \        P                  RVP                  VP
                  VP                  P                  4       VP                  R8X  Ed   V P                  VP                  4      R8X  Edm   VP                  '       d   VP                  P                  MRpV P                  P                  W2P                  4      '       d   R# V P                  P                  Y2P                  VP
                  ;'       g    R4      pV'       d^   V P                  P                  VP                  4      pV'       d/   VP                  VP                   RV RV R	V R
24      G Rj  xL
  R# V P                  P                  VP                  4      pV'       d%   VP                  VP                   R4      G Rj  xL
  V P                  P#                  W2P                  4       R# V P%                  V4      p\'        V R/ 4      pVP                  V4      '       d   VP(                  ;'       g    RP+                  4       pVP-                  4       p	V	R9   d   Rp
MV	R9   d   Rp
MTp
V
'       d|   \.        R,          p VP1                  R4      pVP3                  V
4       VP5                  V4       TP9                  TR4       \;        T
4      ^8:  d   T
MT
R,          R,           pRT R2# \=        \>        P@                  ! RR4      4      pV PB                  P                  V^ 4      pW`PD                  9   Edi   V'       Ed`   \F        PF                  ! 4       V,
          pV PD                  P                  V4      p\=        R4      pRpV'       d~   \I        VR4      '       dl    VPK                  4       pVP                  R\=        R4      4      pRVP                  RR4       R VR! R"VP                  R#^ 4       R$VP                  R%^ 4       2pV^ 8  d   \O        V^
,          R&4      M
\=        R4      pV^ 8  ;'       d    VV8  ;'       g    VV8  pV'       dK   \        P                  R'VR(,          VVVV4       V PD                  V V PB                  P9                  VR4       W`PD                  9   EdW   VP-                  4       R)8X  d   V PQ                  V4      G Rj  xL
 # ^ R*I)H*p VP-                  4       pV'       d	   V! V4      MRpV'       d   VPV                  R+8X  d   V PD                  P                  V4      pV'       d   V\X        Jd   VP[                  R,4       V P                  P                  VP                  4      pV'       d$   \I        VR-4      '       d   VP]                  V4       V P^                  P9                  VR4       W`PD                  9   d   V PD                  V \        Pa                  R.VR,          4       R/# V'       d   VPV                  R08X  d   V PD                  P                  V4      pV'       d   V\X        Jd   VP[                  R14       V P                  P                  VP                  4      pV'       d$   \I        VR-4      '       d   VP]                  V4       V P^                  P9                  VR4       W`PD                  9   d   V PD                  V V Pc                  V4      G Rj  xL
 # VP-                  4       R9   d   VPe                  4       P+                  4       pV'       g   R2# V P                  P                  VP                  4      pV'       dB   ^ R3I3H4pH5p V! VVPl                  VP                   VPn                  R47      pVVP^                  V&   R5# V'       d   VPV                  R68X  d   R7# V'       dU   VPV                  R9   dD   VPV                  R8X  d   V Pq                  V4      G Rj  xL
 # V Ps                  V4      G Rj  xL
 # VPt                  \j        Pv                  8X  Ed}   \        Py                  R8VR,          4       V P                  P                  VP                  4      pV'       Ed0   WeP^                  9   Ed   VP^                  V,          p \'        V R9R4      \j        Pv                  8X  d   V Pz                  P}                  VPz                  4       V P~                  P}                  VP~                  4       VP(                  '       do   V P(                  '       g   VP(                  V n        R# VP(                  V P(                  9  d/   V P(                   R:VP(                   2P+                  4       V n        R# WP^                  V&    R# WP^                  V&   R# V PD                  P                  V4      pV\X        J d   VP-                  4       R+8X  d=   W`PD                  9   d   V PD                  V \        Pa                  R;VR,          4       R<# V P                  P                  VP                  4      pV'       d   WP^                  V&   R# \        Py                  R=VR,          4       VP[                  VP(                  4       W`P^                  9   d3   V P^                  V;;,          R>VP(                  ,           ,          uu&   R# VP(                  V P^                  V&   R# TP-                  4       p!^ R?I)H@p"H*p# V!'       d   V!V"9   d~   V P                  P                  R@V! 2RAVP                  '       d   VP                  P                  MRRBVP                  RCV!RDVPe                  4       P+                  4       /4      G Rj  xL
  V!'       d	   V#! V!4      MRp$V$'       d   V$PV                  MT!p%V%R08X  d   V Pc                  V4      G Rj  xL
 # V%RE8X  d   V P                  V4      G Rj  xL
 # V%RF8X  d   V P                  V4      G Rj  xL
 # V%RG8X  d   V P                  V4      G Rj  xL
 # V%R)8X  d   V PQ                  V4      G Rj  xL
 # V%R+8X  d   V P                  V4      G Rj  xL
 # V%RH8X  d   V P                  V4      G Rj  xL
 # V%RI8X  d   V P                  V4      G Rj  xL
 # V%RJ8X  d   V P                  V4      G Rj  xL
 # V%R68X  d   V P                  V4      G Rj  xL
 # V%RK8X  d   V P                  V4      G Rj  xL
 # V%RL8X  d   V P                  V4      G Rj  xL
 # V%RM8X  dZ    ^ RNIMHNp&HOp' VPe                  4       P+                  4       p(V&! V(4      p)V'! ROV(VRPV) 2RQ7      Vn        VP(                  '       g   RR# Rp%V%RU8X  d   V P                  V4      G Rj  xL
 # V%RV8X  d   V P                  V4      G Rj  xL
 # V%RW8X  d   V P                  V4      G Rj  xL
 # V%RX8X  d   V P                  V4      G Rj  xL
 # V%RY8X  d   V P                  V4      G Rj  xL
 # V%RZ8X  d   V P                  V4      G Rj  xL
 # V%R[8X  d   V P                  V4      G Rj  xL
 # V%R8X  d   V Pq                  V4      G Rj  xL
 # V%R8X  d   V Ps                  V4      G Rj  xL
 # V%R\8X  d   V P                  V4      G Rj  xL
 # V%R]8X  d   V P                  V4      G Rj  xL
 # V%R^8X  d   V P                  V4      G Rj  xL
 # V%R_8X  d   V P                  V4      G Rj  xL
 # V%R`8X  d   V P                  V4      G Rj  xL
 # V%Ra8X  d   V P                  V4      G Rj  xL
 # V%Rb8X  d   V P                  V4      G Rj  xL
 # V%Rc8X  d   V P                  V4      G Rj  xL
 # V!'       Ed3   \        V P                  \        4      '       d(   V P                  P                  Rd/ 4      ;'       g    / p*M!\'        V P                  Rd/ 4      ;'       g    / p*\        V*\        4      '       g   / p*V!V*9   Ed   V*V!,          p+V+P                  Re4      Rf8X  d   V+P                  RCR4      p,V,'       d    \        P                  ! V,\        P                  P                  \        P                  P                  Rg7      G Rj  xL
 p-\        P                  ! V-P                  4       ^Rh7      G Rj  xL
 w  p.p/T.;'       g    T/P                  4       P+                  4       p0V0'       d   V0# Ri# RlV! Rm2# V+P                  Re4      Rn8X  d   V+P                  RoR4      P+                  4       p1V1'       dk   V1P                  R$4      '       d   T1MR$V1 2p1V1P                  R$4      p2VPe                  4       P+                  4       p3V1 R	V3 2P+                  4       Vn        T2p!MRlV! Rp2# RlV! Rq2# V!'       d    ^ RrImHnp4 V4! V!P5                  RsRt4      4      p5V5'       da   VPe                  4       P+                  4       p3^ RIcp6V5! V34      p7V6P                  V74      '       d   V7G Rj  xL
 p7V7'       d   \        V74      # R#  V!'       Ed:    ^ RvIMHqp8HOp'Hrp9 V8! 4       p:V9! V!4      p;V;e   V:V;,          P                  RwR4      p<VP                  '       d   VP                  P                  MRp=V='       d&   V<'       d   ^ RxIsHtp> V<V>! V=Ry7      9   d
   RzV< R{V= R|2# VPe                  4       P+                  4       p(V'! V;V(VR}7      p?V?'       d   V?Vn        Mr\        V!4      p@V@'       d   X@# V!P5                  RsRt4      V"9  dF   \        P                  R~T!VP                  '       d   VP                  P                  MR4       RV! R2#  \X        V PD                  V&   \F        PF                  ! 4       V PB                  V&    V P                  WV4      G Rj  xL
 V PD                  P                  V4      \X        J d   V PD                  V V PB                  P9                  VR4       #  EL EL  \6         d&   p\        P                  RT4       RT 2u Rp?# Rp?ii ; i  \L         d     ELi ; i EL EL EL EL E	L- EL EL EL EL ELt ELW EL: EL EL  EL EL EL  \L         d%   p\        P                  RS4       RTT 2u Rp?# Rp?ii ; i EL^ ELA EL$ EL EL EL EL EL ELv ELY EL< EL EL EL EL EL EL ELu ELJ  \        P                   d     Rj# \L         d   pRkT 2u Rp?# Rp?ii ; i EL  \L         d"   p\        Py                  RuT4        Rp?EL%Rp?ii ; i  \L         d"   p\        Py                  RT4        Rp?ELRp?ii ; i EL  T PD                  P                  T4      \X        J d   T PD                  T T PB                  P9                  TR4       i ; i5i)a9  
Handle an incoming message from any platform.

This is the core message processing pipeline:
1. Check user authorization
2. Check for commands (/new, /reset, etc.)
3. Check for running agent and interrupt if needed
4. Get or create session
5. Build context for agent
6. Run agent conversation
7. Return response
z Unauthorized user: %s (%s) on %sdmrS  r  Nrk   z;Hi~ I don't recognize you yet!

Here's your pairing code: `z5`

Ask the bot owner to run:
`hermes pairing approve  r   z<Too many pairing requests right now~ Please try again later!rk  approveydenyn.update_response.tmpz#Failed to write update response: %su/   ✗ Failed to send response to update process: r     …u
   ✓ Sent `z` to the update process.rq     infget_activity_summaryseconds_since_activityz | last_activity=last_activity_desc (.0fzs ago) | iteration=api_call_countr   r  i   zWEvicting stale _running_agents entry for %s (age: %.0fs, idle: %.0fs, timeout: %.0fs)%s:N   Nstatus)resolve_commandr  Stop requestedr   u2   HARD STOP for session %s — session lock releasedJ   ⚡ Force-stopped. The session is unlocked — you can send a new message.newzSession reset requestedzUsage: /queue <prompt>)r   r   )r   r   r  
message_idzQueued for the next turn.r[   u=   Agent is running — wait or /stop first, then switch models.uF   PRIORITY photo follow-up for session %s — queueing without interruptr   r  7   HARD STOP (pending) for session %s — sentinel clearedE   ⚡ Force-stopped. The agent was still starting — session unlocked.z!PRIORITY interrupt for session %sr   )GATEWAY_KNOWN_COMMANDSrm  zcommand:r  rA  r   r   helpcommandsprofile	reasoningverboseyolorY   personalityplan)build_plan_pathbuild_skill_invocation_messagez/planzlSave the markdown plan with write_file to this exact relative path inside the active workspace/backend cwd: )task_idruntime_notez'Failed to load the bundled /plan skill.zFailed to prepare /plan commandzFailed to enter plan mode: retryundosethomecompressusageinsightsz
reload-mcpr  titleresumebranchrollback
backgroundbtwvoicequick_commandstypeexec)stdoutstderrr3   zCommand returned no output.zQuick command timed out (30s).zQuick command error: zQuick command '/z' has no command defined.aliasr  z' has no target defined.z4' has unsupported type (supported: 'exec', 'alias').)get_plugin_command_handlerr   r   z.Plugin command dispatch failed (non-fatal): %s)get_skill_commandsr~  resolve_skill_command_keyr   )get_disabled_skill_namesr  r   z** skill is disabled for z(.
Enable it with: `hermes skills config`r  uO   Unrecognized slash command /%s from %s — replying with unknown-command notice?zUnknown command `/zl`. Type /commands to see what's available, or resend without the leading slash to send as a regular message.z*Skill command check failed (non-fatal): %s)r\  rc  )r^  no)r   q)r\  r^  )wr  rN  r  r  rA  	user_namer  r   	chat_typerT  rp  _is_rate_limitedgenerate_coderE  r   sendr  _record_rate_limitr  r   r   r   get_commandr   with_suffixr  r   r  r   r   floatr   r   r`  r_  r  r  re  r   max_handle_status_commandhermes_cli.commandsrm  r   r  r  r   ra  r  _handle_reset_commandget_command_argsgateway.platforms.baser   r   TEXTrq  _handle_approve_command_handle_deny_commandr   r   r  r   extendr   rt  rr  r  _handle_help_command_handle_commands_command_handle_profile_command_handle_stop_command_handle_reasoning_command_handle_verbose_command_handle_yolo_command_handle_model_command_handle_provider_command_handle_personality_commandagent.skill_commandsr}  r~  	exception_handle_retry_command_handle_undo_command_handle_set_home_command_handle_compress_command_handle_usage_command_handle_insights_command_handle_reload_mcp_command_handle_update_command_handle_title_command_handle_resume_command_handle_branch_command_handle_rollback_command_handle_background_command_handle_btw_command_handle_voice_commandr  r  r   rY  create_subprocess_shell
subprocessPIPEwait_forcommunicatedecodeTimeoutErrorr   lstriphermes_cli.pluginsr  iscoroutiner   r  r  r   r  r  _handle_message_with_agent)Arv  r   r  rF  coder   
_quick_key_update_promptsr?  cmdresponse_textresponse_pathtmprx  r  _raw_stale_timeout	_stale_ts
_stale_age_stale_agent_stale_idle_stale_detail_sa	_wall_ttl_should_evict_resolve_cmd_inner_evt_cmd_cmd_def_innerrunning_agentqueued_text_ME_MTqueued_eventr  r   rt  _resolve_cmd_cmd_def	canonicalr}  r~  user_instruction	plan_pathr  qcmdexec_cmdprocr  r  outputr  target_command	user_argsr  plugin_handler_aior3  r  r  
skill_cmdscmd_key_skill_namer  _get_plat_disabledmsg_unavail_msgsA   &&                                                               r   r  GatewayRunner._handle_message  s      ''//NN=v~~vO_O_agapapavavw4'D,N,Nv,_ci,i9? 5 5i %%66}nnUU))77!>>63C3C3I3Ir "mm//@G%ll"NN::> @77DoQtfAO  "  #mm//@G%ll"NN6   &&99-X 11&9
!$(@"Ez**::##**,C##%C(( #& # # ,/A AQ'33F;CNN=1KK.  ##J5),]);r)A}UXGY\aGa#E7*BCC #299-CT#JK++//
A>	---))y0J//33J?L,KM6L M M	&;;=C"%''*BE%L"QK+CGG4H),T+U V', -''*ww/?'C&DAcggN^`aFbEce " ?QST>T.3T:Z_`eZfI#a'MMK;M,M * *	)  BsOZ&	 ((4''++J=---  "h.!88??? R((*H=E/94N ."5"5"? $ 4 4 8 8 D ]:Q%Q!++,<=--++FOO<ww0EFF//
;&&**:t<!5!55,,Z8PR\]`Rabc ."5"5"> $ 4 4 8 8 D ]:Q%Q!++,EF--++FOO<ww0EFF//
;&&**:t< !5!55,,Z8!77>>>   "n4#446<<>"3--++FOO<^#&(%(XX$||#(#3#3	$L =IG--j92 ."5"5"@V ."5"59L"L!&&)3!%!=!=e!DDD!66u===!![%6%66egqrugvw--++FOO<7!%>%>>#*#<#<Z#H"8^TBkFWFWW$//66u7G7GH$00778I8IJ$zzz'/}}}49JJHM  &+ZZx}}%D7?}}oT%**4V4\4\4^HM
  EJ55jA  AF11*= 0044Z@M 77$$&&0!%9%99 00<KK Y[efi[jkb --++FOO<<A--j9LL<joN##EJJ/333&&z2dUZZ6GG2  6;ZZ&&z2 ##%
 	`w"88**//HWI"6V___FOO11"6>>7..0668	9    -4<(%-HMM7	33E:::225999
"66u===	!55e<<< 44U;;;225999#77>>>	!55e<<<22599933E:::
"66u===%99%@@@9`#(#9#9#;#A#A#C +,<=	;$&DDM;P
 zzzD 	
 33E:::225999	!66u===
"66u===33E:::
"66u===$88???	!55e<<<225999 44U;;;33E::: 44U;;; 44U;;;
"66u===$88???11%88833E::: 7$++t,,!%1A2!F!L!L"!(6F!K!Q!Qrnd33!#.(%g.88F#v-#xx	26H?)0)H)H ('.'9'9'>'>'.'9'9'>'>* $D
 4;3C3CDDTDTDV`b3c-cNFF&,&6&6%>%>%@%F%F%HF-36V9VV "2':STTXXf%0!XXh399;F+1+<+<S+A+A6(|)/s);$)$:$:$<$B$B$D	(.xq%<%B%B%D
"0 "2':RSS-gY6jkk RI "<GOOCQT<U!V! % 6 6 8 > > @I*+I6F''//'-*03v;:d: " 79N 
 01
3G<&
 #-W"5"9"9&""EK5;___FOO11$Ed&*<e*LL"(5Nug VI !J (-'='='?'E'E'G$8!1:C %(

 $<G#DL#++ sC08NNC#5;___FOO11#	 1	 :4 5 O6 ,CZ(.2iik
+		:88
SS ##''
37NN((4##''
D9a>  QNN#H!LLQCPPQH ! , @\ ?: E=l ; : > = < : ? = : ; > A(  9  !BC4QC889
 ; : > > ; > @ = : < ; < < > @ 9 ; $
 .d  '33 D#C( ?%:1##>>?> ". RMqQQR@  NI1MMN$ T ##''
37NN((4##''
D9s  B)AY-,A7AY-$AY-3,AY- )AY-	AR
2AY-=AY-ARA2AY->AY-AY-3AR! BAY- AAY-?A*AS )0AY-AY-'AY-5BAY-9AS&:!AY-AY-.3AY-"AAY-*BAY--3AY-!AAY-)A0AY-AS)>AY-.AY-A
AY-AY-.6AY-$AS,%AY-=AS/>A.AY--BAY-AY-D!AY-CAY-2AY-9AAY-AS2AY-AY-$)AY-AS5AY--AS8.AY-AS;AY--AS>.AY-ATAY--AT.AY-ATAY--AT
.AY-ATAY--AT.AY-ATAY--AT.AY-:AAT AY-AT AY--AU.AY-AUAY--AU.AY-AUAY--AU.AY-AUAY--AU.AY-AU AY--AU#.AY-AU&AY--AU).AY-AU,AY--AU/.AY-AU2AY--AU5.AY-AU8AY--AU;.AY-;AAY-@>!AY-A AAY-B=AAV D	AU>D
-AV D7AVD8AV E&AV E/AV E0AY-E1AV E2AAY-F7AY-GA&AY-H6%AV; IA AV; JAV; J"AV8J#AV; J/
AV; J9AY-J:AV; J;
AY-KAAW* LAW* L/AW* L7AW* MAY-M0AW* NAW* NAY-NAW* N!AY-N"9AW* O!AW* O=7AY-P5AX Q
AXQAX QAAY-RAY-R!ASR,ASSASSAY-SASSAY-SAS#SAY-S"AS#S#AY-S)AY-S,AY-S/AY-S2AY-S5AY-S8AY-S;AY-S>AY-TAY-TAY-TAY-T
AY-TAY-TAY-TAY-TAY-TAUT$AUT=AUT>AY-UAUUAY-UAY-UAY-UAY-UAY-UAY-UAY-U AY-U#AY-U&AY-U)AY-U,AY-U/AY-U2AY-U5AY-U8AY-U;AY-U>AV VAV VAV5VAY-VAV5V%AV5V&AV0V*AV5V+AY-V0AV5V5AY-V8AV; V;AW'WAW"WAY-W"AW'W'AY-W*AXW5AXXAY-XAXXAY-XAX XAAY*Y*AY-c                    < V ^8  d   QhRS[ /# )r   r  r   )r   r2  s   "r   r   r3    s     ^& ^&# ^&r   c                <  aaaaaa"   \         P                   ! 4       p\        VP                  R4      '       d   VP                  P                  M\	        VP                  4      pVP
                  ;'       g    RR,          P                  RR4      p\        P                  RYRP                  ;'       g    VP                  ;'       g    RVP                  ;'       g    RV4       V P                  P                  V4      pVP                  pVP                  VP                   8H  ;'       g    \#        VRR	4      p	V	'       di   V P$                  P'                  R
RVP                  '       d   VP                  P                  MRRVP                  RVP(                  RV/4      G Rj  xL
  \+        W P,                  V4      p
V P/                  V
4       R	p ^ RIp\3        \4        RR7      ;_uu_ 4       pVP7                  V4      ;'       g    / pRRR4       \9        XP;                  R4      ;'       g    / P;                  RR	4      4      p\?        WR7      p\#        VRR	4      '       Ed   \#        VRR4      ;'       g    RpVR8X  d   RpMRpVR,           V,           p V P                  P,                  PA                  VP                  \#        VRR4      R7      pVP                  '       d   VP                  P                  MRp\#        VRR	4      pVPB                  ;'       d    T;'       d    VVPD                  9  pV'       d   V PF                  P;                  VP                  4      pV'       d   VR8X  d   RVPH                   R 2pMMVPJ                  ^<,          pVPJ                  ^<,          pV'       g   V R!2MV'       d	   V R"V R#2MV R#2pR$V 2pR%V R&2p V PM                  4       pV'       d   V RV 2pTPO                  TP                  T\#        TR'R4      R(7      G Rj  xL
  R	Tn)        RTn*        V	'       d   \#        VR*R4      '       d    ^ R+I+H,pH-p VP\                  p V! V VR,7      p!V!'       dJ   V!w  p"p#p$R-V$ R.2p%V! V"V#V%VP
                  R/7      p&V&'       d   V&Vn        \        P                  R0V V4       M\        P_                  R1V 4        V P                  Pa                  VP(                  4      p'V''       Ed   \c        V'4      ^8  Ed   ^ R3I2H3p(H4p) R4p*R5p+R6p,Rp-Rp.Rp/Rp0 \j        R7,          p1V1Pm                  4       '       Ed^   ^ RIp2\3        V1RR7      ;_uu_ 4       p3V2P7                  V34      ;'       g    / p4RRR4       X4P;                  R8/ 4      p5\o        V5\        4      '       d   T5p*M\o        V5\p        4      '       d   V5P;                  R94      ;'       g    V5P;                  R84      ;'       g    T*p*V5P;                  R:4      p6V6e    \s        V64      p-V5P;                  R;4      ;'       g    Rp.V5P;                  R<4      ;'       g    Rp/V4P;                  R=/ 4      p7\o        V7\p        4      '       d-   \	        V7P;                  R>R64      4      Py                  4       R9   p,V.'       d	   V/'       gS    \{        4       p8T.;'       g    V8P;                  R;4      p.T/;'       g    V8P;                  R<4      p/V8P;                  R?4      p0V-Ef   V/'       Ed    X4P;                  R@4      p9\o        V9\|        4      '       d   V9 F  p:\o        V:\p        4      '       g   K  V:P;                  R<4      ;'       g    RP                  RA4      p;V;'       g   KO  V;V/P                  RA4      8X  g   Kg  V:P;                  RB/ 4      p<\o        V<\p        4      '       dI   V<P;                  V*/ 4      p=\o        V=\p        4      '       d!   V=P;                  R:4      p>V>e   \s        V>4      p- M	  V,'       Ed   T)! T*T/;'       g    RT0;'       g    RT-T.;'       g    RRC7      p?\s        V?V+,          4      p@\s        V?RD,          4      pA\c        V'4      pBVP                  pCVC^ 8  d   XCoREpDM
V(! V'4      oRFpDRGpESX@8  ;'       g    XBXE8  pFVF'       Ed   \        P                  RHXBSRI XD\s        V+^d,          4      V?RI X@RI 4       VP                  '       d   RJVP                  /MRpG ^ RKIBHCpH \{        4       p8V8P;                  R?4      '       Ed   V' UIu. uFX  pIVIP;                  RL4      R9   g   K  XIP;                  RO4      '       g   K4  RLXIP;                  RL4      ROVIP;                  RO4      /NKZ  	  upIo\c        S4      ^8  Ed   XH! R/ V8BR8V*RP^RQR6RRRS.RVP(                  /B oRT SnD        \        P                  ! 4       pJVJP                  RVVV3RU l4      G Rj  xL
 w  pKpLSP(                  pMVMVP(                  8w  d"   XMVn        V P                  P                  4        V P                  P                  VP(                  XK4       ^ Vn@        TKp'\c        VK4      pNV(! VK4      pO\        P                  RVXBVNSRI VORI 4       VOXA8  d   \        P_                  RWXORI 4       V''       g*   V P                  P                  4       '       g
   VRY,          pV''       g   VP                  '       d   VP                  \        P                  8w  d   VP                  \        P                  8w  d   VP                  P                  pVP                  4        RZ2pP\        P                  ! VP4      '       gd   V PF                  P;                  VP                  4      pV'       d7   VPO                  VP                  R[VP                  4        R\24      G Rj  xL
  VP                  \        P                  8X  d   V PF                  P;                  \        P                  4      pV P                  V4      pQVQ'       d@   V'       d8   \        VR]4      '       d&   VP                  XQ4      pRVR'       d   VRXR 2,          pVP
                  ;'       g    RoVP                  R8g  ;'       d1    VP                  ;'       d    \#        V P,                  R^R	4      '       * pSVS'       d%   VP                  '       d   R_VP                   R`S 2oVP                  '       d   . pT\        VP                  4       F  w  pUpVVU\c        VP                  4      8  d   VP                  XU,          MRpWVWP                  Ra4      ;'       g    VP                  \        P                  8H  pXVX'       g   Ku  XTP                  XV4       K  	  XT'       d   V P                  SXT4      G Rj  xL
 oVP                  '       Ed   . pY\        VP                  4       F  w  pUpVVU\c        VP                  4      8  d   VP                  XU,          MRpWVWP                  Rb4      ;'       g.    VP                  \        P                  \        P                  39   pZVZ'       g   K  XYP                  XV4       K  	  XY'       d   V P                  SXY4      G Rj  xL
 oRp[\        ;QJ d    V3Rc lX[ 4       F  '       g   K   R6M	  R	M! V3Rc lX[ 4       4      '       d   V PF                  P;                  VP                  4      p\VP                  '       d   RJVP                  /MRp]X\'       dI    Rdp^V P                  4       '       d
   X^Re,          p^X\PO                  VP                  X^X]R(7      G Rj  xL
  VP                  '       Ed   VP                  \        P                  8X  Ed   ^ RIep_0 Rmp`\        VP                  4       EF]  w  pUpVVU\c        VP                  4      8  d   VP                  XU,          MRpWVWR9   d]   ^ RIOpaVaP                  P                  XV4      ^,          Py                  4       pbVbX`9   d   RfpWMX_P                  XV4      w  pcpLVc'       d   XcpWXWP                  Rg4      '       g   XWP                  Rh4      '       g   K  ^ RIOpdVdP                  P                  XV4      peVeP                  Ri^4      pf\c        Vf4      ^8  d
   Xf^,          MXepg^ RIkphVhP                  RjRiVg4      pgXWP                  Rh4      '       d   RkXg RlXV Rm2pM	RnXg RoXV Rp2pV RS 2oEK`  	  \#        VRqR4      '       dp   VP                  '       d^   VP                  Rr,          o\        ;QJ d    V3Rs lV' 4       F  '       g   K   R6M	  R	M! V3Rs lV' 4       4      piVi'       g	   RtS RuS 2o RVP                  '       d   VP                  P                  MRRVP                  RVP(                  RvSRr,          /pjV P$                  P'                  RwVj4      G Rj  xL
  RxS9   Ed>    ^ RyIoHppk ^ RzI2H4p) \        P                  P;                  R{\        P                  P                  R|4      4      plT)! V P                  V P                  ;'       g    RR}7      pmXk! SXlVmVlR~7      G Rj  xL
 pnVnP                  '       d   V PF                  P;                  VP                  4      poVo'       dH   XoPO                  VP                  RP                  XnP                  4      ;'       g    R4      G Rj  xL
   V P                  4        R# XnP                  '       d   XnP                  oV P                  SVV'VVP(                  VVP                  R7      G Rj  xL
 pq V PF                  P;                  VP                  4      prVr'       d6   \        XrR4      '       d$   XrP                  VP                  4      G Rj  xL
  XqP;                  R4      ;'       g    RpsXqP;                  R. 4      pt\         P                   ! 4       T,
          puTqP;                  R^ 4      pv\c        Ts4      pw\        P                  RYRP                  ;'       g    RXuXvXw4       Xs'       g   XqP;                  R4      '       d   XqP;                  RR4      px\	        Tx4      Py                  4       o\        ;QJ d    T3R lR 4       F  '       g   K   R6M	  R	M! T3R lR 4       4      ;'       g    RS9   ;'       d    \c        T'4      ^28  pyTy'       d   RpsMR\	        Xx4      R,           R2psXqP;                  R4      '       d'   XqR,          TP(                  8w  d   XqR,          Tn        \#        T RR	4      '       d   Xs'       d   XqP;                  R4      pzTz'       d}   XzP                  4       P                  4       p{\c        T{4      ^8  d7   RP                  X{R,          4      p|T|R\c        T{4      ^,
           R2,          p|MXzP                  4       p|RX| RXs 2psT P$                  P'                  R/ XjCRXs;'       g    RRr,          /C4      G Rj  xL
   ^ RIHp} X}EP                  '       dG   X}EP                  EP                  ^ 4      p~\        EP                  ! T EP                  T~4      4       KY   XqP;                  R4      ;'       d    XqP;                  R4      '       * pT'       d!   \        P                  RTP(                  4       E\        EP                  ! 4       EP                  4       pX'       d   MT''       g   XqP;                  R. 4      pT P                  EP                  TP(                  RLRRT;'       g    . R8E\        4       RTP                  '       d   TP                  P                  MRRX/4       X'       g   XqP;                  R\c        T'4      4      p\c        Xt4      T8  d   XtXR M. pT'       gd   T P                  EP                  TP(                  RLRMROSRX/4       Xs'       d.   T P                  EP                  TP(                  RLRNROXsRX/4       MaT EP                  RJpX FL  pTP;                  RL4      R8X  d   K  / XCRX/CpT P                  EP                  TP(                  TXR7       KN  	  T P                  EP                  TP                  XqP;                  R^ 4      R7       \9        TqP;                  R4      4      pT EP                  TXsXtTR7      '       d   T EP                  TXs4      G Rj  xL
  XqP;                  R4      '       de   Xs'       dJ   T PF                  P;                  TP                  4      pT'       d   T EP!                  XsTX4      G Rj  xL
   T P                  4        R# XsT P                  4        #  EL  + '       g   i     ELT; i  \<         d     EL1i ; i  \<         d     ELi ; i ELg  \<         d"   p\        PQ                  R)T4        Rp?ELRp?ii ; i  \<         d-   p\        P_                  R2TP\                  T4        Rp?ELRp?ii ; i  + '       g   i     ELx; i  \t        \v        3 d     ELi ; i  \<         d     ELi ; i  \t        \v        3 d     EL$i ; i  \<         d     EL6i ; iu upIi  ELT  \<         d"   p\        P_                  RXT4        Rp?ELRp?ii ; i EL EL EL EL  \<         d     ELi ; i E	LQ EL ELC  \<         d"   pp\        PQ                  RTp4        Rpp?pEL7Rpp?pii ; i EL EL  \<         d     ELi ; i ELB  \<         d#   p\        EP                  RT4        Rp?ELRp?ii ; i ELy EL  \<         Ed   p T PF                  P;                  TP                  4      pT'       d7   \        XR4      '       d%   XP                  TP                  4      G Rj  xL 
  M  \<         d     Mi ; i\        EP#                  RT4       E\%        T4      EP&                  p\	        T4      '       d   \	        T4      R,          MRpxRp\#        TRR4      pRE\)        4       9   d   \c        T'4      M^ pXR8X  d   RpMXR8X  d   \#        TRR4      p/ p Te"   XEP+                  4       P;                  R/ 4      pM  \<         d     Mi ; iXP;                  R4      R8X  dH   XP;                  R4      pT'       d,   X^ 8  d%   ^ RIpTEP/                  XR,          4      pRT R2pM>RpM;RpM8XR8X  d   RpM.XR9   d(   X^28  d     Rp?T P                  4        R# XRG8X  d   RpRX RXx RX R2u Rp?T P                  4        # Rp?ii ; i  T P                  4        i ; i5i)zAInner handler that runs under the _running_agents sentinel guard.r   rk   NP   Nr   r[  z3inbound message: platform=%s user=%s chat=%s msg=%rr  was_auto_resetFzsession:startr  rA  r  r   Nr*   r+   privacy
redact_pii)r  auto_reset_reasonidledailyz[System note: The user's session was automatically reset by the daily schedule. This is a fresh conversation with no prior context.]zy[System note: The user's previous session expired due to inactivity. This is a fresh conversation with no prior context.]r  r  rZ  )r  session_typereset_had_activityzdaily schedule at z:00hzh r  zinactive for u!   ◐ Session automatically reset (z). Conversation history cleared.
Use /resume to browse and restore a previous session.
Adjust reset timing in config.yaml under session_reset.metadatar  z.Auto-reset notification failed (non-fatal): %s
auto_skill)_load_skill_payload_build_skill_messager  z3[SYSTEM: This conversation is in a topic with the "zO" skill auto-loaded. Follow its instructions for the duration of this session.])r  z8[Gateway] Auto-loaded skill '%s' for DM topic session %sz;[Gateway] DM topic skill '%s' not found in available skillsz2[Gateway] Failed to auto-load topic skill '%s': %s)estimate_messages_tokens_roughget_model_context_lengthzanthropic/claude-sonnet-4.6g333333?Tr)   r[   r  context_lengthrY   r]   compressionr  r_   custom_providersr   modelsr]   r_   config_context_lengthrY   gffffff?actual	estimated  uf   Session hygiene: %s messages, ~%s tokens (%s) — auto-compressing (threshold: %s%% of %s = %s tokens)r>  	thread_idr  r  r  r  r  r  r  r  r  c                      R # r9  r   r  s   *,r   r<  :GatewayRunner._handle_message_with_agent.<locals>.<lambda>8
  s    r   c                  ,   < SP                  SR S R7      # rk   )approx_tokens_compress_context)_approx_tokens
_hyg_agent	_hyg_msgss   r   r<  r!  =
  s    J,H,H(126D -I -&r   u>   Session hygiene: compressed %s → %s msgs, ~%s → ~%s tokensz3Session hygiene: still ~%s tokens after compressionz(Session hygiene auto-compress failed: %sz

[System note: This is the user's very first message ever. Briefly introduce yourself and mention that /help shows available commands. Keep the introduction concise -- one or two sentences max.]_HOME_CHANNELu    📬 No home channel is set for z. A home channel is where Hermes delivers cron job results and cross-platform messages.

Type /sethome to make this chat your home channel, or ignore to skip.get_voice_channel_contextr  [] r   r   c              3   ,   <"   T F	  qS9   x  K  	  R # 5ir9  r   )r   r  message_texts   & r   r   ;GatewayRunner._handle_message_with_agent.<locals>.<genexpr>
  s     D2CQL(2C   u
  🎤 I received your voice message but can't transcribe it — no speech-to-text provider is configured.

To enable voice: install faster-whisper (`pip install faster-whisper` in the Hermes venv) and set `stt.enabled: true` in config.yaml, then /restart the gateway.z@

For full setup instructions, type: `/skill hermes-agent-setup`z
text/plainzapplication/ztext/r   z	[^\w.\- ]z![The user sent a text document: 'zC'. Its content has been included below. The file is also saved at: r   z[The user sent a document: 'z'. The file is saved at: z3. Ask the user what they'd like you to do with it.]reply_to_text:Ni  Nc              3      <"   T FB  pVP                  R 4      R9   g   K  SR,          VP                  R4      ;'       g    R9   x  KD  	  R# 5i)r  N   Nr  rk   N)r  r  toolr   )r   r  reply_snippets   & r   r   r0  $  sG      #"C776?&CC Bd#	(:(@(@bA"s   AA Az[Replying to: "z"]

messagezagent:startr   )#preprocess_context_references_asyncr  r{   ~)r]   )r1   r  allowed_rootzContext injection refused.z(@ context reference expansion failed: %s)r9  context_promptr  r  r  r   event_message_idstop_typingfinal_responsemessages	api_callszMresponse ready: platform=%s chat=%s time=%.1fs api_calls=%d response=%d charsfailedr  r  c              3   ,   <"   T F	  qS9   x  K  	  R # 5ir9  r   )r   rr  	error_strs   & r   r   r0  t  s      # <a	> <r1  400u}   ⚠️ Session too large for the model's context window.
Use /compact to compress the conversation, or /reset to start fresh.zThe request failed: :Ni,  Nz2
Try again or use /reset to start a fresh session.rM  last_reasoning:N   Nz
_... (z more lines)_u   💭 **Reasoning:**
```
z
```

z	agent:endresponser6  zProcess watcher setup error: %sz`Skipping transcript persistence for failed request in session %s to prevent session growth loop.toolssession_meta	timestamphistory_offsetsystem)skip_dblast_prompt_tokensrQ  already_sent)rS  zAgent error in session %szno details availablestatus_coder  i  zH Check your API key or run `claude /login` to refresh OAuth credentials.i  r  usage_limit_reachedresets_in_secondsi  z9 Your plan's usage limit has been reached. It resets in ~zh.zG Your plan's usage limit has been reached. Please wait until it resets.z@ You are being rate-limited. Please wait a moment and try again.i  z= The API is temporarily overloaded. Please try again shortly.z% The request was rejected by the API.zSorry, I encountered an error (z).
z1Try again or use /reset to start a fresh session.ra  r  r   )No STT providerzSTT is disabledzcan't listenVOICE_TOOLS_OPENAI_KEY>   .md.cfg.csv.ini.log.txt.xml.ymlr   .toml.yaml)rk   zapplication/octet-stream)contexttokenz	too largeztoo longexceedpayload)r  i  )r  r  r  r   r   r   r   r  r  r  rA  r  rV  get_or_create_sessionr   
created_at
updated_atr   rr  r  r  r   r  _set_session_envr  r  _config_pathr  r}  r   r   r   get_reset_policynotifynotify_exclude_platformsrE  at_houridle_minutes_format_session_infor  r  r  r	  r  r  r  r  r  r  r   agent.model_metadatar  r  r   r   r  r   r  	TypeError
ValueErrorr   r   r   rstriprQ  r  r  r  r  rY  r  r  r  rewrite_transcripthas_any_sessionsr|   r  r2  upperr   r   r  r  _get_guild_idr+  r  r   r   r   r   r   r   r   r   _enrich_message_with_visionVOICEAUDIO"_enrich_message_with_transcriptionr   r  DOCUMENT	mimetypesr   splitext
guess_typebasenamer   resubreply_to_message_idr2  agent.context_referencesr:  r   r  _model	_base_urlblockedr   warnings_clear_session_envexpandedr9  
_run_agentrq  r@  r   
splitlinesrT  r7  r  r   r  r  r  r   r  	isoformatappend_to_transcriptr   rm  update_session_should_send_voice_reply_send_voice_reply_deliver_media_from_responser  r  __name__localsr   mathceil)rv  r   r  r  _msg_start_time_platform_name_msg_previewsession_entryr   _is_new_sessionrc  _redact_pii	_pii_yaml_pf_pcfgr>  reset_reasoncontext_notepolicyrF  had_activityshould_notifyr   reason_texthoursminsdurationnoticesession_inforx  r  r  r  _loaded_loaded_skill
_skill_dir_display_name_activation_note
_skill_msgr  r  r  
_hyg_model_hyg_threshold_pct_hyg_compression_enabled_hyg_config_context_length_hyg_provider_hyg_base_url_hyg_api_key_hyg_cfg_path	_hyg_yaml_hyg_f	_hyg_data
_model_cfg_raw_ctx	_comp_cfg_hyg_runtime_hyg_custom_providers_cp_cp_url
_cp_models_cp_model_cfg_cp_ctx_hyg_context_length_compress_token_threshold_warn_token_threshold
_msg_count_stored_tokens_token_source_HARD_MSG_LIMIT_needs_compress	_hyg_metar  r  r  _compressedr   _hyg_new_sid
_new_count_new_tokensenv_keyguild_id
vc_context_is_shared_threadimage_pathsr   r   r   is_imageaudio_pathsis_audio_stt_fail_markers_stt_adapter	_stt_meta_stt_msg
_mimetypes_TEXT_EXTENSIONS_os2_extguessed_osr  r   display_name_refound_in_historyhook_ctxr:  _msg_cwd_msg_ctx_len_ctx_result_adapterr   agent_result_typing_adapterrJ  agent_messages_response_time
_api_calls	_resp_lenerror_detail_is_ctx_failrH  linesdisplay_reasoningr7  r  agent_failed_earlyts	tool_defshistory_lennew_messagesagent_persistedr  r  _already_sent_media_adapter_err_adapter
error_typestatus_hintrT  	_hist_len	_err_body	_err_json
_resets_inr  _hoursr'  r(  r)  rF  r/  r8  s   &&&&                                                                                                                                               @@@@@@r   r  (GatewayRunner._handle_message_with_agent  s    ))+29&//72S2S..Y\]c]l]lYm

((b#.66tSAA,,KKKK)NN''i	
 **@@H#// $$(@(@@ ? ?}&6> 	 **///V___FOO11"6>>m66{	4    (]K 	g& 	$lW55!++C066B 6		) 4 : :??eTUK
 6gV ="2E::"=2EtLVVPVLw&  f  [)F2^CN'R++22CC#__!(d!C D  :@ 5 5b&}6JERMM M M$M M%V-L-LL 
 !"mm//@G'72,>v~~>Nc*RK$*$7$72$=E#)#6#6#;D:>%{[`ugRPTvUVDWimhnnofpH,9(*DK?} MV W !+/+D+D+FL+,284~)F &ll"NNF%,UJ%E +    ,1M(.2M+
 wulDAAjZ#..-k:N?F<M:}Mm_ ]b c % "6%z3C)."J "%/
V'
 NNU# $$44]5M5MN" 7s7|q( 7J!%'+$)-& M MLC ,} < '')),mg>>&$-$7$7$?$E$E2	 ? "+w!;J!*c22%/
#J55%/^^I%>%g%g*..QXBY%g%g]g
 $.>>2B#C#/%=@] : )3z(B(J(Jd(2z(B(J(Jd
 !*mR @I!)T2236%MM)T:4%'%94:0
 %M'D'F(5(U(U9I9I*9U(5(U(U9I9I*9U'3'7'7	'B .5--09>P0Q-%&;TBB'<'1#t'<'<$,+.77:+>+D+D"*L*LS*Q#*7w-:N:Ns:S/S1421FJ'1*d'C'C8BzSU8V+5mT+J+J6C6G6GHX6YG/6/BMPQX\0J$) (=$ ('&>*00b(..B*D*00b'# -0'*<<-) ),,?$,F(G% \
 "/!A!A!A%%3N$,M%CG%LN$/M  #&"&?? 5 5!_4  
 #?KK>"~a&8=.45.q14Q7 DJCSCSCSf.>.> ?Y]IE5'D'F'++I66 *1))0A#$55=4I#I !U %&EE)$4 !Uv	155CS T)0)I  #9~2-4 ."&2."*4." 45." 04	."
 7?Z." 0=/G/G."
 8M
 4'.'='='?7;7K7K$(%&8" 2"Q 0:/D/D#/=3K3K#K?KM$<$($6$6$<$<$> $ 2 2 E E$1$<$<k!" DE @*5-0-=
.L$//" !'%9$.
'5a&8k!_	!" $/2G#G$*NN)6+6q/%& t11BBDDNN 6???v(../PU[UdUdhphxhxUx"OO11M&,,./}=G99W%%--++FOO<!,,:=;N;N;P:Q R- .   ??h...mm''(8(89G))%0HG9T(U(U$>>xH
"ZL&99N zz''R $ L L  L LDKK)CUKK 	
 !1!1!1v//0<.ALK$U%5%56401C8I8I4J0J))!,PR$$X. ? ?))[->->>  8&&t, 7 %)%E%E +&   K$U%5%56401C8I8I4J0J))!,PR$$X. T T))k.?.?ARAR-SS  8&&t, 7 %)%L%L +&  %! 3D2CD333D2CDDD#'==#4#4V__#ELCICSCSCSf.>.> ?Y]I#!!= %  $4466 (,p p"."3"3 &)2 #4 #    2 2k6J6J J*y$U%5%56401C8I8I4J0J))!,PR<<%99--d3A6<<>D// ,%/%:%:4%@
"$+E((88E<L<LW<U<U 88,,T2 sA.+.u:?uQx "ww|S,G##G,,;L> J66:V1> ! 7|n E115 7LM !
 #/tL>BI 7Z 5/400U5N5N5N!//5M"s #"#sss #"#  
 $!0vl^Tg	& V___FOO11"6>>m66<-	H **//-::: l"R\M!zz~~orww?Q?QRU?VWH#;dnn.B.B$DL(K$('3()L #LK #***#'==#4#4V__#E#"*-- & $		+*>*> ? _ _C_#   V ##%U #+++'2':':
 "&$-(33'!&!1!1 "1 " L"&--"3"3FOO"D"w'N'N)55fnnEEE $''(89??RH)--j"=N!YY[?:N%))+q9JHIKK_ ; ;)
I  0 0 : :+//I-335	
  #s # < #sss # < #       Y& * *Gr)   1  /s</@/F.G HL L  --,|2LP]PhPh2h+7+E( t.668!-!1!12B!C!*002==?E5zB,0IIeCj,A))xE
R7H-VV),:,@,@,B)!;<M;NiX`WabH **//+ 00X^^T20   CC&777.??CCAFG''(A(A'(JK 8.   * ; ;$(()9::  "A!,, ))+B
 "(,,Wb9	""77!,,b!7!9"V___FOO$9$9RT#R	 &*../?WN?B>?RU`?`~kl;fh $&&;;%00L+rR  **??)44#[)X{TVW '+&6&6d&BO+776?h6$ 83 8R 8**??)44e$3 @   , --))#/#3#34H!#L .  !!1!1.!ABM,,UHn[h,ii,,UH=== //%)]]%6%6v%GN%"??$e^   z ##%w v ##%S" 655  		h  ) ! !  RMqQQRF  jSUZUeUeghiij\ ?>> %.z#: % $%, % . &z2  B)&2"T % F *@ $ 8  ) ! !P ;#L ! RLL!KSQQR F z  C>BBCB >  6	#}}00AGL-$H$H&226>>BBB 8+Fa))J+.q663q6$<7MLK!!]D9K(1VX(=G1Ic!h##Az48		 ,$-NN$4$8$8"$E	  ==(,AA!*/B!CJ!j1n#!%:+<!=(abhaiik&l&o"dK#]
* r>1 ##% !C'"IK1*T.-CD ##%s6	r ##%s9  A/Ay28<Ay25Ay2	Ay2AAy2-Ay2(Ay2,:Ay2&Ai'-Ay2Ai- 2Ai$Ai- 3Ai- 
3Ay2>Ay2BAj $	Aj .Aj ,Aj 3AAj 9Aj Aj Ai? 7Ai? >,Aj *Aj+Aj /Ay2Ay2%Ak ?)Ak )Ak Ay2Ak .Ay2'Ay25#Am Am 2Ak=A Am /Am Am !Al ,Am Am AAm >Am Al) Al) 5#Al) Am 'AAl; Al; Al; 7A1Al; (Ay2)Al; +Ay24Ay2 
Ay2Ay2A&Ay2>Ay2AAy2!,Am- Am%*Am%(Am%+A+Am- Am*CAm- Ay2"Ay2Ay2Ay2%BAy2(,Ay21Ay2AnA$Ay2,Ay24*Ay2Ay2>Ay2Ay2+$Ay2Ay2"#Ay2A#Ay2*#Ay2Ay2/Ay2AnAy2A#Ay2 3Ay28Ay2Ay2*An"+%Ay2Ay216Ay2(Ay2An( *An( An%An( Ay2CAy2B/Ay2CAy2CA;Ay2EAAy2FAy2F=Ay2GAy2G4Ay2G=A,Aq I)An:I*Aq I7A(Ao K Ao K7An=K8Ao L,Ao L;7Ao M3
Ao M=Ao M>Ao NAy2NAo N'Ao N3/Aq O"Ao2O#Aq O(,Ao8 P0Ao8 QAo5QAo8 Q
Aq Q"A0Aq SAq S%Aq S<A
Aq U	Aq U(Aq U5Aq V/Aq V<A Aq W=Aq XBAq Z5Aq [Ap
[	Aq [Ap ['AAp \-Aq ]Aq ]%AAq ^3Aq ^<>Aq _;AAq a9Aq a<4Aq b1DAq gAp=gAq g Aq g(,Aq hAq h,Aq h-Aq h2Ay2iAq iAy2iAi*	i$	Ai- i-Ai<i8Ay2i;Ai<i<Ay2i?Ajj
Aj jAjjAj jAk jAj;j5Ay2j;Ak k Ay2kAk:k!Ak5k/Ay2k5Ak:k:Ay2k=Al	l	Am lAl&l"Am l%Al&l&Am l)Al8l4Am l7Al8l8Am l;AmmAm mAy2mAmmAm mAm"mAy2m!Am"m"Ay2m%Am- m-Anm8AnnAy2nAnnAy2nAy2n"Ay2n%An( n(An7n3Ay2n6An7n7Ay2n:Aq n=Ao o Ao oAo/oAo*o$Aq o*Ao/o/Aq o5Ao8 o8AppAq pAppAq pAp:pAp5p/Aq p5Ap:p:Aq q Aq qAyqAAr4r-Ar0r.Ar4r3Ayr4Asr?AysAssB"Ayu%%Avv
AyvAvvAyvAvv1AywA
AyxAy xAy2x+Ayx?Ayy Ay yAy2yAyyAy yAy/y/Ay2c                    < V ^8  d   QhRS[ /# r   r   )r   r2  s   "r   r   r3  U  s     M  M c M r   c                   ^ RI HpHp \        4       pRpRpRpRp \        R,          pVP                  4       '       d   ^ RIp	\        VRR7      ;_uu_ 4       p
V	P                  V
4      ;'       g    / pRRR4       XP                  R/ 4      p\        V\        4      '       dX   VP                  R4      pVe    \        V4      pVP                  R4      ;'       g    RpVP                  R	4      ;'       g    Rp \!        4       pT;'       g    TP                  R4      pT;'       g    TP                  R	4      pTP                  R
4      pT! TT;'       g    RT;'       g    RTT;'       g    RR7      pTe   RpMY8X  d   RpMRpTR8  d   TR,          R R2pMTR8  d   TR,           R2pM\#        T4      pRT R2RT;'       g    R 2RT RT R2.pT'       d*   RT9   g   RT9   g   RT9   d   TP%                  RT 24       R P'                  T4      #   + '       g   i     EL; i  \        \        3 d     ELi ; i  \         d     EL\i ; i  \         d     ELi ; i)!zResolve current model config and return a formatted info block.

Surfaces model, provider, context length, and endpoint so gateway
users can immediately see if context detection went wrong (e.g.
local models falling to the 128K default).
)r  DEFAULT_FALLBACK_CONTEXTNr)   r*   r+   r[   r  rY   r]   r_   rk   r  r  u:   default — set model.context_length in config to overridedetectedi@B z.1fMi  Ku   ◆ Model: `r   u   ◆ Provider: 
openrouteru   ◆ Context: z	 tokens ()	localhostz	127.0.0.1z0.0.0.0u   ◆ Endpoint: r   )rr  r  r  r   r   r   r  r  r  r   r  r   r  rs  rt  r   r   r   r   r   )rv  r  r  r[   r  rY   r]   r_   r$  
_info_yamlr  r  r  raw_ctxr   r  
ctx_sourcectx_displayr  s   &                  r   rq  "GatewayRunner._format_session_infoU  st    	\&( $	#m3H  )(W55%//288bD 6 HHWb1	i..'mm,<=G*!47L1  )}}Z8@@DH(}}Z8@@DH
	35G::7;;z#:H::7;;z#:Hkk),G 2^^MMr"7^^
 !,!J7UJ#J Y&+i7<A>Ku$+u45Q7Kn-K 5'#X5567K=	*Q?
 0K84Ky\dOdLL>(45yyu 655 !*:6 ! !  		  		sx   <I	 H4AI	 :H1 I	 I	 8I	 <I I *#I H.	(	I	 1II	 II	 	III*)I*c                &   < V ^8  d   QhRS[ RS[/# rW  r   r   )r   r2  s   "r   r   r3    s     E E E# Er   c           	     "  "   VP                   pV P                  V4      p V P                  P                  P	                  V4      pV'       dp   \
        P                  ! V P                  VP                  4      4      pV P                  P                  V4       VP                  V P                  P                  4       T P!                  T4        ^ RIHp T! 4         ^ RIHp T! 4        T P                  P+                  T4      p	T P,                  P/                  TR4       T P0                  P3                  RRTP4                  '       d   TP4                  P6                  MRRTP8                  R	T/4      G Rj  xL
  T P0                  P3                  R
RTP4                  '       d   TP4                  P6                  MRRTP8                  R	T/4      G Rj  xL
   T P;                  4       p
T	'       d   RpMT P                  P=                  TRR7       RpT
'       d   T RT
 2# T#   \         d"   p\        P                  RT4        Rp?ELRp?ii ; i  \         d     ELi ; i  \         d     ELi ; i L L  \         d    Rp
 Li ; i5i)zHandle /new or /reset command.z(Gateway memory flush on reset failed: %sN)clear_env_passthrough)clear_credential_fileszsession:endr  rk   rA  r   zsession:resetu"   ✨ Session reset! Starting fresh.T)	force_newu   ✨ New session started!r  )r  r  rV  r  r   rY  r  r  r  ru  r   add_done_callbackr  r   r  r  _evict_cached_agenttools.env_passthroughr  tools.credential_filesr  reset_sessionrh  r   rr  r  r  r   rA  rq  rg  )rv  r   r  r   	old_entry_flush_taskrx  r  r  	new_entryr  headers   &&          r   r  #GatewayRunner._handle_reset_command  sK     226:		H**3377DI%11..y/C/CD &&**;7--d.D.D.L.LM 	  -	C!#	E"$
 &&44[A	 	%%))+t< jjoom--bv~~;.
  	 	 jjooo--bv~~;0
  	 		446L 9F 44Vt4L/FXT,00i  	HLLCQGG	H  		  				  	L	s   JBH% =JI I& *AJ
.J8I89,J&.JI:JI< *J2)J	J%I0IJIJI#J"I##J&I51J4I55J:J<J	JJJc                &   < V ^8  d   QhRS[ RS[/# rW  r  )r   r2  s   "r   r   r3    s        <  C  r   c                h  "   ^ RI HpHp ^ RIHp V! 4       pV! 4       pVP
                  ! 4       R,          R,          p VP                  V4      p\        V4      P                  R4      ^ ,          p	V	'       d   RV	 R2R	V R2.p
MR
R	V R2.p
RP                  V
4      #   \         d    Rp	 L=i ; i5i)u@   Handle /profile — show active profile name and home directory.)r#   display_hermes_homer   z.hermesprofilesr   Nu   👤 **Profile:** `r   u   📂 **Home:** `u   👤 **Profile:** defaultr   )r   r#   r*  pathlibr   homer   r   r   rt  r   )rv  r   r#   r*  r   r-  r7  profiles_parentr  profile_namer  s   &&         r   r  %GatewayRunner._handle_profile_command  s     I  %' ))+	1J>	 ""?3Cs8>>#.q1L %l^15"7)1-E ,"7)1-E
 yy  	 L	 s.   <B22B 1B29&B2B/,B2.B//B2c                &   < V ^8  d   QhRS[ RS[/# rW  r  )r   r2  s   "r   r   r3  	  s        ,  3  r   c                &  "   VP                   pV P                  P                  V4      pV P                  P	                  4        Uu. uF  qDP
                  NK  	  ppVP                  pW`P                  9   pRRRVP                  R,           R2RVP                  P                  R4       2RVP                  P                  R4       2R	VP                  R
 2RV'       d   RMR 2RRRP                  V4       2.	pRP                  V4      # u upi 5i)zHandle /status command.u   📊 **Hermes Gateway Status**rk   z**Session ID:** `N   Nz...`z**Created:** z%Y-%m-%d %H:%Mz**Last Activity:** z**Tokens:** r>  z**Agent Running:** u   Yes ⚡Noz**Connected Platforms:** ro  r   )r  rV  rg  rE  r  r   r   r_  r  rh  strftimeri  total_tokensr   )	rv  r   r  r  rr  connected_platformsr   
is_runningr  s	   &&       r   r  $GatewayRunner._handle_status_command	  s    **@@H040B0B0DE0D1ww0DE $// $8$88
 - 8 8 =>dCM44==>NOPQ!-":":"C"CDT"U!VW=55a89!z)t!DE'		2E(F'GH

 yy% Fs   ADDB7Dc                &   < V ^8  d   QhRS[ RS[/# rW  r  )r   r2  s   "r   r   r3  "  s     - - - -r   c                  "   VP                   pV P                  P                  V4      pVP                  pV P                  P                  V4      pV\        J d=   W@P                  9   d   V P                  V \        P                  RVR,          4       R# V'       d1   VP                  R4       W@P                  9   d   V P                  V R# R# 5i)as  Handle /stop command - interrupt a running agent.

When an agent is truly hung (blocked thread that never checks
_interrupt_requested), the early intercept in _handle_message()
handles /stop before this method is reached.  This handler fires
only through normal command dispatch (no running agent) or as a
fallback.  Force-clean the session lock in all cases for safety.
rr  r  rs  rn  ro  zNo active task to stop.)
r  rV  rg  r   r_  r   r  r  r  r  )rv  r   r  r  r   rm   s   &&    r   r  "GatewayRunner._handle_stop_command"  s      **@@H#//$$((5++222((5KKQS^_bScdZOO,- 222((5_,s   BC2Cc                &   < V ^8  d   QhRS[ RS[/# rW  r  )r   r2  s   "r   r   r3  @  s            r   c                  "   ^ RI Hp R.V! 4       Op ^ RIHp V! 4       pV'       d   VP	                  R\        V4       R24       \        V4      pVR,           F'  pVP	                  RV RWW,          R	,           24       K)  	  \        V4      ^
8  d&   VP	                  R
\        V4      ^
,
           R24       RP                  T4      #   \         d     Li ; i5i)z/Handle /help command - list available commands.gateway_help_linesu   📖 **Hermes Commands**
r  u   
⚡ **Skill Commands** (z	 active):N
   Nr      ` — descriptionz	
... and z3 more. Use `/commands` for the full paginated list.r   )	r  rA  r  r  r   r   r  r   r   )rv  r   rA  r  r  r  sorted_cmdsr  s   &&      r   r  "GatewayRunner._handle_help_command@  s     :(
!
	?+-J9#j/9J)TU$Z0&s++CLL1SE
0N/O!PQ ,{#b(LL:c+.>.C-DDw!xy yy  		s)   CB'C ;CCCCCc                &   < V ^8  d   QhRS[ RS[/# rW  r  )r   r2  s   "r   r   r3  V  s     3  3 L 3 S 3 r   c                  "   ^ RI Hp VP                  4       P                  4       pV'       d    \	        V4      pM^p\        V! 4       4      p ^ RIHp V! 4       pV'       d|   VP                  R4       VP                  R4       \        V4       FJ  pWx,          P                  RR4      P                  4       ;'       g    Rp	VP                  RV R	V	 24       KL  	  T'       g   R
# ^ RIHp
 TP                  P                   T
P"                  8X  d   ^M^p\%        ^\'        T4      T,           ^,
          T,          4      p\%        ^\)        YL4      4      pT^,
          T,          pY^Y,            pR\'        T4       RT RT R2R.TOpT^8  dj   . pT^8  d   TP                  RT^,
           R24       Y8  d   TP                  RT^,            R24       TP+                  RRP-                  T4      .4       Y8w  d   TP                  RT RT R24       RP-                  T4      #   \
         d     R# i ; i  \         d     ELji ; i5i)zDHandle /commands [page] - paginated list of all commands and skills.r@  zUsage: `/commands [page]`rB  rk   u   ⚡ **Skill Commands**:rF  zSkill commandr   rE  zNo commands available.r|   u   📚 **Commands** (z total, page r   r  z`/commands u
   ` ← prevu   next → `/commands z | z_(Requested page z  was out of range, showing page z.)_r   )r  rA  r  r   r  rt  r   r  r  r   r  r   r   gateway.configr|   r  r  r  r  r   r  r  r   )rv  r   rA  raw_argsrequested_pageentriesr  r  r  descr|   	page_sizetotal_pagespager  page_entriesr  	nav_partss   &&                r   r  &GatewayRunner._handle_commands_commandV  s0    :))+1133!$X N )+,
	?+-Jr"89!*-C%?..}bAGGI\\_DNNQse6$#89 . ++,,//83D3DDB"	!c'lY6:yHI1c.67Y&U%67 "#g,}TF!K=PQR
 

 ?Iax  ;taxj
!CD!  #7qz!CDLL"ejj345!LL,^,<<\]a\bbefgyyW  323   		sY   -IH) IA1H; H; I'EI)H84I7H88I;I
I	I

Ic                &   < V ^8  d   QhRS[ RS[/# rW  r  )r   r2  s   "r   r   r3    s     F  F  F # F r   c           
       "   ^ RI p^ RIHpHpHp ^ RIHp VP                  4       P                  4       pV! V4      w  rp
RpRpRpRpRp\        R,          p VP                  4       '       d   \        VRR7      ;_uu_ 4       pVP                  V4      ;'       g    / pRRR4       XP                  R	/ 4      p\        V\        4      '       d7   VP                  R
R4      pVP                  RV4      pVP                  RR4      pVP                  R4      pTP"                  pT P%                  T4      p\'        T R/ 4      P                  T/ 4      pT'       dI   TP                  R	T4      pTP                  RT4      pTP                  RT4      pTP                  RT4      pT'       Eg   T	'       Eg   T! T4      pRT;'       g    R RT 2R.p T! TT^R7      pT EF  pTR,          '       d   RMRpTP)                  RTR,           RTR,           RT R24       TR,          '       d{   RP+                  R TR,           4       4      pTR,          \-        TR,          4      8  d%   R TR,          \-        TR,          4      ,
           R!2MRpTP)                  R"T T 24       M3TP                  R#4      '       d   TP)                  R$TR#,           R24       TP)                  R4       EK  	  TP)                  R%4       TP)                  R&4       TP)                  R'4       R(P+                  T4      # T! TTTTTT
T	R)7      pTP.                  '       g   R*TP0                   2# Rp\'        T R+R4      p \'        T R,R4      p!T '       d)   T!e%   T ;_uu_ 4        T!P                  T4      pRRR4       T'       d\   T^ ,          eQ    T^ ,          P                  TP2                  TP4                  TP6                  TP8                  TP:                  R-7       \A        T R/4      '       g   / T n!        R0T R1TP2                   R2TPD                  ;'       g    TP4                   R32T PB                  T&   \A        T R4      '       g   / T n#        R	TP2                  RTP4                  RTP6                  RTP8                  R4TP:                  /T PF                  T&   T
'       d    TP                  4       '       d;   \        TRR7      ;_uu_ 4       pTP                  T4      ;'       g    / pRRR4       M/ pXPI                  R	/ 4      pTP2                  TR
&   TP4                  TR&   TP8                  '       d   TP8                  TR&   ^ R5I%H&p# T#! T4       TPD                  ;'       g    TP4                  pR7TP2                   R2.pTP)                  R8T 24       TPN                  p%T%'       d   T%PP                  '       d!   TP)                  R9T%PP                  R: R;24       T%PR                  '       d!   TP)                  R<T%PR                  R: R;24       T%PU                  4       '       d#   TP)                  R=T%PW                  4        24       TP)                  R>T%PY                  4        24       Me ^ R?I-H.p& T&! TP2                  TP8                  ;'       g    TTP6                  ;'       g    TTP4                  R@7      p'TP)                  R9T'R: R;24       RTP8                  ;'       g    RP_                  4       9   ;'       d&    RATP2                  P_                  4       9   ;'       g    TP:                  RB8H  p(T('       d   TP)                  RC4       TP`                  '       d   TP)                  RDTP`                   24       T
'       d   TP)                  RE4       MTP)                  RF4       R(P+                  T4      #   + '       g   i     ELX; i  \          d     ELi ; i  \          d     EL4i ; i  + '       g   i     EL; i  \          d"   p"\<        P?                  R.T"4        Rp"?"ELPRp"?"ii ; i  + '       g   i     ELP; i  \          d"   p$\<        P?                  R6T$4        Rp$?$ELRp$?$ii ; i  \          d     ELi ; i5i)Gu  Handle /model command — switch model for this session.

Supports:
  /model                              — show current model info
  /model <name>                       — switch for this session only
  /model <name> --global              — switch and persist to config.yaml
  /model <name> --provider <provider> — switch provider + model
  /model --provider <provider>        — switch to provider, auto-detect model
N)switch_modelparse_model_flagslist_authenticated_providers)	get_labelrk   r  r)   r*   r+   r[   r  rY   r]   	providersrh  r_   z
Current: `r  z` on )current_provideruser_providers
max_models
is_currentz
 (current)**r   z** `--provider slugr   r   r  ro  c              3   .   "   T F  pR V R 2x  K  	  R# 5ir   Nr   )r   r  s   & r   r   6GatewayRunner._handle_model_command.<locals>.<genexpr>  s     .MA1#Qx   total_modelsz (+z more)z  api_urlz  `u    `/model <name>` — switch modelu5   `/model <name> --provider <slug>` — switch provideru$   `/model <name> --global` — persistr   )	raw_inputr^  current_modelcurrent_base_urlcurrent_api_key	is_globalexplicit_providerError: re  rc  )	new_modelnew_providerr_   r]   r   z1In-place model switch failed for cached agent: %s_pending_model_notesz$[Note: model was just switched from z to z via z/. Adjust your self-identification accordingly.]r   )save_configz"Failed to persist model switch: %szModel switched to `z
Provider: 	Context: r>   tokenszMax output: zCost: zCapabilities: r;  )r]   r_   rY   claudeanthropic_messageszPrompt caching: enabledz	Warning: z!Saved to config.yaml (`--global`)z-_(session only -- add `--global` to persist)_)1r  hermes_cli.model_switchrY  rZ  r[  hermes_cli.providersr\  r  r   r   r   r  r  r   r  r   r   r  r  r   r   r   r   r  error_messagerq  target_providerr_   r]   r   r  r  r  rs  provider_labelrh  r  hermes_cli.configrt  
model_infocontext_window
max_outputhas_cost_dataformat_costformat_capabilitiesrr  r  r   warning_message))rv  r   r  _switch_modelrZ  r[  r\  rM  model_inputro  persist_globalrk  r^  rl  rm  
user_provsr  r  r  r  r  r   overrider}  r  r]  rr  tag
model_strsr  r3  cached_entry_cache_lock_cacher   rt  rx  mir  ctxcache_enableds)   &&                                       r   r  #GatewayRunner._handle_model_command  s     		
 	
 	3))+113 :K89T6 '
"]2	!!##+88A..+11rC 9GGGR0	i..$-MM)R$@M'0}}ZAQ'R$'0}}Z'D$ WW[1

 226:4!;R@DD[RTU$LL-@M'||J8HI'||J8HI&ll9oFO {#4#4&'78N!-"<"<9!=U>BRSUWXE8%5#- 	
 #A*+L//,rCLL2ai[&	{!C5PQ!RS{{%)YY.M8.M%M
VWXfVgjmnopxnyjzVz#a&7#ak:J&J%K6 R  ACr*eW%=>y))s1Y<.%:;LL$ # LL;<LLPQLL?@99U## !-'-+$/
 ~~~V11233 d$7>~t46-%zz+6  LO7	YQ,,$..!'!7!7"NN#__#__ -  t344(*D%2=/fFVFVEW X((BBF,B,BC D<= 	!!+. t788,.D)V%%..v~~6
%%k2 H%%''kG<<"nnQ/552 =< CNN7B7	'-'7'7	)$(.(>(>	*%???,2OOIj)9C 
  ..HH&2H2H&v'7'7&8:;z.!123    y):):1(=WEF}}}|BMM!+<GDE!!vbnn&6%789LL>"*@*@*B)CDE
I.$$#__@@0@"NN==o#33	 yQw78 foo33::<<eeVM]M]McMcMeAe 7 7"66 	 LL23!!!LL9V%;%;$<=>LL<=LLHIyyO 988  		D  6   YRTWXXY8 =<<  HCQGGH8  s  Ab>+` _.A7` Bb>)b>2b>
b>A` +B` <2` .A$b>Ab>`&&b>6b>A`: <b>Bb>a= .a= a)Aa= ,a= 	b>Ab>"b>41b>&5b>Ab>"%b, b, )b, b>b>4$b>b>1"b>%b>:4b>._?	9	` `b>`b>`#b>"`##b>&`7	1	b>:a&a!b>!a&&b>)a:	4	a= =b)b$b>$b))b>,b;7b>:b;;b>c                &   < V ^8  d   QhRS[ RS[/# rW  r  )r   r2  s   "r   r   r3  S  s     6  6 L 6 S 6 r   c           
     h  "   ^ RI p^ RIHpHpHp Rp\
        R,          p VP                  4       '       dt   \        VRR7      ;_uu_ 4       pVP                  V4      ;'       g    / p	RRR4       X	P                  R/ 4      p
\        V
\        4      '       d   V
P                  RV4      pT! T4      pTR	8X  d    ^ R
IHp T! T4      pTR8X  d<   \        X
\        4      '       d   T
P                  RR4      MRpT'       d
   RT9  d   RpTP                  Yf4      pRT RT R2RR.pT! 4       pT F  pTR,          T8X  d   RMRpTR,          '       d   RMRpTR,          '       d   RRP                  TR,          4       R2MRpTP!                  T RTR,           RTR,           T T 24       K  	  TP!                  R4       TP!                  R4       TP!                  R 4       R!P                  T4      #   + '       g   i     EL; i  \         d     ELpi ; i  \         d    Rp ELfi ; i5i)"z4Handle /provider command - show available providers.N)list_available_providersnormalize_provider_PROVIDER_LABELSr  r)   r*   r+   r[   rY   rl   )resolve_providerr]   rk   zopenrouter.aicustomu   🔌 **Current provider:** z (`z`)z**Available providers:**idu    ← activeauthenticatedu   ✅u   ❌aliasesz
  _(also: ro  )_z `rE  r  z$Switch: `/model provider:model-name`zSetup: `hermes setup`r   )r  hermes_cli.modelsr  r  r  r   r   r  r  r   r  r   r   hermes_cli.authr  r   r   )rv  r   r  r  r  r  r^  r  r  r  r  _resolve_provider	_cfg_basecurrent_labelr  r]  rr  markerauthr  s   &&                  r   r  &GatewayRunner._handle_provider_commandS  s     	
 	
 ("]2	!!##+88A..+11rC 9GGGR0	i..'0}}ZAQ'R$ ..>?v%0Q#45E#F 
 |+9CIt9T9T	j"5Z\I_I=#+ (,,-=P *-<L;MRP&
 -.	A&'g1A&A]rFo..5EDBCI,,
499Qy\#:";2>TVGLLD6AdG9F1W:,wixPQ	  	R;<,-yyQ 988
  		  0#/ 0sy   H2+H G8(AH *H2:H 8H2AH2H2'BH28H			H HH2HH2H/+H2.H//H2c                &   < V ^8  d   QhRS[ RS[/# rW  r  )r   r2  s   "r   r   r3    s#     HJ HJ| HJ HJr   c                  "   ^ RI pVP                  4       P                  4       P                  4       p\        R,          p VP                  4       '       d^   \        VRRR7      ;_uu_ 4       pVP                  V4      ;'       g    / pRRR4       XP                  R/ 4      P                  R/ 4      pM/ p/ p V'       g   R# V'       g   R	.pVP                  R
4       VP                  4        F  w  r\        V
\        4      '       d4   V
P                  R4      ;'       g    V
P                  RR4      R,          pM"\        V
4      ^28  d   V
R,          R,           MT
pVP                  RV	 RV 24       K  	  VP                  R4       RP                  V4      # R pVR9   dS    RV9  g&   \        VP                  R4      \        4      '       g   / VR&   RVR,          R&   \!        WF4       RT n        R# W79   dc   V! Ws,          4      p RV9  g&   \        VP                  R4      \        4      '       g   / VR&   WR,          R&   \!        WF4       Yn        RT R2# RRP                  R VP%                  4        4       4      ,           pRV RV 2#   + '       g   i     EL; i  \         d	    / p/ p ELi ; i  \         d   pRT 2u Rp?# Rp?ii ; i  \         d   pRT 2u Rp?# Rp?ii ; i5i)z8Handle /personality command - list or set a personality.Nr)   r  r*   r+   rm   personalitiesz6No personalities configured in `~/.hermes/config.yaml`u!   🎭 **Available Personalities**
u'   • `none` — (no personality overlay)rF  r*  rk   :N2   N...u   • `rE  z
Usage: `/personality <name>`r   c                 b   \        V \        4      '       d   V P                  R R4      .pV P                  R4      '       d   VP                  RV R,           24       V P                  R4      '       d   VP                  RV R,           24       RP	                  R V 4       4      # \        V 4      # )r*  rk   tonezTone: stylezStyle: r   c              3   8   "   T F  q'       g   K  Vx  K  	  R # 5ir9  r   rq  s   & r   r   UGatewayRunner._handle_personality_command.<locals>._resolve_prompt.<locals>.<genexpr>  s      7EqQEs   	
)r  r   r   r   r   r   )r   r   s   & r   _resolve_promptBGatewayRunner._handle_personality_command.<locals>._resolve_prompt  s    %&&?B7899V$$LL6%-!9:99W%%LL75>*:!;<yy 7E 777u:r   u*   ⚠️ Failed to save personality change: uX   🎭 Personality cleared — using base agent behavior.
_(takes effect on next message)_u   🎭 Personality set to **z#**
_(takes effect on next message)_z`none`, ro  c              3   .   "   T F  pR V R 2x  K  	  R# 5ire  r   )r   r_  s   & r   r   <GatewayRunner._handle_personality_command.<locals>.<genexpr>  s     *R=QQqc8=Qrg  zUnknown personality: `z`

Available: )noner  neutral)r  r  r   r   r   r   r  r  r   r   r   r  r  r   r   r   r$   rI  r  )rv  r   r  r   r  r  r  r  r  r   r+  previewr  rx  
new_prompt	availables   &&              r   r  )GatewayRunner._handle_personality_command  s    %%'--/557"]2
	!!##+sW==!^^A.44"F > &

7B 7 ; ;OR P "
 K9:ELLBC - 3 3 5fd++$jj7__6::oWY;Z[^;_G58[25EfSkE16GuTF&	:; !6 LL9:99U##	 11H&(
6::g;NPT0U0U&(F7O35w0!+6 -/D)n"()<=JH&(
6::g;NPT0U0U&(F7O3=w0!+6
 -7)/v5YZZ*R]=O=O=Q*R!RR	'v-=i[II >==  	FM	F  HCA3GGH  HCA3GGHs   >K9,J) -J	*J) 3K94J) 8K9	K9AK9"BK9'AJ? /K9AK AK9J&	 	J) )J<8K9;J<<K9?K
KKK9KK9K6'K1+K6,K91K66K9c                &   < V ^8  d   QhRS[ RS[/# rW  r  )r   r2  s   "r   r   r3    s     !7 !7 !7# !7r   c                ^  "   VP                   pV P                  P                  V4      pV P                  P                  VP                  4      pRpRp\        \        V4      ^,
          RR4       F;  pWG,          P                  R4      R8X  g   K!  WG,          P                  RR4      pTp M	  V'       g   R# VRV pV P                  P                  VP                  V4       ^ Vn	        \        V\        P                  VVP                  R7      p	V P                  V	4      G Rj  xL
 #  L5i)	z6Handle /retry command - re-send the last user message.Nr  r  r  rk   zNo previous message to retry.)r   r   r  raw_message)r  rV  rg  r  r  r  r   r   rv  rQ  r   r   r  r  r  )
rv  r   r  r  r  last_user_msglast_user_idxr   	truncatedretry_events
   &&        r   r  #GatewayRunner._handle_retry_command  s    **@@H$$44]5M5MN s7|a'R0Az~~f%/ '
y" = !	 1 2 N]+	--m.F.F	R+,( #$))))	
 ))+6666s   B
D-%D-7A/D-&D+'D-c                &   < V ^8  d   QhRS[ RS[/# rW  r  )r   r2  s   "r   r   r3    s     S S S Sr   c                D  "   VP                   pV P                  P                  V4      pV P                  P                  VP                  4      pRp\        \        V4      ^,
          RR4       F#  pWF,          P                  R4      R8X  g   K!  Tp M	  Vf   R# WE,          P                  RR4      p\        V4      V,
          pV P                  P                  VP                  VRV 4       ^ Vn	        \        V4      ^(8  d   VR,          R,           MTp	R	V R
V	 R2# 5i)z?Handle /undo command - remove the last user/assistant exchange.Nr  r  zNothing to undo.r  rk   N(   Nr  u   ↩️ Undid z message(s).
Removed: ""r  )
r  rV  rg  r  r  r  r   r   rv  rQ  )
rv  r   r  r  r  r  r   removed_msgremoved_countr  s
   &&        r   r  "GatewayRunner._handle_undo_command  s    **@@H$$44]5M5MN s7|a'R0Az~~f%/ ! 1
  %,00B?G}4--m.F.FP^Q^H_`+,(.1+.>.C+c"U*}o-FwirRRs   BD BD c                &   < V ^8  d   QhRS[ RS[/# rW  r  )r   r2  s   "r   r   r3    s     
 
L 
S 
r   c                n  "   VP                   pVP                  '       d   VP                  P                  MRpVP                  pVP                  ;'       g    TpVP                  4        R2p ^ RIp\        R,          p/ p	VP                  4       '       d:   \        VRR7      ;_uu_ 4       p
VP                  V
4      ;'       g    / p	RRR4       WIV&   \        W4       \        V4      \        P                  V&   RT R	T R
2#   + '       g   i     LD; i  \         d   pRT 2u Rp?# Rp?ii ; i5i)zOHandle /sethome command -- set the current chat as the platform's home channel.r  r*  Nr)   r*   r+   zFailed to save home channel: u   ✅ Home channel set to **z** (ID: z@).
Cron jobs and cross-platform messages will be delivered here.)r  r  r   r  	chat_namerx  r  r   r   r  r  r$   r   r   r   r   )rv  r   r  rF  r  r  r  r  r  user_configr  rx  s   &&          r   r  &GatewayRunner._handle_set_home_command  s    17--i..$$//	"((*+=9	7&6KK!!##+88A"&.."3"9"9rK 9#* k7"%g,BJJw
 )8G9 EL M	
 98  	721#66	7sZ   AD5D5/(D D -D	3D <	D5D	D D2#D-'D2(D5-D22D5c                6   < V ^8  d   QhRS[ RS[S[,          /# rW  )r   r   r  )r   r2  s   "r   r   r3  /  s      \ hsm r   c                   \        V RR4      pVf   R# \        VR4      '       d(   VP                  '       d   \        VP                  4      # \        VR4      '       d)   VP                  '       d   VP                  P
                  # R# )z5Extract Discord guild_id from the raw message object.r  Nr  guild)r   r  r  r  r  r  )r   r?  s   & r   ry  GatewayRunner._get_guild_id.  sd     e]D1;3
##s||$$3  SYYY99<<r   c                &   < V ^8  d   QhRS[ RS[/# rW  r  )r   r2  s   "r   r   r3  <  s     I. I. I.# I.r   c                  "   VP                  4       P                  4       P                  4       pVP                  P                  pV P
                  P                  VP                  P                  4      pVR 9   d>   RV P                  V&   V P                  4        V'       d   V P                  WCRR7        R# VR!9   d=   RV P                  V&   V P                  4        V'       d   V P                  WCRR7       R# VR8X  d>   R	V P                  V&   V P                  4        V'       d   V P                  WCRR7        R
# VR"9   d   V P                  V4      G Rj  xL
 # VR8X  d   V P                  V4      G Rj  xL
 # VR8X  Ed0   V P                  P                  VR4      pRRRRR	R/pV P
                  P                  VP                  P                  4      pV P                  V4      pV'       d   \        VR4      '       d   VP                  V4      pV'       d   RVP                  WU4       2RVR,           2RVR,           2.p	VR,           F;  p
V
P                  R4      '       d   RMRpV	P!                  RV
R,           V 24       K=  	  RP#                  V	4      # RVP                  WU4       2# V P                  P                  VR4      pVR8X  d=   RV P                  V&   V P                  4        V'       d   V P                  WCRR7       R# RV P                  V&   V P                  4        V'       d   V P                  WCRR7       R#  EL EL5i)#z8Handle /voice [on|off|tts|channel|leave|status] command.r  Fr   z}Voice mode enabled.
I'll reply with voice when you send voice messages.
Use /voice tts to get voice replies for all messages.r  Tz'Voice mode disabled. Text-only replies.ttsr  z;Auto-TTS enabled.
All replies will include a voice message.Nleaverl  zOff (text only)z"On (voice reply to voice messages)z!TTS (voice reply to all messages)get_voice_channel_infozVoice mode: zVoice channel: #channel_namezParticipants: member_countmembersis_speakingz (speaking)rk   z  - r  r   zVoice mode enabled.zVoice mode disabled.)onenable)r  disable)channelr   )r  r   r   r  r  rE  r   r  rt  r  r  _handle_voice_channel_join_handle_voice_channel_leavery  r  r  r   r   )rv  r   r   r  r   r  labelsr  r  r  r  rl  r   s   &&           r   r  #GatewayRunner._handle_voice_command<  s     %%'--/557,,&&--##ELL$9$9:##(4DW%""$33Gu3UH
 ''(-DW%""$33Gt3T<U](-DW%""$33Gu3U< ((88???W_99%@@@X##''7D(B:F mm''(=(=>G))%0HGG-EFF55h?&vzz$'=&>?*4+?*@A(n)=(>?E
 ")__23%%2F2FBtAn,=+>vh%GH -  99U++!&**T"8!9:: &&**7E:G%,8  )&&(77SX7Y,,1  )&&(77SW7X-Q @@sR   BM"AM&AM)1MMM:M;A7M3*MC!M ;M<MMc                &   < V ^8  d   QhRS[ RS[/# rW  r  )r   r2  s   "r   r   r3    s     0X 0Xl 0Xs 0Xr   c                *  "   V P                   P                  VP                  P                  4      p\	        VR4      '       g   R# V P                  V4      pV'       g   R# VP                  W1P                  P                  4      G Rj  xL
 pV'       g   R# \	        VR4      '       d   V P                  Vn	        \	        VR4      '       d   V P                  Vn         VP                  V4      G Rj  xL
 pT'       d   \%        TP                  P&                  4      TP(                  T&   RT P*                  TP                  P&                  &   T P-                  4        T P/                  Y!P                  P&                  RR7       RTP0                   R2# RTn	        R#  EL L  \         db   p\        P                  RT4       RTn	        \!        T4      P#                  4       pR	T9   g   R
T9   g   RT9   d     Rp?R# RT 2u Rp?# Rp?ii ; i5i)z.Join the user's current Discord voice channel.join_voice_channelz2Voice channels are not supported on this platform.z,This command only works in a Discord server.Nz(You need to be in a voice channel first._voice_input_callback_on_voice_disconnectz Failed to join voice channel: %spynaclnacldaveyzVoice dependencies are missing (PyNaCl / davey). Install or reinstall Hermes with the messaging extra, e.g. `pip install hermes-agent[messaging]`.zFailed to join voice channel: r  Fr  zJoined voice channel **zL**.
I'll speak my replies and listen to you. Use /voice leave to disconnect.zFFailed to join voice channel. Check bot permissions (Connect + Speak).)rE  r   r  r  r  ry  get_user_voice_channelrA  _handle_voice_channel_inputr  _handle_voice_timeout_cleanupr  r  r   r  r  r   r   r  r  _voice_text_channelsrt  r  r  r   )rv  r   r   r  voice_channelr  rx  	err_lowers   &&      r   r  (GatewayRunner._handle_voice_channel_join  s    --##ELL$9$9:w 455G%%e,A%<<ll**
 
 = 7344,0,L,LG)7233+/+M+MG(	8#66}EEG 589M9M5NG((25:DU\\112""$//9M9MX]/^)-*<*<)= >[ \
 )-%WM
 F 
	8NN=qA,0G)AI9$)(;w)?S=
 4A377
	8su   AH*H	F
HAHF$ 3F"4F$ 8H B H"F$ $H/AH;HHHHHHc                &   < V ^8  d   QhRS[ RS[/# rW  r  )r   r2  s   "r   r   r3    s     % %| % %r   c                  "   V P                   P                  VP                  P                  4      pV P	                  V4      pV'       d   \        VR4      '       g   R# \        VR4      '       d   VP                  V4      '       g   R#  VP                  V4      G Rj  xL
  RV P                  VP                  P                  &   V P                  4        V P                  W!P                  P                  RR7       \        VR	4      '       d   RVn        R
#  Ly  \         d!   p\        P                  RT4        Rp?LRp?ii ; i5i)z Leave the Discord voice channel.leave_voice_channelzNot in a voice channel.is_in_voice_channelNzError leaving voice channel: %sr  Tr  r  zLeft voice channel.)rE  r   r  r  ry  r  r  r  r   r  r  rt  r  r  r  r  )rv  r   r   r  rx  s   &&   r   r  )GatewayRunner._handle_voice_channel_leave  s	    --##ELL$9$9:%%e,ww0EFF,w 566g>Y>YZb>c>c,	A--h777 27--. ++G\\5I5ITX+Y7344,0G)$ 8 	ANN<a@@	AsI   BE	E	D D D $A5E	D E&E<E	EE	c                $   < V ^8  d   QhRS[ RR/# )r   r  r   Nr   )r   r2  s   "r   r   r3    s     M MS MT Mr   c                    RV P                   V&   V P                  4        V P                  P                  \        P
                  4      pV P                  W!RR7       R# )z}Called by the adapter when a voice channel times out.

Cleans up runner-side voice_mode state that the adapter cannot reach.
r  Tr  N)rt  r  rE  r   r|   r  r  )rv  r  r   s   && r   r  +GatewayRunner._handle_voice_timeout_cleanup  sM    
 %*! --##H$4$45++Gt+Lr   c                ,   < V ^8  d   QhRS[ RS[ RS[/# )r   r  rA  
transcript)r  r   )r   r2  s   "r   r   r3    s%     0, 0,0,&)0,7:0,r   c           
       "   V P                   P                  \        P                  4      pV'       g   R# VP                  P                  V4      pV'       g   R# \        \        P                  \        V4      \        V4      \        V4      RR7      pV P                  V4      '       g   \        P                  RV4       R#  VP                  P                  V4      pV'       dI   VR,          P                  RR4      P                  RR	4      pVP                  R
V RV 24      G Rj  xL
  ^ RIHp	 \#        TT\$        P&                  T	! TRR7      R7      p
TP)                  T
4      G Rj  xL
  R#  LJ  \         d     LUi ; i L5i)zHandle transcribed voice from a user in a voice channel.

Creates a synthetic MessageEvent and processes it through the
adapter's full message pipeline (session, typing, agent, TTS reply).
Nr  )r  r  rA  r  r  z/Unauthorized voice input from user %d, ignoring:Ni  Nz	@everyoneu   @​everyonez@hereu   @​herez**[Voice]** <@z>: )SimpleNamespace)r  r  )r  r   r   r  )rE  r   r|   r  r  r   r   rN  r  r  _clientget_channelr   r  r   typesr  r   r   r{  handle_message)rv  r  rA  r  r   
text_ch_idr  r  	safe_textr  r   s   &&&&       r   r  )GatewayRunner._handle_voice_channel_input  sR     --##H$4$451155h?
 %%
OL'l
 ''//LLJGT	oo11*=G&u-55kCTU]]^egtu	ll^G9C	{#KLLL 	*$**'F	
 $$U+++ M 		 	,sV   AF
A*F
"E7 'AE7 *E5+E7 /?F
.F/F
5E7 7FF
FF
c          
      8   < V ^8  d   QhRS[ RS[RS[RS[RS[/# )r   r   rJ  r  rS  r   )r   r   r   r}  )r   r2  s   "r   r   r3    s=     4 44 4 	4
 4 
4r   c                   V'       d   VP                  R4      '       d   R# VP                  P                  pV P                  P	                  VR4      pVP
                  \        P                  8H  pVR8H  ;'       g    VR8H  ;'       d    TpV'       g   R# \        ;QJ d    R V 4       F  '       g   K   RM	  RM! R V 4       4      p	V	'       d   R# V'       d   V'       g   R# R# )a  Decide whether the runner should send a TTS voice reply.

Returns False when:
- voice_mode is off for this chat
- response is empty or an error
- agent already called text_to_speech tool (dedup)
- voice input and base adapter auto-TTS already handled it (skip_double)
  UNLESS streaming already consumed the response (already_sent=True),
  in which case the base adapter won't have text for auto-TTS so the
  runner must handle it.
zError:Fr  r  r  c              3   &  "   T F  pVP                  R 4      R8H  ;'       dg    \        ;QJ d5    R VP                  R4      ;'       g    .  4       F  '       g   K   RM*	  RM&! R VP                  R4      ;'       g    .  4       4      x  K  	  R# 5i)r  r  c              3   j   "   T F)  pVP                  R / 4      P                  R4      R8H  x  K+  	  R# 5i)functionr   text_to_speechNr7  )r   tcs   & r   r   CGatewayRunner._should_send_voice_reply.<locals>.<genexpr>.<genexpr>/  s3      6B z2&**626FF6s   13
tool_callsTFN)r   r   )r   r  s   & r   r   9GatewayRunner._should_send_voice_reply.<locals>.<genexpr>-  s      
 & GGFO{*   77<066B6 77<066B6 
 &s!   BBB	B!B=BT)	r   r  r  rt  r   r   r   r{  r   )
rv  r   rJ  r  rS  r  
voice_modeis_voice_inputshouldhas_agent_ttss
   &&&&&     r   r  &GatewayRunner._should_send_voice_reply  s    $ 8..x88,,&&%%))'59
,,0A0AA 5  ? ?l*==~ 	   
 &
 
 &
 
  ,r   c                *   < V ^8  d   QhRS[ RS[RR/# )r   r   r   r   Nr  )r   r2  s   "r   r   r3  B  s"     8 8\ 8 8 8r   c                  "   ^ RI pRpRp ^ RIHpHp V! VR,          4      pV'       g-    WE0R0,
           F  p	 \        P
                  ! V	4       K  	  R# \        P                  P                  \        P                  ! 4       RRVP                  4       P                  R,           R24      p\        P                  ! \        P                  P                  V4      RR	7       \        P                   ! WhVR
7      G Rj  xL
 p
\"        P$                  ! V
4      pVP'                  RV4      pVP'                  R4      '       d&   \        P                  P)                  V4      '       gR   \*        P-                  RVP'                  R4      4        WE0R0,
           F  p	 \        P
                  ! V	4       K  	  R# V P.                  P'                  VP0                  P2                  4      pV P5                  V4      pV'       dV   \7        VR4      '       dD   \7        VR4      '       d2   VP9                  V4      '       d   VP;                  W4      G Rj  xL
  MV'       d   \7        VR4      '       dx   RVP0                  P<                  RVRVP>                  /pVP0                  P@                  '       d   RVP0                  P@                  /VR&   VPB                  ! R/ VB G Rj  xL
  WE0R0,
           F  p	 \        P
                  ! V	4       K  	  R#   \         d     EK  i ; i EL&  \         d     EK  i ; i L LZ  \D         d#   p\*        P-                  RTRR7        Rp?LRp?ii ; i  \         d     K  i ; i  YE0R0,
           F,  p	 \        P
                  ! T	4       K    \         d     K*  i ; i	  i ; i5i)zEGenerate TTS audio and send as a voice message before the text reply.N)text_to_speech_tool_strip_markdown_for_tts:Ni  Nhermes_voice
tts_reply_r3  .mp3T)r  )r   output_pathr"  r  zAuto voice reply TTS failed: %sr  play_in_voice_channelr  
send_voicer  
audio_pathreply_tor  r  zAuto voice reply failed: %sexc_infor   )#uuidtools.tts_toolr  r  r   unlinkr  r   r   tempfile
gettempdiruuid4hexmakedirsdirnamerY  	to_threadr   r   r   isfiler  r  rE  r  r  ry  r  r  r   r  rq  r  r!  r   )rv  r   r   _uuidr"  actual_pathr  r  tts_textrr  result_jsonr3  r   r  send_kwargsrx  s   &&&             r   r  GatewayRunner._send_voice_replyB  s    
3	S.tE{;HT !.$77IIaL 8M ##%~U[[]..s34D9J KK
3dC ' 1 1#
! K ZZ,F !**[*=K::i(({0K0K@&**WBUV. !.$77IIaL 8+ mm''(=(=>G ))%0H)@AA)>??33H==33HJJJWWl;;u||33 + 0 0/
 <<)))/:ELL<R<R.SK
+((7;777 !.$77IIaL 8  GF  ! K 8 	LNN8!dNKK	L   !.$77IIaL  8sJ  	O L> O LO B'L> >L$?AL> $L> '%L> O L'2O 8AL>  :L> ;L> L:L> N  L> AL> 10L> !L<"L> &O 5M.O L!O  L!!O $L> 'L72O 6L77O :L> <L> >M+	M&!N  &M++N  .M=9O <M==O  N=N(&N=(N7	3N=6N7	7N==O c                *   < V ^8  d   QhRS[ RS[RR/# )r   rJ  r   r   N)r   r   )r   r2  s   "r   r   r3  |  s3     JI JIJI JI
 
JIr   c                  "   ^ RI Hp  VP                  V4      w  rVVP                  V4      w  rgVP	                  V4      w  rVP
                  P                  '       d   RVP
                  P                  /MRp	0 Rmp
0 Rmp0 RmpV F  w  r V! V4      P                  P                  4       pW9   d3   VP                  VP
                  P                  VV	R7      G Rj  xL
  K^  W9   d3   VP                  VP
                  P                  VV	R7      G Rj  xL
  K  W9   d3   VP                  VP
                  P                  VV	R7      G Rj  xL
  K  VP                  VP
                  P                  VV	R7      G Rj  xL
  EK  	  V F  p V! V4      P                  P                  4       pW9   d3   VP                  VP
                  P                  VV	R7      G Rj  xL
  K\  VP                  VP
                  P                  VV	R7      G Rj  xL
  K  	  R#  EL@ EL L L  \         d.   p\        P!                  RTP"                  T4        Rp?EK  Rp?ii ; i L LQ  \         d.   p\        P!                  R	TP"                  T4        Rp?EK  Rp?ii ; i  \         d"   p\        P!                  R
T4        Rp?R# Rp?ii ; i5i)u  Extract MEDIA: tags and local file paths from a response and deliver them.

Called after streaming has already sent the text to the user, so the
text itself is already delivered — this only handles file attachments
that the normal _process_message_background path would have caught.
r   r  N)r  r"  r  )r  
video_pathr  )r  
image_pathr  )r  r"  r  z*[%s] Post-stream media delivery failed: %sz)[%s] Post-stream file delivery failed: %sz'Post-stream media extraction failed: %s>   .m4ar  .ogg.wav.opus>   .3gp.avi.mkv.mov.mp4.webm>   .gif.jpg.png.jpeg.webp)r,  r   extract_mediaextract_imagesextract_local_filesr  r  r   r   r!  r  
send_videosend_image_filesend_documentr   r  r  r   )rv  rJ  r   r   r   media_filesr   cleanedlocal_files_thread_meta_AUDIO_EXTS_VIDEO_EXTS_IMAGE_EXTS
media_pathis_voiceextrx  r"  s   &&&&              r   r  *GatewayRunner._deliver_media_from_response|  s     	!<	I$228<NK //9JA$88ANKDILLDZDZDZK)?)?@`dLCKKKDK(3$
bz*11779C)%00$)LL$8$8'1%1 1   
 +%00$)LL$8$8'1%1 1   
 +%55$)LL$8$8'1%1 6    &33$)LL$8$8&0%1 4   - )4< )	ay/00668C)%55$)LL$8$8'0%1 6    &33$)LL$8$8&/%1 4    )5
 ! bNN#OQXQ]Q]_`aab
 ! aNN#NPWP\P\^_``a  	INNDaHH	Is!  KBJ" AH(HH(#J" %1H(H!H(J" 1H(H$H(J" +H( H&H(
J" AI'!I#"I'&J" (+I'I%I'J" KH(!H($H(&H((I 3!IJ" I  J" #I'%I''J2!JJ" JJ" "K-K	K	KKc                &   < V ^8  d   QhRS[ RS[/# rW  r  )r   r2  s   "r   r   r3    s     9( 9(L 9(S 9(r   c                X  "   ^ RI HpHp / p ^ RIp\        R,          pVP                  4       '       df   \        VRR7      ;_uu_ 4       pVP                  V4      ;'       g    / pRRR4       XP                  R/ 4      p\        V\        4      '       d   RV/pTP                  RR4      '       g    R	# T! R
TP                  R^24      R7      p	\        P                  ! R\        \        P                   ! 4       4      4      p
TP#                  4       P%                  4       pT'       g   T	P'                  T
4      pT! Y4      # T	P'                  T
4      pT'       g   RT
 2# Rp \)        T4      ^,
          p^ Tu;8:  d   \+        T4      8  d   M MY,          R,          pMR\+        T4       R2# T	P/                  Y4      pTR,          '       d   RTR,           RTR,           R2# RTR,           2#   + '       g   i     EL; i  \         d     ELyi ; i  \,         d    Tp Lxi ; i5i)uD   Handle /rollback command — list or restore filesystem checkpoints.)CheckpointManagerformat_checkpoint_listNr)   r*   r+   checkpointsr  FzXCheckpoints are not enabled.
Enable in config.yaml:
```
checkpoints:
  enabled: true
```Tmax_snapshots)r  r`  r{   zNo checkpoints found for hashz!Invalid checkpoint number. Use 1-.r  u   ✅ Restored to checkpoint restored_tord  r  z1
A pre-rollback snapshot was saved automatically.u   ❌ r  )tools.checkpoint_managerr]  r^  r  r   r   r  r  r   r  r}  r   r   r   r   r   r-  r  r   list_checkpointsr  r   rt  restore)rv  r   r]  r^  cp_cfgr#  	_cfg_pathr%  _datamgrr1   argr_  target_hashidxr3  s   &&              r   r  &GatewayRunner._handle_rollback_command  s
    V 
	$}4I!!)g66"LL,22E 7="5fd++'0F zz)U++R
   **_b9

 iiTYY[)9:$$&,,...s3K)+;; **3/.se44	c(Q,CC*#k**).v6:3{;K:LANN S.)-f].C-DBvhGWFX YC D fWo&''_ 766
  		B  	K	s~   H*<H 
G1&4H H*2B'H*H*"<H H*H -AH*1H	<	H HH*HH*H'$H*&H''H*c                &   < V ^8  d   QhRS[ RS[/# rW  r  )r   r2  s   "r   r   r3    s     J Jl Js Jr   c                .  "   VP                  4       P                  4       pV'       g    R# VP                  pR\        P                  ! 4       P                  R4       R\        P                  ! ^4      P                  4        2p\        P                  ! V P                  W#V4      4      pV P                  P                  V4       VP                  V P                  P                  4       VR,          \!        V4      ^<8  d   RMR,           pRV R	V R
2# 5i)u	  Handle /background <prompt> — run a prompt in a separate background session.

Spawns a new AIAgent in a background thread with its own session.
When it completes, sends the result back to the same chat without
modifying the active session's conversation history.
u   Usage: /background <prompt>
Example: /background Summarize the top HN stories today

Runs the prompt in a separate session. You can keep chatting — the result will appear here when done.bg_%H%M%Sr   N<   Nr  rk   u   🔄 Background task started: "z"
Task ID: u9   
You can keep chatting — results will appear when done.)r  r   r  r   r  r6  r   urandomr,  rY  r  _run_background_taskru  r   r  r  r   )rv  r   r+  r  r  r  r  s   &&     r   r  (GatewayRunner._handle_background_command  s      '')//1S //9:!BJJqM<M<M<O;PQ ##%%fg>
 	""5) 6 6 > >?+#f+*:C0	gY  OI  J  	Js   DDc                .   < V ^8  d   QhRS[ RRRS[ RR/# )r   r+  r  r   r  r   Nr   )r   r2  s   "r   r   r3     s3      #2=@	r   c           
     d  a aaaaaaaaa"   ^ RI Ho S P                  P                  VP                  4      pV'       g$   \
        P                  RVP                  S4       R# VP                  '       d   RVP                  /MRp \        4       pVP                  R4      '       g-   VP                  VP                  RS R2VR7      G Rj  xL
  R# \        4       p\        V4      p\        VP                  4      o^ R	IHp	 \!        V	! VS4      4      oS P"                  o\%        \&        P(                  ! R
R4      4      oS P+                  4       oSS n        S P/                  SW4      oVVVVVVVV VV3
R lp
\0        P2                  ! 4       pVP5                  RV
4      G Rj  xL
 pV'       d   VP                  RR4      MRpV'       g,   V'       d$   VP                  R4      '       d   RVR,           2pV'       Ed;   VP7                  V4      w  rVP9                  V4      w  ppSR,          \;        S4      ^<8  d   RMR,           pRV R2pV'       d/   VP                  VP                  VV,           VR7      G Rj  xL
  M=V'       g6   V'       g.   VP                  VP                  VR,           VR7      G Rj  xL
  T;'       g    .  F-  w  pp VP=                  VP                  VVR7      G Rj  xL
  K/  	  T;'       g    .  F)  p VPA                  VP                  VR7      G Rj  xL
  K+  	  R# SR,          \;        S4      ^<8  d   RMR,           pVP                  VP                  RV R2VR7      G Rj  xL
  R#  EL EL EL L L  \>         d     K  i ; i Lw  \>         d     K  i ; i L9  \>         df   p\
        PC                  RS4        TP                  TP                  RS RT 2TR7      G Rj  xL 
   Rp?R#   \>         d	      Rp?R# i ; iRp?ii ; i5i)zCExecute a background agent task and deliver the result to the chat.r  z0No adapter for platform %s in background task %sNr  r_   u   ❌ Background task z, failed: no provider credentials configured.r  _get_platform_toolsro   90c            "      x  <
 S! RR S
R ,          /S
R,          BRSRRRRRSRSR	SP                  R
4      RSP                  R4      RSP                  R4      RSP                  R4      RSP                  RR4      RSP                  R4      RS	RSRSP                  RSP                  /B p V P                  SS	R7      # )r[   r   r  r  Tverbose_loggingFr  reasoning_configproviders_allowedonlyproviders_ignoredignoreproviders_orderorderprovider_sortsortprovider_require_parametersrequire_parametersprovider_data_collectiondata_collectionr  r  
session_dbrL  )r  r  r   )r   rm  rQ  r  )rm   r  r  r  platform_keyprr+  r  rv  r  
turn_routes    r   run_sync4GatewayRunner._run_background_task.<locals>.run_syncD  s     $W- + $2  $	
 %* &6 &6 ')ffVn ')ffX&6 %'FF7O #%&&. 137KU0S .0VV4E-F  ' *   $//!" $(#7#7#( --!'# .  r   rA  rk   r  rp  rs  r  u&   ✅ Background task complete
Prompt: ""

r  r  r  (No response generated)r  	image_urlcaptionr  r"  z"

(No response generated)zBackground task %s failedz	 failed: )"r  r  rE  r   r  r  r  r  r   r  r  r  r   r  hermes_cli.tools_configr{  r  rO  r  r   r   rJ  rK  r   rY  r  r  rJ  rK  r   
send_imager   rO  r  )rv  r+  r  r  r   _thread_metadatar  r  r[   r{  r  r  r3  rJ  rP  imagestext_contentr  r&  r  alt_textrW  rx  r  r  r  r  r  r  r  s   ff&f                   @@@@@@@r   rv  "GatewayRunner._run_background_task   s     	&--##FOO4NNMv`gh>D>N>N>NK)9)9:TXr	:<N!%%i00llNN*7)3_`- #   
 .0K*;7E/@LC%&9+|&TU''B +BD!IJN#::<%5D"88WJ 4 ))+D//h??F;Avzz"2B7rH6::g+>+>$VG_$56 x(/(=(=h(G%'.'='=h'G$ +#f+2BKB7)5Q!,, & & 5!1 '   
  !,, & &)B B!1 '    -3LLbL'Ix%00$*NN&/$, 1    -9 $/#4#4"#4J%33$*NN&0 4    $5 !+#f+2BKll"NNEgYNjk- #   A^ @
 %  %   		8'Bll"NN27)9QCH- #   
  		s~  A(P05P0AN= NN= P0CN= #N$N= 0N= N= N= +N=  AN= (N= ?N N= N= (N= =N>N= 	N= !N6N7N;N= N=  N)/N'0N)4N= 8P0:AN= N;N= P0N= N= N= N= NN$ N= #N$$N= 'N))N84N= 7N88N= =P-P('PP	PP0P%P(P0$P%%P((P--P0c                &   < V ^8  d   QhRS[ RS[/# rW  r  )r   r2  s   "r   r   r3    s     #J #J| #J #Jr   c                   a a
"   VP                  4       P                  4       pV'       g    R# VP                  pS P                  V4      o
\	        S R/ 4      P                  S
4      pV'       d   VP                  4       '       g   R# \        S R4      '       g   / S n        ^ RI	pR\        P                  ! 4       P                  R4       RVP                  4       P                  R,           2p\        P                   ! S P#                  W#S
V4      4      pS P$                  P'                  V4       VS P                  S
&   V V
3R	 lpVP)                  V4       VR
,          \+        V4      ^<8  d   RMR,           p	RV	 R2# 5i)uD   Handle /btw <question> — ephemeral side question in the same chat.zUsage: /btw <question>
Example: /btw what module owns session title sanitization?

Answers using session context. No tools, not persisted._active_btw_tasksz?A /btw is already running for this chat. Wait for it to finish.Nbtw_rr  r   N   Nc                    < SP                   P                  V 4       SP                  P                  S4      V J d   SP                  P	                  SR 4       R # R # r9  )ru  r  r  r   r   )taskrv  r   s   &r   _cleanup3GatewayRunner._handle_btw_command.<locals>._cleanup  sK    ""**40%%))+6$>&&**;= ?r   rs  r  rk      💬 /btw: "z!"
Reply will appear here shortly.)r  r   r  r  r   r   doner  r  r&  r   r  r6  r+  r,  rY  r  _run_btw_taskru  r   r  r   )rv  r   questionr  r  r1  r  r  r  r  r   s   f&        @r   r  !GatewayRunner._handle_btw_command  sE    ))+113J 226: 4!4b9==kJHMMOOTt011+-D"00:;1U[[]=N=Nr=R<ST##D$6$6xV]$^_""5).3{+	>
 	)3-CMB,>5BGgY&HIIs   B E>C9E>c                0   < V ^8  d   QhRS[ RS[ RS[ RR/# )r   r  r   r  r   Nr   )r   r2  s   "r   r   r3    s3     y yy25y@Cy	yr   c           	     v  a aaaaaaaa"   ^ RI Ho S P                  P                  VP                  4      pV'       g$   \
        P                  RVP                  S4       R# VP                  '       d   RVP                  /MRp \        4       pVP                  R4      '       g)   VP                  VP                  RVR7      G Rj  xL
  R# \        4       p\        V4      p	\        VP                  4      oS P                  4       oS P                  WV4      oS P                   oS P"                  P                  V4      p
V
'       d,   V
\$        Jd"   \'        \)        V
R. 4      ;'       g    . 4      oM@S P*                  P-                  V4      pS P*                  P/                  VP0                  4      oR	V,           oVVVVVVV VV3	R
 lp\2        P4                  ! 4       pVP7                  RV4      G Rj  xL
 pV'       d   VP                  R4      ;'       g    RMRpV'       g,   V'       d$   VP                  R4      '       d   RVR,           2pV'       g   RpVP9                  V4      w  ppVP;                  V4      w  ppVR,          \=        V4      ^<8  d   RMR,           pRV R2pV'       d/   VP                  VP                  VV,           VR7      G Rj  xL
  M=V'       g6   V'       g.   VP                  VP                  VR,           VR7      G Rj  xL
  T;'       g    .  F-  w  pp VP?                  VP                  VVR7      G Rj  xL
  K/  	  T;'       g    .  F)  p VPC                  VP                  VR7      G Rj  xL
  K+  	  R#  EL EL L L LM  \@         d     K  i ; i L(  \@         d     K]  i ; i  \@         dc   p\
        PE                  RS4        TP                  TP                  RT 2TR7      G Rj  xL 
   Rp?R#   \@         d	      Rp?R# i ; iRp?ii ; i5i)z?Execute an ephemeral /btw side question and deliver the answer.r  z*No adapter for platform %s in /btw task %sNr  r_   u4   ❌ /btw failed: no provider credentials configured.r  _session_messageszs[Ephemeral /btw side question. Answer using the conversation context. No tools available. Be direct and concise.]

c            
        <	 S! RR S	R ,          /S	R,          B/ R^bRRbRRbR. bRSbR	SP                  R
4      bRSP                  R4      bRSP                  R4      bRSP                  R4      bRSP                  RR4      bRSP                  R4      bRSbRSbRRbRSP                  bRRbRRbRRbB p V P                  SSSR7      # )r[   r   r  r  Tr~  Fr  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  NrL  r  skip_context_filespersist_session)r  r  r  r   )r   rQ  r  )
rm   r  
btw_prompthistory_snapshotr  r  r  rv  r  r  s
    r   r  -GatewayRunner._run_btw_task.<locals>.run_sync  s;    $W- + $%  $	
 %* &( &6 ')ffVn ')ffX&6 %'FF7O #%&&. 137KU0S .0VV4E-F  ' *   $!" $(#7#7#$ !%%& (,'( %*), --!+)9# .  r   rA  rk   r  rp  r  rs  r  r  r  r  r  r  z/btw task %s failedu   ❌ /btw failed: )#r  r  rE  r   r  r  r  r  r   r  r  r  r   r  rJ  r   rO  r_  r  r   r   rV  rg  r  r  rY  r  r  rJ  rK  r   r  r   	send_filer  ) rv  r  r  r   r  r   rS  r  r  r[   r  r  r  r  r3  rJ  rP  r  r  r  r&  r  r  rW  rx  r  r  r  r  r  r  r  s    f&&&f                    @@@@@@@r   r  GatewayRunner._run_btw_task  s     	&--##FOO4NNGZab:@:J:J:JV%5%56PTl	:<N!%%i00llNNJ) #   
 .0K*;7E/@L#::<88.YJ''B !0044[AM6M!M#'?RTV(W(](][]#^  $ 2 2 H H P#'#5#5#E#EmF^F^#_ K  : ))+D//h??F?E

#34::2H6::g+>+>$VG_$564$+$9$9($C!K#*#9#9(#C FLsmH0BuKG#G9E2Fll"NN"\1) #   
 Kll"NN"%>>) #    )/"#	8!,,V^^ybj,kkk )5  +00b0
!++FNNj+YYY  1ut @ l  
 Z    		2G<ll"NN/s3) #   
  		sr  A(P94P9AO	 NO	 P9BO	 ,B	O	 5N6O	 O	 O	 'O	 /O	 O	 AO	 4(O	 NO	 *O	 2(O	 NO	 (	O	 2!N#N!N#O	 %O	 , N7N5N7O	 P9O	 O	 O	 O	 !N##N2.O	 1N22O	 5N77OO	 OO	 	P6P1+$PPPP9P.&P1'P9-P..P11P66P9c                &   < V ^8  d   QhRS[ RS[/# rW  r  )r   r2  s   "r   r   r3  A  s#     QV QV\ QVc QVr   c                  a	a
"   ^ RI o
VP                  4       P                  4       P                  4       p\        R,          o	V P                  4       V n        V P                  4       V n        R V	V
3R llpV'       g]   V P                  pVf   RpM*VP                  R4      RJ d   RpMVP                  R	R
4      pV P                  '       d   RMRpRV RV R2# VR9   d   RV n        V! RR4       R# VR9   d   RV n        V! RR4       R# VP                  4       pVR8X  d   RR/pMVR9   d   RRR	V/pMRV R2# Wn        V! RV4      '       d   RV R2# RV R2# 5i)uj  Handle /reasoning command — manage reasoning effort and display toggle.

Usage:
    /reasoning              Show current effort level and display state
    /reasoning <level>      Set reasoning effort (none, low, medium, high, xhigh)
    /reasoning show|on      Show model reasoning in responses
    /reasoning hide|off     Hide model reasoning from responses
Nr)   c                $    V ^8  d   QhR\         /# )r   key_pathr   )r   s   "r   r   =GatewayRunner._handle_reasoning_command.<locals>.__annotate__Q  s     	 	s 	r   c                  <  / pSP                  4       '       d:   \        SRR7      ;_uu_ 4       pS	P                  V4      ;'       g    / pRRR4       V P                  R4      pTpVRR  F1  pWe9  g   \	        WV,          \
        4      '       g   / WV&   WV,          pK3  	  WVR,          &   \        SV4       R#   + '       g   i     Lv; i  \         d"   p\        P                  RY4        Rp?R# Rp?ii ; i)	z(Save a dot-separated key to config.yaml.r*   r+   Nrb  Tz Failed to save config key %s: %sFr  )
r   r  r  r   r  r   r$   r   r  r  )
r  r   r  r  r  r   krx  r  r  s
   &&      r   _save_config_keyAGatewayRunner._handle_reasoning_command.<locals>._save_config_keyQ  s     %%''kG<<&*nnQ&7&=&=2 =~~c*%crA'z'*d/K/K%'
%jG # %*R!!+{; =<  ?Ms4   C C B:A,C :C
	C C9C44C9zmedium (default)r  Fznone (disabled)r2  mediumu   on ✓r  u*   🧠 **Reasoning Settings**

**Effort:** `z`
**Display:** z>

_Usage:_ `/reasoning <none|low|medium|high|xhigh|show|hide>`Tzdisplay.show_reasoninguU   🧠 ✓ Reasoning display: **ON**
Model thinking will be shown before each response.u#   🧠 ✓ Reasoning display: **OFF**r  u   ⚠️ Unknown argument: `zT`

**Valid levels:** none, low, minimal, medium, high, xhigh
**Display:** show, hidezagent.reasoning_effortu"   🧠 ✓ Reasoning effort set to `z4` (saved to config)
_(takes effect on next message)_z` (this session only))showr  )hider  )xhighhighr  lowminimal)
r  r  r   r   r   rJ  rK  rL  rM  r   )rv  r   r   r  rcleveldisplay_stater2  parsedr  r  s   &&       @@r   r  'GatewayRunner._handle_reasoning_commandA  s     	%%'--/557"]2!%!<!<!>#88:	 	( ''Bz*	"e+)x2(,(<(<(<H%M  %w '  - /OO >!#'D 5t<k?"#(D 5u=8 V'FDDx8F -VH 5* * "(4f==7x?tuu7x?TUUs   CEBEc                &   < V ^8  d   QhRS[ RS[/# rW  r  )r   r2  s   "r   r   r3    s     \ \ \ \r   c                   "   \        \        P                  P                  R4      4      pV'       d#   \        P                  P	                  RR4       R# R\        P                  R&   R# 5i)u:   Handle /yolo — toggle dangerous command approval bypass.HERMES_YOLO_MODENuF   ⚠️ YOLO mode **OFF** — dangerous commands will require approval.rx   uF   ⚡ YOLO mode **ON** — all commands auto-approved. Use with caution.)r}  r   r   r   r   )rv  r   r   s   && r   r  "GatewayRunner._handle_yolo_command  sH     rzz~~&89:JJNN-t4[-0BJJ)*[s   A(A*c                &   < V ^8  d   QhRS[ RS[/# rW  r  )r   r2  s   "r   r   r3    s     ;R ;R< ;RC ;Rr   c                  "   ^ RI p\        R,          p / pVP                  4       '       d:   \        VRR7      ;_uu_ 4       pVP	                  V4      ;'       g    / pRRR4       VP                  R/ 4      P                  RR4      pV'       g    R# . ROpR	RR
RRRRR/pXP                  R/ 4      P                  RR4      p	V	RJ d   R	p
M"V	RJ d   Rp
M\        V	4      P                  4       p
W9  d   Rp
VP                  V
4      ^,           \        V4      ,          pW{,          p RV9  g&   \        VP                  R4      \        4      '       g   / VR&   WR,          R&   \        W44       W,           R2#   + '       g   i     EL$; i  \         d    Rp ELi ; i  \         d/   p\        P                  RT4       Y,           RT R2u Rp?# Rp?ii ; i5i)u   Handle /verbose command — cycle tool progress display mode.

Gated by ``display.tool_progress_command`` in config.yaml (default off).
When enabled, cycles the tool progress mode through off → new → all →
verbose → off, same as the CLI.
Nr)   r*   r+   r7  tool_progress_commandFzThe `/verbose` command is not enabled for messaging platforms.

Enable it in `config.yaml`:
```yaml
display:
  tool_progress_command: true
```r  rp  r  ry  u9   ⚙️ Tool progress: **OFF** — no tool activity shown.uK   ⚙️ Tool progress: **NEW** — shown when tool changes (short previews).uI   ⚙️ Tool progress: **ALL** — every tool call shown (short previews).uJ   ⚙️ Tool progress: **VERBOSE** — every tool call with full arguments.tool_progressTu5   
_(saved to config — takes effect on next message)_z%Failed to save tool_progress mode: %sz
_(could not save to config: r  )r  rp  r  ry  )r  r   r   r  r  r   r   r   r   indexr   r  r   r$   r  r  )rv  r   r  r  r  r  gate_enabledcycledescriptionsraw_progressr   rm  new_moderx  s   &&            r   r  %GatewayRunner._handle_verbose_command  s     	"]2	!K!!##+88A"&.."3"9"9rK 9&??9b9==>UW\]L ? 1N`^c	
 #y"599/5Q5 GT!G,'--/GG{{7#a'3u:5:	R+:kooi>XZ^3_3_)+I&6>	"?3k7",--cddS 988  	! L	!N  	RNNBAF",--KA3bQQ	Rsx   G-F E9*F GBG'AF! 8G9F
		F FGFG!G,#GGGGGc                &   < V ^8  d   QhRS[ RS[/# rW  r  )r   r2  s   "r   r   r3    s     C. C.L C.S C.r   c                  aaa"   VP                   pV P                  P                  V4      pV P                  P                  VP                  4      pV'       d   \        V4      ^8  d   R#  ^ RIHp ^ RIH	p \        4       pVP                  R4      '       g   R# \        4       pV U	u. uFX  p	V	P                  R4      R9   g   K  V	P                  R4      '       g   K4  RV	P                  R4      RV	P                  R4      /NKZ  	  up	o\        S4      p
V! S4      oV! R/ VBRVR	^R
RRR.RVP                  /B oR Sn        \        P                  ! 4       pVP!                  RVVV3R l4      G Rj  xL
 w  rSP                  pWP                  8w  d!   Wn        V P                  P#                  4        V P                  P%                  W4       V P                  P'                  VP(                  ^ R7       \        V4      pV! V4      pRV
 RV RSR RVR R2	# u up	i  L  \*         d&   p\,        P/                  RT4       RT 2u Rp?# Rp?ii ; i5i)zCHandle /compress command -- manually compress conversation context.z?Not enough conversation to compress (need at least 4 messages).r  r  r_   z*No provider configured -- cannot compress.r  r  r[   r  r  Tr  r  r  c                      R # r9  r   r  s   *,r   r<  8GatewayRunner._handle_compress_command.<locals>.<lambda>  r  r   Nc                  ,   < SP                  SR S R7      # r#  r%  )r$  r  r  s   r   r<  r    s    	33D"M3Zr   rR  u   🗜️ Compressed: u    → z messages
~r>  u    → ~rv  zManual compress failed: %szCompression failed: r  r   )r  rV  rg  r  r  r   r  r  rr  r  r   r   r   r  rY  r  r  r  rv  r  r   r   r  r  )rv  r   r  r  r  r  r  r  r[   r  original_countr  
compressedr   new_session_id	new_count
new_tokensrx  r$  r  r  s   &&                @@@r   r  &GatewayRunner._handle_compress_command  s_    **@@H$$44]5M5MN#g,*T:	.)K:<N!%%i00C +,E ! A55=$99 E>?eeI>N Ev	1553CD D
 !YN:4@M    !  	
 #+ )33I #8I))+D"&"6"6Z# MJ '11N!9!99+9(""((*11.M--))a .  JI7
CJ '~&6eI; G!!$F:a.AS&4  	.NN7;)!--	.sn   A'I--H% IH% *HH (HA-H% 5H#6B'H% IH% %I0I
IIIIc                &   < V ^8  d   QhRS[ RS[/# rW  r  )r   r2  s   "r   r   r3     s     .f .f .f# .fr   c                ^  "   VP                   pV P                  P                  V4      pVP                  pV P                  '       g   R# V P                  P                  V4      pVfR    V P                  P                  TVP                  '       d   VP                  P                  MRVP                  R7       VP                  4       P                  4       pV'       dQ    V P                  P                  V4      pT'       g   R#  T P                  P                  YG4      '       d   RT R2# R	# V P                  P                  V4      p	V	'       d
   R
V RV	 R2# R
V R2#   \         d     Li ; i  \         d   pRT 2u Rp?# Rp?ii ; i  \         d   pRT 2u Rp?# Rp?ii ; i5i)uB   Handle /title command — set or show the current session's title.Session database not available.Nr  )r  r  rA     ⚠️ uE   ⚠️ Title is empty after cleanup. Please use printable characters.u   ✏️ Session title set: **rb  zSession not found in database.u   📌 Session: `z`
Title: **z/`
No title set. Usage: `/title My Session Name`)r  rV  rg  r  rm  get_session_titlecreate_sessionr  r   rA  r   r  r   sanitize_titlert  set_session_title)
rv  r   r  r  r  existing_title	title_arg	sanitizedrx  r  s
   &&        r   r  #GatewayRunner._handle_title_command   s    **@@H"--
4 ));;JG!  //)4:OOO6??00"NN 0  **,224	% ,,;;IF	 ^%##55jLL9)BGG;
 $$66zBE(LrJJ(4dee5    % }$%  % }$%s   A'F-*'E" (E" :%F-!E3 <F-F-&F -%F-F-"E0-F-/E00F-3F>FFF-FF-F*F%F* F-%F**F-c                &   < V ^8  d   QhRS[ RS[/# rW  r  )r   r2  s   "r   r   r3  P  s#     KT KT, KT3 KTr   c                  "   V P                   '       g   R# VP                  pV P                  V4      pVP                  4       P	                  4       pV'       g    VP
                  '       d   VP
                  P                  MRpV P                   P                  V^
R7      pV Uu. uF  qwP                  R4      '       g   K  VNK  	  ppV'       g    R# R.p	VR,           FL  pVR,          p
VP                  RR	4      R
,          pV'       d   RV R2MR	pV	P                  RV
 RV 24       KN  	  V	P                  R4       RP                  V	4      # V P                   P                  V4      pV'       g   RV R2# V P                  P!                  V4      pVP"                  V8X  d   RV R2#  \$        P&                  ! V P)                  VP"                  4      4      pV P*                  P-                  V4       VP/                  V P*                  P0                  4       W0P2                  9   d   V P2                  V V P                  P5                  W>4      pV'       g   R# V P                   P7                  V4      ;'       g    Tp
V P                  P9                  V4      pV'       d4   \;        V Uu. uF  pVP                  R4      R8X  g   K  VNK  	  up4      M^ pV'       d   RT RV^8w  d   RMR	 R2MR	pRV
 RV R 2# u upi   \         d&   p\        P                  RT4       RT 2u Rp?# Rp?ii ; i  \         d"   p\        P                  RT4        Rp?ELCRp?ii ; iu upi 5i)!u@   Handle /resume command — switch to a previously-named session.r  N)r  limitr  zNo named sessions found.
Use `/title My Session` to name your current session, then `/resume My Session` to return to it later.u   📋 **Named Sessions**
rC  r  rk   r  u    — _r   u   • **rb  z 
Usage: `/resume <session name>`r   z"Failed to list titled sessions: %szCould not list sessions: zNo session found matching '**z?**'.
Use `/resume` with no arguments to see available sessions.u   📌 Already on session **z**.z!Memory flush on resume failed: %szFailed to switch session.r  r  rh   messagesr  u   ↻ Resumed session **z. Conversation restored.)rm  r  r  r  r   r  r   list_sessions_richr   r   r   r   r  r  resolve_session_by_titlerV  rg  r  rY  r  r  ru  r   r  r  r_  switch_sessionr  r  r   )rv  r   r  r   r   user_sourcesessionsr  titledr  r  r  preview_partrx  	target_idcurrent_entryr$  r%  r  r  	msg_countmsg_parts   &&                    r   r  $GatewayRunner._handle_resume_commandP  s.    4226:%%'--/77=foo33D++>>&b ?  &.@Xw!!X@K
 55AgJEeeIr237G:AVG9A#6rLLL6%<.!AB	 %
 @Ayy'' $$==dC	/v 6M M **@@H##y0/vS99	A!--**=+C+CDK ""&&{3))$*@*@*H*HI
 ...$$[1 &&55kM	.   229=EE $$44Y?LSCGGGqquuV}/FGGHYZ	OXR	{()q.3b*IK^`'wb
:RSSw A  7A1E21#6670  	ALL<a@@	A" Hs   AM/L -9L &LL	L M/A=L #M/78M/0A/L; A#M/%M/)	M/2M*M*M/&M/L L8L3-L8.M/3L88M/;M'M"M/"M''M/c                &   < V ^8  d   QhRS[ RS[/# rW  r  )r   r2  s   "r   r   r3    s     X
 X
, X
3 X
r   c                  "   ^ RI pV P                  '       g   R# VP                  pV P                  V4      pV P                  P                  V4      pV P                  P                  VP                  4      pV'       g   R# TP                  4       P                  4       p^ RI
H
p VP                  4       p	V	P                  R4      p
VP                  4       P                  R,          pV
 RV 2pV'       d   TpMLV P                  P                  VP                  4      pT;'       g    RpV P                  P!                  V4      pVP                  p V P                  P#                  TVP$                  '       d   VP$                  P&                  MR	\)        V P*                  \,        4      '       d6   V P*                  P/                  R
/ 4      ;'       g    / P/                  R4      MRVR7       T F  p T P                  P7                  TTP/                  RR4      TP/                  R4      TP/                  R4      ;'       g    TP/                  R4      TP/                  R4      TP/                  R4      TP/                  R4      R7       K  	   T P                  P9                  Y4       T P                  P;                  YL4      pT'       g   R# T P=                  T4       \?        T Uu. uF  pTP/                  R4      R8X  g   K  TNK  	  up4      pRT RT RT^8w  d   RMR RT RT R 2#   \0         d&   p\2        P5                  RT4       RT 2u Rp?# Rp?ii ; i  \0         d     EK  i ; i  \0         d     Li ; iu upi 5i)!u   Handle /branch [name] — fork the current session into a new independent copy.

Copies conversation history to a new session so the user can explore
a different approach without losing the original.
Inspired by Claude Code's /branch command.
Nr  u3   No conversation to branch — send a message first.r   z%Y%m%d_%H%M%Sr  r   r  gatewayr[   r  )r  r  r[   parent_session_idz#Failed to create branch session: %szFailed to create branch: r  r  r  	tool_namer   r  tool_call_idrx  )r  r  r  r  r  r  rx  z*Branch created but failed to switch to it.u   ⑂ Branched to **z** (r  r  rk   z copied)
Original: `z`
Branch: `z/`
Use `/resume` to switch back to the original.) r&  rm  r  r  rV  rg  r  r  r  r   r   r  r6  r+  r,  r  get_next_title_in_lineager  r  r   r  r  r   r   r   r  r  append_messager  r  r  r   )rv  r   r1  r  r   r  r  branch_name_dtr  timestamp_str
short_uuidr  branch_titlecurrent_titlebaser
  rx  r  r%  r  r  s   &&                    r   r  $GatewayRunner._handle_branch_command  s+     	4226: **@@H$$44]5M5MNH,,.446 	-ggi_5[[]&&r*
)?!J<8 &L ,,>>}?W?WXM ,,HD++EEdKL)44		3++)06v,,YMWX\XcXceiMjMjt{{w399r>>yIpt"3	 ,  C  //-0GGI.!ggk2EEcggfo"ww|4!$!8!ggk2 0  	..~L
 &&55kR	? 	  -GGGqquuV}/FGGH	  /89>Cr#B C+, -&' (<=	
E  	3LL>B.qc22	3     		 Hs   A=N A6N70N(*N'L/ ;AL/ L/ /N5AM"AM"NM5 +?N*NN"N/M:MMNMN"M2-N1M22N5N NNNc                &   < V ^8  d   QhRS[ RS[/# rW  r  )r   r2  s   "r   r   r3    s     #; #; #;# #;r   c           	     Z  "   VP                   pV P                  V4      pV P                  P                  V4      pV'       Ed7   \	        VR4      '       Ed$   VP
                  ^ 8  Ed   RRVP                  R 2RVP                  R 2RVP                  R 2RVP
                   2.pVP                  pVP                  '       du   VP                  '       d/   \        ^dVP                  VP                  ,          ^d,          4      M^ pVP                  RVP                  R R	VP                  R R
VR R24       VP                  '       d   VP                  RVP                   24       RP                  V4      # V P                   P#                  V4      pV P                   P%                  VP&                  4      p	V	'       dc   ^ RIHp
 V	 Uu. uF5  qP                  R4      R9   g   K  VP                  R4      '       g   K3  VNK7  	  ppV
! V4      pR\-        V4       RVR R2# R# u upi 5i)zKHandle /usage command -- show token usage for the session's last agent run.session_total_tokensu   📊 **Session Token Usage**zPrompt (input): r>  zCompletion (output): zTotal: zAPI calls: ru  z / rh  ri  z%)zCompressions: r   r  r  r  u    📊 **Session Info**
Messages: z
Estimated context: ~z@ tokens
_(Detailed usage available during active conversations)_z)No usage data available for this session.r  )r  r  r_  r   r  session_api_callssession_prompt_tokenssession_completion_tokensr  context_compressorrQ  r  r  r   compression_countr   rV  rg  r  r  rr  r  r   )rv  r   r  r   rm   r  r  pctr  r  r  r  r  approxs   &&            r   r  #GatewayRunner._handle_usage_command  s    226:$$((55WU$:;;@W@WZ[@[."5#>#>q"AB'(G(G'JK%44Q78e5567E **C%%%UXUgUgUgc#s558J8JJSPQmny)?)?(B#cFXFXYZE[[]^abe]ffhij$$$~c.C.C-DEF99U## **@@H$$44]5M5MNK&fw!%%-;P*PAUVUZUZ[dUeAAwDf3D9F YK (''-aj 1KL ; gs8   CH+H+A3H+A6H+
H+H&(H&H&$H+c                &   < V ^8  d   QhRS[ RS[/# rW  r  )r   r2  s   "r   r   r3    s     -5 -5L -5S -5r   c                x  a	a
aa"   ^ RI pVP                  4       P                  4       p^oRoV'       d   VP                  4       p^ pV\	        V4      8  d   WE,          R8X  d<   V^,           \	        V4      8  d%    \        WE^,           ,          4      oT^,          pKX  WE,          R8X  d2   V^,           \	        V4      8  d   WE^,           ,          oV^,          pK  WE,          P                  4       '       d   \        WE,          4      oV^,          pK  V^,          pK   ^ RIH	o
 ^ RI
Ho	 VP                  4       pV	V
VV3R lpVP                  RV4      G Rj  xL
 #   \         d    RYE^,           ,           2u # i ; i L'  \         d(   p\        P!                  RTR	R
7       RT 2u Rp?# Rp?ii ; i5i)z>Handle /insights command -- show usage insights and analytics.Nz--dayszInvalid --days value: z--sourcerA  )InsightsEnginec                     < S! 4       p S! V 4      pVP                  SSR 7      pVP                  V4      pV P                  4        V# ))daysr  )generateformat_gatewayclose)dbenginereportr3  r$  rB  r&  r  s       r   _run_insights=GatewayRunner._handle_insights_command.<locals>._run_insights>  sD    ['+d6B..v6
r   zInsights command error: %sTr$  zError generating insights: )rY  r  r   r   r   r  rt  isdigitrn  rB  agent.insightsr$  r  r  r   r  r  )rv  r   _asyncior   r   r   r  r-  rx  r$  rB  r&  r  s   &&       @@@@r   r  &GatewayRunner._handle_insights_command  su    "%%'--/ JJLEAc%j.8x'AECJ,>G"5Q<0 FAX+AE
0B"q5\FFAX%%''ux=DFAFA	5.5**,D  --dMBBB5 & G!7!e~FFG4 C 	5LL5q4LH044	5sm   A5F:<E  BF:!:F FF F: F =F:?F  F:F F7F2,F7-F:2F77F:c                &   < V ^8  d   QhRS[ RS[/# rW  r  )r   r2  s   "r   r   r3  K  s     D1 D1l D1s D1r   c                  "   \         P                  ! 4       p ^ RIHpHpHpHpHp V;_uu_ 4        \        VP                  4       4      pRRR4       V! 4       p	\        V	P                  4       4      p
VP                  RV4      G Rj  xL
  VP                  RV4      G Rj  xL
 pV;_uu_ 4        \        VP                  4       4      pRRR4       XX,
          pW,
          pW,          pR.pV'       d-   VP                  RRP                  \        V4      4       24       V'       d-   VP                  RRP                  \        V4      4       24       V'       d-   VP                  RRP                  \        V4      4       24       V'       g   VP                  R4       M*VP                  R	\        V4       R
\        V4       R24       . pV'       d-   VP                  RRP                  \        V4      4       24       V'       d-   VP                  RRP                  \        V4      4       24       V'       d-   VP                  RRP                  \        V4      4       24       V'       d   \        V4       R2MRpV'       d   RP                  V4      R,           MRpRRRRV V R2/p V P                  P!                  VP"                  4      pV P                  P%                  VP&                  V4       RP                  V4      #   + '       g   i     EL; i EL EL  + '       g   i     ELh; i  \(         d     LLi ; i  \(         d&   p\*        P-                  RT4       RT 2u Rp?# Rp?ii ; i5i)zGHandle /reload-mcp command -- disconnect and reconnect all MCP servers.)shutdown_mcp_serversdiscover_mcp_tools_load_mcp_config_serversr  Nu   🔄 **MCP Servers Reloaded**
u   ♻️ Reconnected: ro  u   ➕ Added: u   ➖ Removed: zNo MCP servers connected.u   
🔧 z tool(s) available from z
 server(s)zAdded servers: zRemoved servers: zReconnected servers: z MCP tool(s) now availablezNo MCP tools availablez. rk   r  r  r  z)[SYSTEM: MCP servers have been reloaded. zD. The tool list for this conversation has been updated accordingly.]r   zMCP reload failed: %su   ❌ MCP reload failed: )rY  r  tools.mcp_toolr5  r6  r7  r8  r  r   r  r  r   r   r  r   rV  rg  r  r  r  r   r  r  )rv  r   r  r5  r6  r7  r8  r  old_servers
new_confignew_server_names	new_toolsconnected_serversaddedremovedreconnectedr  change_partstool_summarychange_detail
reload_msgr  rx  s   &&                     r   r  (GatewayRunner._handle_reload_mcp_commandK  s    %%'A	1rr !(--/2  *+J":??#45 &&t-ABBB #2249KLLI $'$8!  &3E!5G+9K67E3DIIf[>Q4R3STU{499VE]+C*DEF}TYYvg-G,HIJ$89ws9~&66NsSdOeNffpqr
 L##odiiu6N5O$PQ##&7		&/8R7S$TU##&;DIIf[FY<Z;[$\]LUc)n--GH[sL>JDIIl3d:PRMF}oVbUc  dh  iJ $ 2 2 H H V""77!,,j 99U##s  C M P  
  	1NN2A6,QC00	1s   NM L=M L$	M "L'#M 1L*AM +3M 3M AM 3M 3M 3M 5M &M 4AL> ?M NL!	
M 'M *L;	5	M >M	M MM M?M:4M?5N:M??Nc                6   < V ^8  d   QhRS[ RS[S[,          /# rW  rX  )r   r2  s   "r   r   r3    s#     7q 7q< 7qHSM 7qr   c                *  "   VP                   pV P                  V4      p^ RIHpHpHp V! V4      '       g0   W0P                  9   d   V P                  P                  V4       R# R# VP                  4       P                  4       P                  4       P                  4       pRV9   pV U	u. uF  qR8w  g   K  V	NK  	  p
p	\        ;QJ d    R V
 4       F  '       g   K   RM	  RM! R V
 4       4      '       d   RpR	pMC\        ;QJ d    R
 V
 4       F  '       g   K   RM	  RM! R
 V
 4       4      '       d   RpRpMRpRpV! W;VR7      pV'       g   R# V^8  d   RV R2MRp\        P                  RW4       RV^8  d   RMR RV V R2# u up	i 5i)u  Handle /approve command — unblock waiting agent thread(s).

The agent thread(s) are blocked inside tools/approval.py waiting for
the user to respond.  This handler signals the event so the agent
resumes and the terminal_tool executes the command inline — the same
flow as the CLI's synchronous input() approval.

Supports multiple concurrent approvals (parallel subagents,
execute_code).  ``/approve`` resolves the oldest pending command;
``/approve all`` resolves every pending command at once.

Usage:
    /approve              — approve oldest pending command once
    /approve all          — approve ALL pending commands at once
    /approve session      — approve oldest + remember for session
    /approve all session  — approve all + remember for session
    /approve always       — approve oldest + remember permanently
    /approve all always   — approve all + remember permanently
)resolve_gateway_approvalhas_blocking_approvalpending_approval_countuQ   ⚠️ Approval expired (agent is no longer waiting). Ask the agent to try again.zNo pending command to approve.r  c              3   *   "   T F	  qR9   x  K  	  R# 5i)alwaysN)rM  	permanentpermanentlyr   r   r  s   & r   r   8GatewayRunner._handle_approve_command.<locals>.<genexpr>  s     NIq::Ir   TFrM  z (pattern approved permanently)c              3   *   "   T F	  qR9   x  K  	  R# 5i)r   N)r   sesr   rP  s   & r   r   rQ    s     <)Q(()r   r   z$ (pattern approved for this session)oncerk   resolve_allrh  
 commands)z4User approved %d dangerous command(s) via /approve%su   ✅ Commandr  z	 approvedz. The agent is resuming...)r  r  tools.approvalrI  rJ  rK  ri  r   r  r   r   r   r   r  r  )rv  r   r  r   rI  rJ  rK  r   rV  r  	remainingchoice	scope_msgcount	count_msgs   &&             r   r  %GatewayRunner._handle_approve_command  sj    ( 226:	
 	

 %[11555''++K8j3 %%'--/557==?tm $31U
QQ	33NIN333NINNNF9IS<)<SSS<)<<<F>IFI(+V3.3aibz*R	JE]EAIS26i	{9+Uopp% 4s7   B(F*F7F=FF9F	FF8AFc                &   < V ^8  d   QhRS[ RS[/# rW  r  )r   r2  s   "r   r   r3    s     K K K Kr   c                  "   VP                   pV P                  V4      p^ RIHpHp V! V4      '       g0   W0P
                  9   d   V P
                  P                  V4       R# R# VP                  4       P                  4       P                  4       pRV9   pV! VRVR7      pV'       g   R# V^8  d   RV R2MR	p	\        P                  R
V4       RV^8  d   RMR	 RV	 R2# 5i)u   Handle /deny command — reject pending dangerous command(s).

Signals blocked agent thread(s) with a 'deny' result so they receive
a definitive BLOCKED message, same as the CLI deny flow.

``/deny`` denies the oldest; ``/deny all`` denies everything.
)rI  rJ  u(   ❌ Command denied (approval was stale).zNo pending command to deny.r  r^  rU  rh  rW  rk   z-User denied %d dangerous command(s) via /denyu   ❌ Commandr  z deniedrb  )r  r  rX  rI  rJ  ri  r   r  r   r   r  r  )
rv  r   r  r   rI  rJ  r   rV  r\  r]  s
   &&        r   r  "GatewayRunner._handle_deny_command  s      226:	
 %[11555''++K8A0%%'--/557tm(f+V0.3aibz*R	CUKEAIS26gi[JJs   B&C")9C"c                &   < V ^8  d   QhRS[ RS[/# rW  r  )r   r2  s   "r   r   r3    s#     [J [J, [J3 [Jr   c                  "   ^ RI p^ RIp^ RIp^ RIHp ^ RIHpHp VP                  P                  pWP                  9  d   R# V! 4       '       d   RV! R4       2# \        \        4      P                  P                  P                  4       p	V	R,          p
V
P                  4       '       g   R# \        4       pV'       g    R	# \         R
,          p\         R,          p\         R,          pV P#                  VP                  4      pRVP                  P                  P$                  RVP                  P&                  RVP                  P(                  RVRVP*                  ! 4       P-                  4       /pVP/                  R4      pVP1                  VP2                  ! V4      4       VP5                  V4       VP7                  RR7       RP9                  R V 4       4      pRV R\:        P<                  ! \?        V4      4       R\:        P<                  ! \?        V4      4       2p VPA                  R4      pV'       d/   VPC                  VRRV.VPD                  VPD                  RR7       M-VPC                  RRV.VPD                  VPD                  RR7        V PI                  4        R#   \F         d4   pTP7                  RR7       TP7                  RR7       RT 2u Rp?# Rp?ii ; i5i) uK  Handle /update command — update Hermes Agent to the latest version.

Spawns ``hermes update`` in a detached session (via ``setsid``) so it
survives the gateway restart that ``hermes update`` may trigger. Marker
files are written so either the current gateway process or the next one
can notify the user when the update finishes.
Nr   )
is_managedformat_managed_messageu^   ✗ /update is only available from messaging platforms. Run `hermes update` from the terminal.u   ✗ zupdate Hermes Agentr   u+   ✗ Not a git repository — cannot update.u   ✗ Could not locate the `hermes` command. Hermes is running, but the update command could not find the executable on PATH or via the current Python interpreter. Try running `hermes update` manually in your terminal.rm  .update_output.txt.update_exit_coder  r  rA  r   rM  ra  T
missing_okr[  c              3   N   "   T F  p\         P                  ! V4      x  K  	  R # 5ir9  )shlexquoter   s   & r   r   7GatewayRunner._handle_update_command.<locals>.<genexpr>6  s     !K
%++d"3"3
r^  zPYTHONUNBUFFERED=1 z update --gateway > z* 2>&1; status=$?; printf '%s' "$status" > setsidbash-c)r  r  start_new_sessionu   ✗ Failed to start update: u8   ⚕ Starting Hermes update… I'll stream progress here.)%r   r%  r  r   r~  rd  re  r  r  _UPDATE_ALLOWED_PLATFORMSr   r   r   r   r   r.  r   r  r   r  rA  r  r  r  r  r  r   r(  r   rk  rl  r   r&  PopenDEVNULLr   r  )rv  r   r   r%  r  r   rd  re  r  project_rootgit_dir
hermes_cmdpending_pathr  exit_code_pathr   pending_tmp_pendinghermes_cmd_str
update_cmd
setsid_binrx  s   &&                    r   r  $GatewayRunner._handle_update_command  s     	%H <<((999s<<01FGHIIH~,,33;;='~~@(*
I $&<<"%99%(;;225<<@--33u||++u||++;113
 $//7

7 34\*. !K
!KK!.!1 2++c+./0 1449KKN@S4T3UW 	
	6h/J  z:%--%--&*	 !    T:.%--%--&*	 !  	002I  	640!!T!21!55	6sJ   AK/GK/(AJ. .K//,J. K/.K,9(K'!K,"K/'K,,K/c                   < V ^8  d   QhRR/# r   r   )r   r2  s   "r   r   r3  V  s     X XT Xr   c                   \        V RR4      pV'       d   VP                  4       '       g   R#  \        P                  ! V P	                  4       4      V n        R#   \         d    \        P                  R4        R# i ; i)z;Ensure a background task is watching for update completion._update_notification_taskNz;Skipping update notification watcher: no running event loop)	r   r  rY  r  _watch_update_progressr  r   r  r  )rv  existing_tasks   & r   r  1GatewayRunner._schedule_update_notification_watchV  sj    &A4H!3!3!5!5	X-4-@-@++-.D*  	XLLVW	Xs   )A  A>=A>c                0   < V ^8  d   QhRS[ RS[ RS[ RR/# )r   poll_intervalstream_intervalr3   r   N)r  )r   r2  s   "r   r   r3  c  s9     |? |?|? |? 	|?
 
|?r   c                >  aaaa a!a"a#"   ^ RI p^ RIo\        R,          p\        R,          p\        R,          p\        R,          p\        R,          p	\        P                  ! 4       o#S#P                  4       V,           p
RoRo!RpWe3 F  pVP                  4       '       g   K   VP                  ! VP                  4       4      pVP                  R4      pVP                  R4      o!VP                  R	4      pV'       d>   S!'       d6   \        V4      pV P                  P                  V4      oV'       g   V R
S! 2p M	  S'       d
   S!'       Eg   \        P                  R4       VP                  4       '       g   VP                  4       '       df   S#P                  4       V
8  dQ   VP                  4       '       d   V P                  4       G Rj  xL
  R# \        P                   ! V4      G Rj  xL
  K  VP                  4       '       g   VP                  4       '       d@   VP                  4       '       g*   VP#                  R4       V P                  4       G Rj  xL
  R# R V3R llo^ pS#P                  4       o"Ro R VVV V!V"V#3R llpS#P                  4       V
8  Ed.   VP                  4       '       EdM   VP                  4       '       d9    VP                  4       p\%        V4      V8  d   S VVR ,          o \%        V4      pV! 4       G Rj  xL
   VP                  4       P)                  4       ;'       g    Rp\+        V4      pV^ 8X  d   SP-                  S!R4      G Rj  xL
  M)SP-                  S!RP/                  V4      4      G Rj  xL
  \        P1                  RVV4       WVVW3 F  pVP3                  RR7       K  	  \        R,          P3                  RR7       V P4                  P7                  VR4       R# VP                  4       '       d9    VP                  4       p\%        V4      V8  d   S VVR ,          o \%        V4      pS P)                  4       '       d,   S#P                  4       S",
          V8  d   V! 4       G Rj  xL
  V	P                  4       '       Ed   V'       d    VP                  ! V	P                  4       4      pVP                  RR4      pVP                  RR4      pV'       d   V! 4       G Rj  xL
  Rp\9        \;        S4      RR4      e!    SP=                  S!VVVR7      G Rj  xL
  RpV'       g1   V'       d   R V R!2MRpSP-                  S!R"V V R#24      G Rj  xL
  RV P4                  V&   \        P1                  R$VVR%,          4       \        P                   ! V4      G Rj  xL
  EKC  VP                  4       '       g   \        P                  R'V4       VP#                  R4       V! 4       G Rj  xL
   SP-                  S!R(4      G Rj  xL
  WVVW3 F  pVP3                  RR7       K  	  \        R,          P3                  RR7       V P4                  P7                  VR4       R# R#   \         d     EK  i ; i EL EL ELP  \&         d     ELi ; i EL EL\ EL5  \         d"   p\        P                  RT4        Rp?ELCRp?ii ; i  \&         d     ELi ; i ELz EL EL  \         d"   p\        P?                  RT4        Rp?ELRp?ii ; i EL  TP@                  \&        3 d"   p\        P?                  R&T4        Rp?ELRp?ii ; i EL ELl ELT  \         d     EL`i ; i5i))a  Watch ``hermes update --gateway``, streaming output + forwarding prompts.

Polls ``.update_output.txt`` for new content and sends chunks to the
user periodically.  Detects ``.update_prompt.json`` (written by the
update process when it needs user input) and forwards the prompt to
the messenger.  The user's next message is intercepted by
``_handle_message`` and written to ``.update_response``.
Nrm  rn  rf  rg  z.update_prompt.jsonr  r  r   r   zOUpdate watcher: cannot resolve adapter/chat_id, falling back to completion-only124c                0    V ^8  d   QhR\         R\         /# )r   r   r   r   )r   s   "r   r   :GatewayRunner._watch_update_progress.<locals>.__annotate__  s     	? 	?c 	?c 	?r   c                 *   < SP                  R RV 4      # )z\x1b\[[0-9;]*[A-Za-z]rk   )r  )r   r  s   &r   _strip_ansi9GatewayRunner._watch_update_progress.<locals>._strip_ansi  s    773R>>r   rk   c                    V ^8  d   QhRR/# r   r   )r   s   "r   r   r    s     	E 	ET 	Er   c                   <"   SP                  4       '       g   RoR# S! S4      P                  4       p RoSP                  4       o
V '       g   R# Rp\        ^ \        V 4      V4       Uu. uF  q W"V,            NK  	  ppV F"  p SP	                  S	RV R24      G Rj  xL
  K$  	  R# u upi  L  \
         d"   p\        P                  RT4        Rp?KV  Rp?ii ; i5i)z!Send buffered output to the user.rk   N  z```

```zUpdate stream send failed: %s)r   r  r  r   r  r   r  r  )clean	max_chunkr   chunkschunkrx  r  r   bufferr  last_stream_timer  s         r   _flush_buffer;GatewayRunner._watch_update_progress.<locals>._flush_buffer  s      <<>>'--/EF#yy{I6;As5z96UV6UA)m,6UFVE!,,w%we0DEEE   W F  ELL!@!DDEsT   A
CC*B)=CB0B.B0#C.B00C;CCCCrx   u   ✅ Hermes update finished.u(   ❌ Hermes update failed (exit code {}).z&Update finished (exit=%s), notified %sz$Update final notification failed: %sTrh  r`  r+  r  Fsend_update_prompt)r  r+  r  r   z%Button-based update prompt failed: %sz (default: r  u"   ⚕ **Update needs your input:**

zG

Reply `/approve` (yes) or `/deny` (no), or type your answer directly.z!Forwarded update prompt to %s: %sr  z Failed to read update prompt: %sz$Update watcher timed out after %.0fsu-   ❌ Hermes update timed out after 30 minutes.)!r   r  r   rY  get_running_loopr  r   r   r   r   r|   rE  r   r  r  r  r  r  r   r  r   r  r  r   r  r(  rk  r   r   r  r  r  r  )$rv  r  r  r3   r   rx  claimed_pathr  ry  prompt_pathdeadliner   r   rz  platform_strr  
bytes_sentr  r  exit_code_raw	exit_coderx  rr  prompt_dataprompt_textr  sent_buttonsbtn_errdefault_hintr  r  r   r  r  r  r  s$   &&&&                         @@@@@@@r   r  $GatewayRunner._watch_update_progressc  s     	#&<<#&DD"%99%(;;"%::'')99;( !0D{{}}"jj)9:G#*;;z#:L%kk)4G")++m"<K##+L#9"&--"3"3H"=*-9N!G9*EK 1" ggNNlm&&((L,?,?,A,Atyy{U]G]!((**88:::mmM222##%%)<)<)>)>H]H]H_H_))%044666	? 	? 
99;	E 	E* iikH$$$&&%%''"-"7"7"9w<*4"gjk&::F),WJ $o%%	N$2$<$<$>$D$D$F$M$M#M #M 2I A~%ll74QRRR%ll74^4e4efo4pqqqKK H)U`a
 'k(7AHHH-7  22::d:K++//TB !!##)335G7|j0'*+"66%(\

 ||~~499;1A#Ao"U#o%% !!##!H"&**[-B-B-D"EK"-//(B"?K)ooi<G" ,o--',"4=2FMY	_&-&@&@,3+6,30;	 'A '" !" !" 04  ,GN[	+CTVL"),, '"F#.-~ >@!A#   DH33K@$GVabeVfg --... $$&&NNA7K%%e,/!!ll7,[\\\ #+$3D)3 ..66$6G''++K> 'I !  ;2 7R # % Sq  NNN#I1MMN$  
 & .
!" $- _ &-TV] ^ ^_ ,,g6 HLL!CQGGH / "\ sQ  B^$AZ?Z5Z<^^*^<^*^=^Z'^0Z*1^^#^9$^Z-A^<^7Z0 

^[^$[ ?*[ )[*)[ [[ /A.^7[: ^,&^\^.^7A] 
] \] -\ \\ ] ] #] ?] 1] 1^
^^(1^^^^ 4^5^ 9A^Z$^#Z$$^*^-^0Z?;^>Z??^[ [ [7[2,^2[77^:\	^\		^] \ ] \<6] <]] ]?]:4^:]??^^^ ^^^^c                    < V ^8  d   QhRS[ /# r   r|  )r   r2  s   "r   r   r3  !  s     W W Wr   c                  "   ^ RI p^ RIp\        R,          p\        R,          p\        R,          p\        R,          pVP                  4       '       g   VP                  4       '       g   R# RpTp VP                  4       '       d    VP	                  V4       MkVP                  4       '       gV    V'       dK   VP                  RR7       VP                  RR7       VP                  RR7       VP                  RR7       R# R# VP                  ! VP                  4       4      p	V	P                  R	4      p
V	P                  R
4      pVP                  4       '       g   \        P                  R4       RpTpVP	                  V4        V'       dK   VP                  RR7       VP                  RR7       VP                  RR7       VP                  RR7       R# R# VP                  4       P                  4       ;'       g    Rp\        V4      pRpVP                  4       '       d   VP                  4       p\        V
4      pV P                  P                  V4      pV'       d   V'       d   VP!                  RRV4      P                  4       pV'       d2   \#        V4      R8  d   RVRR ,           pV^ 8X  d   RV R2pMRV R2pMV^ 8X  d   RpMRpVP%                  VV4      G Rj  xL
  \        P                  RV
VV4       T'       dI   TP                  RR7       TP                  RR7       TP                  RR7       TP                  RR7       R#   \
         dp    TP                  4       '       gV    T'       dK   TP                  RR7       TP                  RR7       TP                  RR7       TP                  RR7       R# R#  ELi ; i L  \&         d!   p\        P)                  RT4        Rp?LRp?ii ; i  T'       dJ   TP                  RR7       TP                  RR7       TP                  RR7       TP                  RR7       i i ; i5i)aT  If an update finished, notify the user.

Returns False when the update is still running so a caller can retry
later. Returns True after a definitive send/skip decision.

This is the legacy notification path used when the streaming watcher
cannot resolve the adapter (e.g. after a gateway restart where the
platform hasn't reconnected yet).
Nrm  rn  rf  rg  FTrh  r  r  z2Update notification deferred: update still runningrx   rk   z\x1b\[[0-9;]*mr  rb  u!   ✅ Hermes update finished.

```
r  u   ❌ Hermes update failed.

```
u(   ✅ Hermes update finished successfully.u]   ❌ Hermes update failed. Check the gateway logs or run `hermes update` manually for details.z0Sent post-update notification to %s:%s (exit=%s)z#Post-update notification failed: %siT)r   r  r   r   r   r  r(  r   r   r   r  r  r   r  r|   rE  r  r   r  r   r  )rv  r   r  rx  r  r  ry  cleanupactive_pending_pathrz  r  r  r  r  r  r  r   r  rx  s   &                  r   r  'GatewayRunner._send_update_notification!  s     	#&<<#&DD"%99%(;;""$$\-@-@-B-B*>	7""$$$ ((6 "((**d #**d*;##t#4""d"3%%%6	 a jj!7!7!9:G";;z2Lkk),G!((**PQ&2#$$\2N #**d*;##t#4""d"3%%%6	 K +446<<>EE#MM*I F!!##$..0  -Hmm''1G7!2B?EEG6{T)!&!7 A~ DVHER B6(%P A~H}ll7C000F 	 #**d*;##t#4""d"3%%%6y ) $'..00#h #**d*;##t#4""d"3%%%6	 k 1$X 1  	ENN@!DD	E #**d*;##t#4""d"3%%%6	 s   A(Q+Q2O 	M O 2AQAO *O 	AQ$O A+O .(O AO )O*O AQ O9O :QAQO OO P"O=8P =PP AQQc                $   < V ^8  d   QhRS[ RR/# )r   rc  r   N)r   )r   r2  s   "r   r   r3  z  s     S S S4 Sr   c                   VP                   P                  P                  \        P                  R&   VP                   P
                  \        P                  R&   VP                   P                  '       d(   VP                   P                  \        P                  R&   VP                   P                  '       d3   \        VP                   P                  4      \        P                  R&   R# R# )z2Set environment variables for the current session.HERMES_SESSION_PLATFORMHERMES_SESSION_CHAT_IDHERMES_SESSION_CHAT_NAMEHERMES_SESSION_THREAD_IDN)	r  r  r   r   r   r  r  r  r   )rv  rc  s   &&r   rj  GatewayRunner._set_session_envz  s    070G0G0M0M

,-/6~~/E/E

+,>>###5<^^5M5MBJJ12>>###589Q9Q5RBJJ12 $r   c                   < V ^8  d   QhRR/# r   r   )r   r2  s   "r   r   r3    s     $ $D $r   c                h    R F+  pV\         P                  9   g   K  \         P                  V K-  	  R# )z$Clear session environment variables.N)r  r  r  r  )r   r   )rv  vars   & r   r   GatewayRunner._clear_session_env  s'     ACbjj JJsO Ar   c                <   < V ^8  d   QhRS[ RS[S[ ,          RS[ /# )r   	user_textr  r   r   r	   )r   r2  s   "r   r   r3    s2     B BB #YB 
	Br   c                B  "   ^ RI Hp ^ RIpRp. pV F  p \        P	                  RV4       V! VVR7      G Rj  xL
 pVP                  V4      p	V	P                  R4      '       d-   V	P                  RR4      p
VP                  R	V
 R
V R24       K  VP                  RV R24       K  	  V'       d#   RP                  V4      pV'       d   V RV 2# V# V#  L  \         d8   p\        P                  RT4       TP                  RT R24        Rp?EK  Rp?ii ; i5i)aP  
Auto-analyze user-attached images with the vision tool and prepend
the descriptions to the message text.

Each image is analyzed with a general-purpose prompt.  The resulting
description *and* the local cache path are injected so the model can:
  1. Immediately understand what the user sent (no extra tool call).
  2. Re-examine the image with vision_analyze if it needs more detail.

Args:
    user_text:   The user's original caption / message text.
    image_paths: List of local file paths to cached images.

Returns:
    The enriched message string with vision descriptions prepended.
)vision_analyze_toolNzDescribe everything visible in this image in thorough detail. Include any text, code, data, objects, people, layout, colors, and any other notable visual information.zAuto-analyzing user image: %s)r  user_promptr  analysisrk   z0[The user sent an image~ Here's what I can see:
zA]
[If you need a closer look, use vision_analyze with image_url: z ~]z[The user sent an image but I couldn't quite see it this time (>_<) You can try looking at it yourself with vision_analyze using image_url: r   zVision auto-analysis error: %sz[The user sent an image but something went wrong when I tried to look at it~ You can try examining it yourself with vision_analyze using image_url: r  )tools.vision_toolsr  r   r  r  r   r   r   r   r  r   )rv  r  r  r  r!  analysis_promptenriched_partsr   r4  r3  rF  rx  prefixs   &&&          r   rz  )GatewayRunner._enrich_message_with_vision  sG    * 	;8 	 D<dC$7" /%  [1::i(("(**Z"<K"))KK= Y&&*V30 #))@@DvQH!  < [[0F i[11MA$  =qA%%<<@6D s\   D#CC+C'*CDC(D4DDCD%+DDDDc                <   < V ^8  d   QhRS[ RS[S[ ,          RS[ /# )r   r  r  r   r  )r   r2  s   "r   r   r3    s2     Q QQ #YQ 
	Qr   c                  "   \        V P                  RR4      '       g<   RpV P                  4       '       d
   VR,          pVR,          pV'       d   V RV 2# V# ^ RIHpHp ^ RIpV! 4       p. pV F  p	 \        P                  R	V	4       VP                  ! WIVR
7      G Rj  xL
 p
V
R,          '       d!   V
R,          pVP                  RV R24       Ke  V
P                  RR4      pRV9   g   VP                  R4      '       d>   RpV P                  4       '       d
   VR,          pVR,          pVP                  V4       K  VP                  RV R24       K  	  V'       d#   RP                  V4      pV'       d   V RV 2# V# V#  L  \         d4   p\        P                  RT4       TP                  R4        Rp?EKR  Rp?ii ; i5i)aK  
Auto-transcribe user voice/audio messages using the configured STT provider
and prepend the transcript to the message text.

Args:
    user_text:   The user's original caption / message text.
    audio_paths: List of local file paths to cached audio files.

Returns:
    The enriched message string with transcriptions prepended.
stt_enabledTzI[The user sent voice message(s), but transcription is disabled in config.z{ You have a skill called hermes-agent-setup that can help users configure Hermes features including voice, tools, and more.r   r  )transcribe_audioget_stt_model_from_configNzTranscribing user voice: %s)r[   r  r  z8[The user sent a voice message~ Here's what they said: "z"]r  r  rW  z8Neither VOICE_TOOLS_OPENAI_KEY nor OPENAI_API_KEY is setu   [The user sent a voice message but I can't listen to it right now — no STT provider is configured. A direct message has already been sent to the user with setup instructions.zC[The user sent a voice message but I had trouble transcribing it~ (z)]zTranscription error: %sze[The user sent a voice message but something went wrong when I tried to listen to it~ Let them know!])r   r  r  tools.transcription_toolsr  r  rY  r  r  r/  r   r   r   r   r  r   )rv  r  r  disabled_noter  r  rY  	stt_modelr  r   r3  r  r  _no_stt_noterx  r  s   &&&             r   r}  0GatewayRunner._enrich_message_with_transcription  s      t{{M488gM$$&&X S M'YK88  Y-/	D':DA&001AyYY)$$!'!5J"))44><rC
 #JJw@E)U2 ++,fgg7 %  0022(!DL
 %+&--l;&--116r;?  T [[0F i[11MY Z@  6:%%D s   5GG#G6-F#F	$F7FG/FF#FGFG%G>G	FG	'G=GG		Gc                $   < V ^8  d   QhRS[ RR/# )r   r  r   Nr   )r   r2  s   "r   r   r3     s     ]> ]>$ ]>4 ]>r   c                  "   ^ RI Hp VR,          pVR,          pVP                  RR4      pVP                  RR4      pVP                  RR4      pVP                  RR4      pV P                  4       p	\        P                  R	W4V	4       V	R
8X  db    \        P                  ! V4      G Rj  xL
  VP                  V4      p
V
e   V
P                  '       g   KH   \        P                  RT4       R# ^ p \        P                  ! V4      G Rj  xL
  VP                  V4      p
V
f   EM\        V
P                  4      pW8  pTpV
P                  '       d   V	R9   ;'       g    V	R8H  ;'       d    V
P                  R9  pV'       d   V
P                  '       d   V
P                  RR MRpRV RV
P                   RV R2pRpV P                  P                  4        F  w  ppVP                  V8X  g   K  Tp M	  V'       d4   V'       d,    V'       d   RV/MRpVP                  VVVR7      G Rj  xL
  MV'       g   EKO  V	R8X  g   EKY  V
P                  '       d   V
P                  RR MRpRV RV R2pRpV P                  P                  4        F  w  ppVP                  V8X  g   K  Tp M	  V'       g   EK  V'       g   EK   V'       d   RV/MRpVP                  VVVR7      G Rj  xL
  EK  \        P                  RV4       R#  ELe EL L  \          d"   p\        P#                  RT4        Rp?ELRp?ii ; i LV  \          d#   p\        P#                  RT4        Rp?EK}  Rp?ii ; i5i)u  
Periodically check a background process and push updates to the user.

Runs as an asyncio task. Stays silent when nothing changed.
Auto-removes when the process exits or is killed.

Notification mode (from ``display.background_process_notifications``):
  - ``all``    — running-output updates + final message
  - ``result`` — final completion message only
  - ``error``  — final message only when exit code != 0
  - ``off``    — no messages at all
r6  r  check_intervalr   rk   r  r  r  z2Process watcher started: %s (every %ss, notify=%s)r  Nz"Process watcher ended (silent): %sr  r  z[Background process z finished with exit code z~ Here's the final output:
r   r  zWatcher delivery error: %sz is still running~ New output:
zProcess watcher ended: %s)r  r3  )r5  Nii)rT  r7  r   rA  r  r  rY  r  exitedr   output_bufferr  rE  r  r   r  r   r  )rv  r  r7  r  r  r   rF  r  r  notify_moder   last_output_lencurrent_output_lenhas_new_outputr  
new_outputr/  r   rr  r  	send_metarx  s   &&                    r   r  "GatewayRunner._run_process_watcher   sK     	<\*
+,kk-4J3++i,KKR0	>>@I K	9 % mmH---*..z:?gnnnLL=zJ--)))&**:6G!$W%:%:!;/AN0O~~~  #44 W W#w.UU73D3DI3U  !BIBWBWBW!6!6uv!>]_J.zl:ST[TeTeSf g55?LC ! #G $ 3 3 5177m3&'G! !6 7JDMi(@SWI"),,wy,"YYY K5$8=D=R=R=RW22459XZ
*:, 7$$.<q2   MM//1DAqww-/"# 2 7wwF@I[)$<t	%ll7L9lUUU 	0*= . *< Z( J"LL)EqIIJ& V$ F%A1EEFs   B)M9+L,(M95M9LAM9#M90M9M9AM96M9M9L L 2L3L 7M9M9M9A
M9.M9?M9M	 M	 0M1M	 5M9M9L M#L?9M9?MM9M	 	M6M1*M91M66M9c          
      8   < V ^8  d   QhRS[ RS[RS[RS[ RS[ /# )r   r[   r   r  ephemeral_promptr   )r   r   r   )r   r2  s   "r   r   r3    s;     %> %>%>%> %> 	%>
 
%>r   c           
     
   ^ RI p^ RIp\        VP                  RR4      ;'       g    R4      pV'       d.   VP	                  VP                  4       4      P                  4       MRpTP                  T TVP                  RR4      VP                  RR4      VP                  RR4      V'       d   \        V4      M. T;'       g    R.R\        R7      pVP	                  VP                  4       4      P                  4       R	,          # )
u  Compute a stable string key from agent config values.

When this signature changes between messages, the cached AIAgent is
discarded and rebuilt.  When it stays the same, the cached agent is
reused — preserving the frozen system prompt and tool schemas for
prompt cache hits.
Nr_   rk   r]   rY   r   T)	sort_keysr  :N   N)	hashlibr   r   r   sha256encode	hexdigestr  r  )	r[   r   r  r  r  _j_api_key_api_key_fingerprintblobs	   &&&&     r   _agent_config_signature%GatewayRunner._agent_config_signature  s     	# w{{9b177R8PXw~~hoo.?@JJL^`xx$J+J+J+,<'(" !&&B
   
 ~~dkkm,668==r   c                $   < V ^8  d   QhRS[ RR/# r   r   )r   r2  s   "r   r   r3    s     9 9s 9t 9r   c                    \        V RR4      pV'       d2   V;_uu_ 4        V P                  P                  VR4       RRR4       R# R#   + '       g   i     R# ; i)zBRemove a cached agent for a session (called on /new, /model, etc).re  N)r   rc  r   )rv  r   r  s   && r   r  !GatewayRunner._evict_cached_agent  sC    148!!%%k48  s   A		A	c                   < V ^8  d   QhRS[ RS[ RS[S[S[ S[3,          ,          RS[RS[ RS[ RS[RS[S[ ,          R	S[S[ S[3,          /	# )
r   r9  r>  r  r  r  r   _interrupt_depthr?  r   )r   r	   r   r   r   r  r   )r   r2  s   "r   r   r3    s     [ [[ [ d38n%	[
 [ [ [ [ #3-[ 
c3h[r   c	                  a aaaaaaa:a;a<a=a>a?a@aAaBaCaDaEaFaGaHaIaJaKaLaMaNaOaPaQaRaSaT"   ^ RI Ho: ^ RIoN\        4       oT\	        SP
                  4      p	^ RIHp
 \        V
! STV	4      4      oH ^ RI	H
p STP                  R/ 4      P                  R^ 4      pT! V'       d   \        V4      M^ 4       STP                  R/ 4      P                  R4      pVRJ d   R	pT;'       g!    \        P                  ! R
4      ;'       g    RoL^ RIHo; SLR	8g  ;'       d    SP
                  S;P$                  8g  oRSR'       d   SNP'                  4       MRoMR.oJR.oI^ .oORPR VIVJVLVMVO3R llloKSP
                  S;P(                  8X  d   SP*                  ;'       g    ToAMSP*                  oASA'       d   RSA/MRo@V@VMVNV V3R lpR.oGR.oPR.oSR.oQ\,        P.                  ! 4       o>S P0                  o=R V=V>VV3R lloFS P2                  P                  SP
                  4      oBSP4                  oDSA'       d   RSA/MRoER V>VBVDVE3R lloCV:V;V=V>VAVBVCVDVEVFVGVVHVVVKVPV VVVVQVRVSVT3R lpRpSR'       d   \,        P6                  ! V! 4       4      pRpVQ3R lp\,        P6                  ! V! 4       4      pVGV V3R lp\,        P6                  ! V! 4       4      pVGV VV3R lp\,        P6                  ! V! 4       4      pRo<\8        P8                  ! 4       o?V<V?VEVGV V3R lp\,        P6                  ! V! 4       4      p \;        \        P                  ! RR4      4      pV^ 8  d   TMRp\,        P.                  ! 4       p\,        P<                  ! VP?                  RV4      4      pRpRpVf   VG Rj  xL
 pMRp \,        P@                  ! V0VR7      G Rj  xL
 w  p p!V '       d   VPC                  4       pMTSG^ ,          p"R p#V"'       d6   \E        V"R!4      '       d$    V"PG                  4       p$V$P                  R"R 4      p#V#V8  g   K  Rp V'       Ed   SG^ ,          p%/ p&V%'       d$   \E        V%R!4      '       d    V%PG                  4       p&V&P                  R#R$4      p'V&P                  R"^ 4      p(V&P                  R%4      p)V&P                  R&^ 4      p*V&P                  R'^ 4      p+\H        PK                  R(T(TST'T*T+T);'       g    R)4       V%'       d$   \E        V%R*4      '       d   V%PM                  R+4       \        V^<,          4      ;'       g    ^p,R,V, R-2.p-V)'       d!   V-PO                  R.V) R/V(R0 R1V* R2V+ R32	4       MV-PO                  R4V' R5V(R0 R6V* R2V+ R72	4       V-PO                  R84       R9R:PQ                  V-4      R;SP^ ,          '       d   SP^ ,          P                  R;. 4      M. R<T*R=SS^ ,          ;'       g    . R>^ R?R/pSG^ ,          p.V.eq   \E        V.R@4      '       d_   \S        4       p/V.PT                  V/8w  d6   V.PT                  S n+        \Y        V.RAR4      S n-        S P]                  S4       MRS n+        RS n-        SP^ ,          p0S P2                  P                  SP
                  4      p1Rp2V0'       d   V1'       d   S'       d   V0P                  RB4      '       d>   \_        V1S4      p2V2'       g)   V0P                  RC4      '       d   V0P                  RC4      p2M1\_        V1S4      p2V2'       d   \H        Pa                  RDV2RE,          4       V2'       Ed   \H        Pa                  RFV2RE,          4       V1'       dM   \E        V1RG4      '       d;   S'       d3   SV1Pb                  9   d"   V1Pb                  S,          Pe                  4        VS Pf                  8  Ed^   \H        Pi                  RHVS4       S P2                  P                  SP
                  4      p1V1'       d%   \E        V1RI4      '       d   V1Pk                  SV24       SP^ ,          ;'       g    R9VR;S/ V'       d   VPm                  4        VPm                  4        VPm                  4        V'       d"    \,        Pn                  ! VRR7      G Rj  xL
  VPm                  4        S'       d   SS Pt                  9   d   S Pt                  S S'       d   S Pv                  Py                  SR4       VVVV3 F  p3V3'       g   K   V3G Rj  xL
  K  	  # V0P                  RB4      p4V4'       gy   SQ^ ,          p5T5;'       d    \Y        V5RJR4      p6V0P                  R9RK4      p7V7'       d?   V6'       g7    V1P{                  SP4                  V7\Y        \|        RLR4      RM7      G Rj  xL
  V0P                  R;S4      p9S P                  V2SV9SSSV^,           RO7      G Rj  xL
 V'       d   VPm                  4        VPm                  4        VPm                  4        V'       d"    \,        Pn                  ! VRR7      G Rj  xL
  VPm                  4        S'       d   SS Pt                  9   d   S Pt                  S S'       d   S Pv                  Py                  SR4       VVVV3 F  p3V3'       g   K   V3G Rj  xL
  K  	  #  V'       d   VPm                  4        VPm                  4        VPm                  4        V'       d"    \,        Pn                  ! VRR7      G Rj  xL
  VPm                  4        S'       d   SS Pt                  9   d   S Pt                  S S'       d   S Pv                  Py                  SR4       VVVV3 F  p3V3'       g   K   V3G Rj  xL
  K  	  SQ^ ,          p5T5'       d.   T5P                  '       d   \        T\        4      '       d   RTRJ&   T#   \         d     ELCi ; i EL^ EL<  \         d     ELi ; i  \         d     ELi ; i EL  \,        Pp                  \,        Pr                  3 d>    TPm                  4         TG Rj  xL 
   EL  \,        Pr                   d      ELi ; ii ; i ELs  \,        Pr                   d     EK  i ; i EL  \         d"   p8\H        Pi                  RNT84        Rp8?8EL"Rp8?8ii ; i EL EL  \,        Pp                  \,        Pr                  3 d>    TPm                  4         TG Rj  xL 
   EL  \,        Pr                   d      ELi ; ii ; i EL  \,        Pr                   d     EK  i ; i ELB  \,        Pp                  \,        Pr                  3 d>    TPm                  4         TG Rj  xL 
   EL  \,        Pr                   d      ELi ; ii ; i EL2  \,        Pr                   d     EKa  i ; i  T'       d   TPm                  4        TPm                  4        TPm                  4        T'       d    \,        Pn                  ! TRR7      G Rj  xL 
  Mc  \,        Pp                  \,        Pr                  3 d<    TPm                  4         TG Rj  xL 
   M   \,        Pr                   d      Mi ; ii ; iTPm                  4        S'       d   SS Pt                  9   d   S Pt                  S S'       d   S Pv                  Py                  SR4       TTTT3 F5  p3T3'       g   K   T3G Rj  xL 
  K    \,        Pr                   d     K3  i ; i	  i ; i5i)Qaq  
Run the agent with the given message and context.

Returns the full result dict from run_conversation, including:
  - "final_response": str (the text to send back)
  - "messages": list (full conversation including tool calls)
  - "api_calls": int
  - "completed": bool

This is run in a thread pool to not block the event loop.
Supports interruption via new messages.
r  Nrz  )set_tool_preview_max_lenr7  tool_preview_lengthr  Fr  HERMES_TOOL_PROGRESS_MODEr  rK  c                H    V ^8  d   QhR\         R\         R\         R\        /# )r   
event_typer  r  r   r  )r   s   "r   r   .GatewayRunner._run_agent.<locals>.__annotate__  s)     8	$ 8	$# 8	$# 8	$s 8	$ae 8	$r   c                (  < S'       g   R# V R9  d   R# SR8X  d   VS^ ,          8X  d   R# TS^ &   ^ RI Hp V! VRR7      pSR8X  d   V'       d}   ^ RI Hp V! 4       p^ RIp	V	P	                  VR\
        R	7      p
V^ 8  d   TM^p\        V
4      V8  d   V
RV^,
           R
,           p
V RV R\        VP                  4       4       RV
 2pMV'       d   V RV RV R2pMV RV R
2pSP                  V4       R# V'       d-   \        V4      ^(8  d   VR,          R
,           pV RV RV R2pMV RV R
2pVS^ ,          8X  d3   S^ ;;,          ^,          uu&   SP                  RVS^ ,          34       R# VS^ &   ^ S^ &   SP                  V4       R# )z3Callback invoked by agent on tool lifecycle events.Nrp  )get_tool_emojiu   ⚙️)r  ry  )get_tool_preview_max_lenF)ensure_asciir  r  r[  (z)
z: "r  :N%   N	__dedup__)ztool.started)
agent.displayr  r  r   r  r   r   r   r  put)r  r  r  r   kwargsr  emojir  _plr!  args_str_capr  last_progress_msg	last_toolprogress_modeprogress_queuerepeat_counts   &&&&,        r   progress_callback3GatewayRunner._run_agent.<locals>.progress_callback  s   ! !22 %)y|*C$IaL 5"9h?E 	)F24C(${{4eS{QH"%'3sD8}t+#+ITAX#6#>"G1YKqdiik1B0C3xjQC"G1YKtG9B?C"G1YKs3C""3' w<"$%clU2Gq4y;q3/
 '**Q1$ ""Kl1o#FG#&a LOs#r   r  c                  "	  <"   S'       g   R # SP                   P                  SP                  4      p V '       g   R # . pR pRpRpRp  SP                  4       p\	        V\
        4      '       dR   \        V4      ^8X  dB   V^ ,          R8X  d4   Vw  rxp	V'       d   V RV	^,            R2VR&   V'       d
   VR,          MTp
MTp
VP                  V
4       \        P                  ! 4       pW[V,
          ,
          pV^ 8  d!   \        P                  ! V4      G R j  xL
  K  V'       d   Ve   RP                  V4      pV P                  SP                  VVR7      G R j  xL
 pVP                  '       g|   \!        VR	R
4      ;'       g    R
P#                  4       pRV9   g   RV9   d!   \$        P'                  RV P(                  4       RpV P+                  SP                  V
SR7      G R j  xL
  MV'       d9   RP                  V4      pV P+                  SP                  VSR7      G R j  xL
 pM&V P+                  SP                  V
SR7      G R j  xL
 pVP                  '       d   VP,                  '       d   VP,                  p\        P                  ! 4       p\        P                  ! R4      G R j  xL
  V P/                  SP                  SR7      G R j  xL
  EK   EL EL L L L L8 L  SP0                   d%    \        P                  ! R4      G R j  xL 
   EK  \        P2                   Ed
    SP5                  4       '       g    SP                  4       p\	        T\
        4      '       dB   \        T4      ^8X  d2   T^ ,          R8X  d$   Tw  rxp	T'       d   T RT	^,            R2TR&   K|  K~  TP                  T4       K    \6         d     Mi ; iT'       d\   T'       dT   T'       dL   RP                  T4      p T P                  SP                  TTR7      G R j  xL 
  M  \6         d     Mi ; i R # \6         dB   p\$        P9                  RT4       \        P                  ! ^4      G R j  xL 
   R p?EK@  R p?ii ; i5i)NT        g      ?r  u    (×r  r   )r  rq  r  r  rk   floodzretry afterz1[%s] Progress edits disabled due to flood controlFr  g333333?r  zProgress message error: %sr  )rE  r   r  
get_nowaitr  tupler   r   r  r  rY  r  r   edit_messager  r  r   r   r  r  r   r  rq  send_typingEmptyCancelledErroremptyr   r  )r   progress_linesprogress_msg_idcan_edit_last_edit_ts_PROGRESS_EDIT_INTERVALr?  r   base_msgr\  r  _now
_remaining	full_textr3  _errrx  _progress_metadatar	  r   rv  r  s                    r   send_progress_messages8GatewayRunner._run_agent.<locals>.send_progress_messages7  s    !mm''8GN"OHM&)#\+(335C "#u--#c(a-CFkDY-0*U)4<:T%!)A1NN2.4BnR0!&--c2  >>+D!8=<P!QJ!A~ &mmJ777 O$?$(IIn$=	'.';';$*NN'6$- (< ( "
  &~~~$+FGR$@$F$FB#M#M#OD&$-42G !'$W$+LL!" (-H"),,v~~s]o,"ppp#(,		.(AI+2<<Xal~<+%F ,3<<X[fx<+y%yF!>>>f.?.?.?.4.?.?O$(NN$4M "--,,,!--fnnGY-ZZZM 8"  q
 &@ &z -Z{{ -!--,,,-- ,2244	""0";";"=C)#u55#c(a-CPQFVaLa58 2U#1<D:T%RS)TU9VN2$6 $2 !/ 5 5c :( "!"  N$(IIn$=	!")"6"6(.+:(1 #7 #  
  ) ! !  +LL!=qA!--****+s  7RR	A*K0 4A#K0 K K0 RK0 &6K0 K#K0 3K0 A"K0 )K&*K0 72K0 )K(*&K0 K*K0 'K0 9:K0 3K,4$K0 K.K0 R K0 #K0 &K0 (K0 *K0 ,K0 .K0 0*RLR R$R8RA#O
3R7O
R
ORO
R#R+R3R!P-&P)'P-,R-P;8R:P;;R>RR
R/R:Q=;R RRRc                4    V ^8  d   QhR\         R\        RR/# )r   	iteration
prev_toolsr   N)r  r   )r   s   "r   r   r    s!     	> 	>3 	>D 	>T 	>r   c                   <  . pT;'       g    .  F_  p\        V\        4      '       d-   TP                  VP                  R 4      ;'       g    R4       KE  VP                  \	        V4      4       Ka  	  \
        P                  ! SP                  RRSP                  '       d   SP                  P                  MRRSP                  RSRV RVRV/4      S4       R
#   \         d"   p\        P                  R	T4        R
p?R
# R
p?ii ; i)r   rk   z
agent:stepr  rA  r  r%  
tool_namesrK  zagent:step hook error: %sN)r  r   r   r   r   rY  run_coroutine_threadsafer  r  r   rA  r   r  r  )	r%  r&  _names_tr  
_hooks_ref_loop_for_stepr  r  s	   &&   r   _step_callback_sync5GatewayRunner._run_agent.<locals>._step_callback_sync  s    > %'%+++B!"d++bffVn&:&:;c"g.	 ,
 00OOL"V___FOO$9$9RT!6>>$j#Y$f3  #
  >8"==>s)   
C >C AC #6C D&DDc                4    V ^8  d   QhR\         R\         RR/# )r   r  r9  r   Nr   )r   s   "r   r   r    s&     	O 	Oc 	OC 	OD 	Or   c                    < S'       g   R #  \         P                  ! SP                  SVSR7      S4       R #   \         d"   p\        P                  RY4        R p?R # R p?ii ; i)Nr  zstatus_callback error (%s): %srY  r)  r  r   r  r  )r  r9  r  r-  _status_adapter_status_chat_id_status_thread_metadatas   && r   _status_callback_sync7GatewayRunner._run_agent.<locals>._status_callback_sync  sd    "
O00#(('!8 ) 
 #  O=zNNO   )8 A$AA$c                    <aG S[;'       g    R \         P                  R&   \        \         P                  ! RR4      4      p S\P                  SIP
                  8X  d   RMS\P                  P                  pSS;'       g    R pSYP                  '       d)   VR,           SYP                  ,           P                  4       p \        \        RRR7       \        S`4      p \        4       pSYP                  pSYP!                  4       pTSYn        RpRp	\%        \%        SYRR4      RR4      p
T
f   ^ RIHp T! 4       p
T
P*                  '       d   T
P,                  R8w  d    ^ RIHpHp SYP4                  P7                  S\P                  4      pT'       d]   T! T
P8                  T
P:                  T
P<                  R7      pT! TS\P>                  TSL'       d   RSL/MRR7      pTP@                  p	TS]^ &   SYPG                  SVY44      pSYPI                  TR,          TR,          STT4      pRp\%        SYRR4      p\%        SYRR4      pT'       d^   TeZ   T;_uu_ 4        TP7                  S[4      pT'       d.   T^,          T8X  d    T^ ,          p\B        PE                  RS[4       RRR4       TEf   SH! R]RTR,          /TR,          B/ RT bRRbR R!bR"STbR#T;'       g    RbR$SYPJ                  ;'       g    RbR%TbR&TP7                  R'4      bR(TP7                  R)4      bR*TP7                  R+4      bR,TP7                  R-4      bR.TP7                  R/R!4      bR0TP7                  R14      bR2SZbR3TbR4SYPL                  bR5SYPN                  bB pT'       d   Te   T;_uu_ 4        TT3TS[&   RRR4       \B        PE                  R6S[T4       S^'       d   SWMRTn(        SJPR                  '       d   SQMRTn*        T	Tn+        SNTn,        TTn-        R7 TKTMTOTP3R8 llpTTn.        TSR^ &   \_        TR4      '       d   TP`                  MRS_^ &   . pSU EF,  pTP7                  R94      pT'       g   K  TR^9   d   K(  TR:8X  d   K1  R;T9   pR<T9   pTR=8H  pT'       g   T'       g	   T'       dB   TPc                  4        UUu/ uF  w  ppTR>8w  g   K  TTbK  	  p ppTPe                  T 4       K  TP7                  R?4      p!T!'       g   K  TP7                  R@4      '       d   TP7                  RARB4      p"RCT" RDT! 2p!R9TR?T!/p#TRE8X  d*   R_ F#  p$TP7                  T$4      p%T%'       g   K  T%T#T$&   K%  	  TPe                  T#4       EK/  	  \g        4       p&T F  p'T'P7                  R94      R`9   g   K  T'P7                  R?R 4      p(RFT(9   g   K6  \h        Pj                  ! RGT(4       FL  p)T)Pm                  ^4      P                  4       Po                  RH4      p*T*'       g   K;  T&Pq                  T*4       KN  	  K  	  ^ RII9H:p+H;p,H<p-H=p. RJ TGTKTMTOTP3RK llp/\%        SYRL/ 4      p0S['       d   T0P}                  S[R4      MRp1T1'       d   T1R,           SV,           oVS[;'       g    R oGT-! SG4      p2T+! SGT/4        TP                  SVTSZRM7      p3T.! SG4       T,! T24       T3SX^ &   Te   TP                  4        T3P7                  R
4      p4^ p5^ p6^ p7SR^ ,          p8T8'       dD   \_        T8RN4      '       d2   \%        T8P                  RO^ 4      p5\%        T8RP^ 4      p6\%        T8RQ^ 4      p7T8'       d   \%        T8RR4      MRp9T4'       gt   T3P7                  RR4      '       d   RST3RR,           2MRTp:R
T:RT3P7                  R. 4      RT3P7                  R^ 4      RS_^ ,          ;'       g    . RU\        T4      ROT5RVT6RWT7RT9/	# RFT49  EdP   . p;R!p<T3P7                  R. 4       F  pTP7                  R94      R`9   g   K  TP7                  R?R 4      p!RFT!9   g   K6  \h        Pj                  ! RGT!4       FX  p=T=Pm                  ^4      P                  4       Po                  RH4      p>T>'       g   K;  T>T&9  g   KD  T;Pe                  RFT> 24       KZ  	  RXT!9   g   K  Rp<K  	  T;'       dz   \g        4       p?. p@T; F.  pATAT?9  g   K  T?Pq                  XA4       X@Pe                  TA4       K0  	  T<'       d   X@P                  ^ RX4       T4RY,           RYP                  X@4      ,           p4SR^ ,          pR!pBT'       d   S['       d   \_        TR24      '       d   TP                  SZ8w  d|   RpB\B        P                  RZSZTP                  4       SYP                  P                  P7                  S[4      p#T#'       d,   TP                  T#nE        SYP                  P                  4        T'       d   \%        TR2SZ4      MSZpCXB'       d   ^ M
\        T4      pDT4'       dZ   SYPL                  '       dH    ^ R[IJHKpE SX^ ,          '       d   SX^ ,          P7                  R. 4      M. pFXE! SYPL                  XCSVT4TF4       R
T4R\T3P7                  R\4      RSX^ ,          '       d   SX^ ,          P7                  R. 4      M. RSX^ ,          '       d   SX^ ,          P7                  R^ 4      M^ RS_^ ,          ;'       g    . RUXDROT5RVT6RWT7RT9R2XC/#   \         d    \        \        RR	R7        E
LA\         d     E
LNi ; i  \         d   pR
RT 2R. R^ R. /u Rp?# Rp?ii ; i  \         d"   p\B        PE                  RT4        Rp?E	LRp?ii ; i  + '       g   i     EL; i  + '       g   i     EL; iu uppi   T.! SG4       T,! T24       i ; i  \         d     EL^i ; i)ark   HERMES_SESSION_KEYro   r|  r
  r  Tr*   )r  r,   zlatin-1rA  u'   ⚠️ Provider authentication failed: rB  rC  rK  Nr  	streaming)StreamingConfigr  )GatewayStreamConsumerStreamConsumerConfig)edit_intervalbuffer_thresholdcursorr  )r   r  r  r  z$Could not set up stream consumer: %sr[   r   re  rc  z#Reusing cached agent for session %sr  r  r~  Fr  ephemeral_system_promptprefill_messagesr  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  rL  z)Created new agent for session %s (sig=%s)c                (    V ^8  d   QhR\         RR/# )r   r9  r   Nr   )r   s   "r   r   @GatewayRunner._run_agent.<locals>.run_sync.<locals>.__annotate__c  s     M M M Mr   c                    < S'       g   R #  \         P                  ! SP                  SV SR7      S4       R #   \         d"   p\        P                  RT4        R p?R # R p?ii ; i)Nr  z$background_review_callback error: %sr2  )r9  r  r-  r3  r4  r5  s   & r   _bg_review_sendCGatewayRunner._run_agent.<locals>.run_sync.<locals>._bg_review_sendc  sd    &
M44',,+#%< - 
 ' ! MLL!GLLMr8  r  rO  r  r  r6  rM  r  mirrormirror_sourcezanother sessionz[Delivered from r-  r  zMEDIA:zMEDIA:(\S+)z",})register_gateway_notifyreset_current_session_keyset_current_session_keyunregister_gateway_notifyc                (    V ^8  d   QhR\         RR/# )r   approval_datar   Nr   )r   s   "r   r   rE    s     3L 3LT 3Ld 3Lr   c           
       < V P                  RR4      pV P                  RR4      p\        \        S4      RR4      e?    \        P                  ! SP                  S	VSVS
R7      S4      P                  ^R7       R# \        V4      ^8  d   VR
,          R,           MTpRV RV R2p \        P                  ! SP                  S	VS
R7      S4      P                  ^R7       R#   \         d!   p\        P                  R	T4        Rp?LRp?ii ; i  \         d"   p\        P                  RT4        Rp?R# Rp?ii ; i)a	  Send the approval request to the user from the agent thread.

If the adapter supports interactive button-based approvals
(e.g. Discord's ``send_exec_approval``), use that for a richer
UX.  Otherwise fall back to a plain text message with
``/approve`` instructions.
r   rk   rF  zdangerous commandsend_exec_approvalN)r  r   r   rF  r  r  z6Button-based approval failed, falling back to text: %sr4  r  u4   ⚠️ **Dangerous command requires approval:**
```
z
```
Reason: z

Reply `/approve` to execute, `/approve session` to approve this pattern for the session, `/approve always` to approve permanently, or `/deny` to cancel.r  z#Failed to send approval request: %s)r   r   r  rY  r)  rR  r3  r   r  r  r   r  r  )rP  r  rP  r  cmd_previewr  _approval_session_keyr-  r3  r4  r5  s   &     r   _approval_notify_syncIGatewayRunner._run_agent.<locals>.run_sync.<locals>._approval_notify_sync  s^    $''	26$((8KL
 402FMY88+>>(7(+,A,0)@ ?  +	 !&&, 47s8c>c$i%/s'= )#f %gh 
L44',,+%< - 
 ' fRf(- % TVX . ! LLL!FKKLs/   ;C# (9D #D.D		DD=D88D=rs  )r  r  r  rQ  r  r  r  r  r  rN  input_tokensoutput_tokensz[[audio_as_voice]]r   u/   Session split detected: %s → %s (compression))maybe_auto_titlerH  r   )rL  )rx  reasoning_detailscodex_reasoning_items)r6  r  )Lr   r   r  r   r  r  r   rI  r   r%   	_env_pathUnicodeDecodeErrorr   r   r   rO  rJ  rK  r   rL  r<  r  	transportgateway.stream_consumerr=  r>  rE  r   r?  r@  rA  r  on_deltar  r  r   r  rG  rm  rQ  tool_progress_callbackr  step_callbackstream_delta_callbackstatus_callbackr  background_review_callbackr  rK  r  r   r   r  finditergroupru  r   rX  rK  rL  rM  rN  r   r  finishr  r   insertr   r  r  rV  r  r  agent.title_generatorrY  )ar  r  combined_ephemeralr[   r  r   r  r  _stream_consumer_stream_delta_cb_scfgr<  r=  r>  r  _consumer_cfg_sc_errr  _sigrm   r  r  cachedrG  agent_historyr  r  has_tool_callshas_tool_call_idis_tool_messager  r\  	clean_msgr  
mirror_srcr  _rkey_rval_history_media_paths_hm_hc_match_prK  rL  rM  rN  rU  _pending_notes_msn_approval_session_tokenr3  rA  _last_prompt_toks_input_toks_output_toks_agent_resolved_model	error_msg
media_tagshas_voice_directivematchr   seenunique_tagsr  _session_was_spliteffective_session_id_effective_history_offsetrY  all_msgsrT  r  r|   r,  r-  _progress_thread_idr3  r6  r4  r5  r.  agent_holderr>  r  r  r9  r  result_holderrv  r  r   r  stream_consumer_holdertool_progress_enabledtools_holderr  sa                                                                          @r   r  *GatewayRunner._run_agent.<locals>.run_sync  sa    0;/@/@bBJJ+, !+BD!IJN %+OOx~~$E56??K`K`L "0!5!52,,,&86&ADDaDa&a%h%h%j"IwG +;7E!>!@ ''B#::<%5D"##GD(D9;ME}:')}}}E!9Rc#}}00AH(<*/*=*=-2-C-C#(<<)
 ,A$,$*NN#0K^k3F%Gdh	,( ,<+D+D(4D.q1 88%XJ
 //7#9% "	D E!$(;TBKT>48Fv1 [#ZZ4F&)t"3 &q	%JKX	 ! } $W- + $2  $	
 %* &6 -?,F,F$ &*%;%;%C%Ct &6 ')ffVn ')ffX&6 %'FF7O #%&&. 137KU0S .0VV4E-F   *!" *#$  $//%& $(#7#7'* 6#5$/4dm{+ %H+W[\ AV+<[_E(9C9P9P9P"5VZE*:E'$9E!%5E"M M 0?E, $LO-4UG-D-Dekk$LO Mwwv ,, 8# ".!4#1S#8 "&&.!%525))+ R+$!QkAQA+I R!((3 "ggi0Gw778,,),BS)TJ(8Bwi&PG!'y' B
  ;.*C(+#(538E%L	*C
 &,,U3U ^ ), $776?&::'')R0C3&(kk.#&FF!'a!6!6!8!?!?!FB!r 4 8 8 < 'G	 % 3L 3Ll %T+A2FN<G>%%k48TD-'1$/$5$52!&=>S&T##$9;PQC//meo/p)*?@)*AB%M!  + '') $ZZ(89N !"KL!!_F'&*>??$+F,E,EG[]^$_!%f.EqI&v/JAN@Fgfgt<DO!;A::g;N;NgfWo%67Tm	$i

:r :K!;\!_22$c-&8(*;"K#\_
 
, ~-
&+#!::j"5Cwwv*>>"%'')R"8#w.)+^W)M',{{1~';';'='D'DU'K#'4D8L,L$.$5$5tfo$F *N  4w>6: 3 6 5D"$K)d? HHSM'..s3  * +#**1.BC%3d%:TYY{=S%SN !OE!&)E)E%JZJZ^hJh%)"E 0 0 **3377D','7'7E$&&,,.OT75,
#KZd  .@SEW% $"2"2"2FGTUVGWGW}Q/33JC]_H$((,&  !. &**-=">MRSDTDTM!,00R@Z\]STEUEU]1-11+qA[\a..B ";$&72  & JIyII   $(OPSu&UR	 J ! RLL!GQQR$ ![[< %B !S` **?@)*ABX ! s   :k- 
l 4m ?m m Am2n#n4nn  n5 41n5 -llllm )l;5m ;m m/m**m/2n	n	 n25ooc                    <"   \        ^4       FN  p S^ ,          e#   S^ ,          P                  4       G Rj  xL
   R# \        P                  ! R4      G Rj  xL
  KP  	  R#  L+ L5i)z8Wait for the stream consumer to be created, then run it.N皙?)r  runrY  r  )r   r  s    r   _start_stream_consumer8GatewayRunner._run_agent.<locals>._start_stream_consumer  sQ     3Z)!,80377999mmD)))	  9)s!   4A'A# A'A%A'%A'c                     <"   S ^ ,          f!   \         P                  ! R4      G Rj  xL
  K+  S'       d   S ^ ,          SP                  S&   R# R#  L(5i)r5  Nr  )rY  r  r_  )r  rv  r   s   r   track_agent-GatewayRunner._run_agent.<locals>.track_agent  sC     q/)mmD)))4@O$$[1  *s   %AAAAc                    <"   SP                   P                  SP                  4      p V '       d	   S'       g   R #  \        P                  ! R4      G R j  xL
  \        V R4      '       g   K3  V P                  S4      '       g   KL  S^ ,          pV'       g   K_  V P                  S4      pV'       d   VP                  MR p\        P                  R4       VP                  V4       R #  L5i)Ng?has_pending_interruptz3Interrupt detected from adapter, signaling agent...)rE  r   r  rY  r  r  r  r   r   r  r  r  )r   rm   pending_eventpending_textr  rv  r   r  s       r   monitor_for_interrupt7GatewayRunner._run_agent.<locals>.monitor_for_interrupt  s     mm''8G+mmC(((
 7$;<<A^A^_jAkAk(OEu(/(C(CK(P=J}'9'9PT%Z[5 )s.   5C+C+C)C+.C+C+C+37C+iX  c                  `  <"   SP                   P                  SP                  4      p V '       g   R #  \        P                  ! S4      G R j  xL
  \        \        P                  ! 4       S,
          ^<,          4      pS
^ ,          pRpV'       d   \        VR4      '       d    VP                  4       pRVR,           RVR,           2.pVP                  R4      '       d   VP                  RVR,           24       M!VP                  VP                  R	R4      4       R
RP                  V4      ,           p V P                  SP                  RV RV R2S	R7      G R j  xL
  EK5   EL  \         d     LAi ; i L  \         d#   p\        P                  RT4        R p?EKs  R p?ii ; i5i)Nrk   re  z
iteration rj  r   r  current_toolz	running: rg  u    — ro  u   ⏳ Still working... (z min elapsedr  r  z#Long-running notification error: %s)rE  r   r  rY  r  r  r  r  re  r   r   r   r  r  r  r  )_notify_adapter_elapsed_mins
_agent_ref_status_detail_ar  _ne_NOTIFY_INTERVAL_notify_startr5  r  rv  r  s          r   _notify_long_running6GatewayRunner._run_agent.<locals>._notify_long_running  s    "mm//@O"mm$4555 #TYY[=%@R$G H)!_
!#'*6L"M"M	'<<>$.r2B/C.DAbIYFZE["\!]66.11"MMIb6H5I*JK"MM"&&1Er*JK)0499V3D)DM)..0|NK[[\]!8 /   # 6 % 
 ! MLL!FLLMst   A
F.E(AF.$=E+ "AE+ 8(E>  E<!E> %F.+E96F.8E99F.<E> >F+	F&F.&F++F.rq   rc  g      @Tr  r  re  rf  rg  r  r  rj  r  zaAgent idle for %.0fs (timeout %.0fs) in session %s | last_activity=%s | iteration=%s/%s | tool=%sr  r  z Execution timed out (inactivity)u   ⏱️ Agent inactive for u(    min — no tool calls or API responses.z!The agent appears stuck on tool `z` (ri  z!s since last activity, iteration r   z).zLast activity: rh  zs ago, iteration z6). The agent may have been waiting on an API response.zTo increase the limit, set agent.gateway_timeout in config.yaml (value in seconds, 0 = no limit) and restart the gateway.
Try again, or use /reset to start fresh.rA  r   rB  rC  rK  rN  rD  r[   rY   interruptedinterrupt_messagez9Processing queued message after agent completion: '%s...'r  z#Processing pending message: '%s...'_active_sessionsu^   Interrupt recursion depth %d reached for session %s — queueing message instead of recursing.queue_messagerS  rk   r  r  z7Failed to send first response before queued message: %s)r9  r>  r  r  r  r   r  )NNN)Cr  r  r   r  r  r  r  r{  r  r  r  r   r  r   r   r   rL  r|   r2  Queuer  r  rY  r  rr  rE  r  r  r  r  ensure_futurer  r  r3  r  re  r  r  r  r   r   r   r[   rf  r   rg  r  r   r  r  r  _MAX_INTERRUPT_DEPTHr  r  r  r  r  r  r_  r`  r   r  r   r  rS  r  r   )Urv  r9  r>  r  r  r  r   r  r?  r  r{  r  _tpl_raw_tpr"  r  progress_taskstream_taskr  r  tracking_taskr  interrupt_monitorr  _notify_task_agent_timeout_raw_agent_timeoutr  _executor_task_inactivity_timeout_POLL_INTERVALrJ  r  r   r  
_idle_secs_act_timed_out_agent	_activity
_last_desc	_secs_ago	_cur_tool_iter_n	_iter_max_timeout_mins_diag_linesr  
_cfg_modelr3  r   rz  r  was_interrupted_sc_already_streamedfirst_responserx  updated_historyr  r|   r  r,  r-  r  r!  r  r3  r6  r4  r5  r.  r  r  r  r  r  r  r	  r   r
  r  r  r  r  r  sU   fffffff&&                                                 @@@@@@@@@@@@@@@@@@@@@@@@@@@r   r  GatewayRunner._run_agent  s    . 	&*,+FOO<?!"5k<"PQ	>??9b1556KQOD$$SYA> //)R044_EeG  yy45  	 	, - 6 ^ ^6??hN^N^;^ +@TF	!Fs8	$ 8	$D ??hnn,"("2"2"F"F6F"("2"2CVk+>?\`k	+ k	+\ vv"& !//1ZZ
	> 	>4 --++FOO< ..H[;0C"Dae	O 	Oh	 h	 h	 h	V  #//0F0HIM 	* ))*@*BC	D  ++KM:	 	( $//0E0GH 			M 	M< **+?+ABd	 "'ryy1G'N!O3E3I/tN))+D$22$$T84N #( N%!//
  $+LL'(.% GD! #1#8#8#:!-aJ!$J!gj:P&Q&Q!#-#B#B#DD)-2JC)PJ "^3.2+""#/? 	#0@BX(Y(Y$4$I$I$K	 ']]+?K
%MM*BAF	%MM.9	#--(8!<%MM*:A>	E~{'' $0@+(N(N$../QR #Nb$8 9 > >Q 1 @( ) &&;I; G%c? +%%,IQyk=  &&)*R	# G%%,IQyk :NN
 ""? %dii&<VWHXHXa 0 4 4Z D^`\!_22$ad "!_F!gfg&>&>35
<<:-,2LLD)/6vz4/PD, ,,[9 -1D)/3D, #1%Fmm''8G G'k::m,,3G[IG"vzz2E'F'F"(**-@"A3G[IG%`bijmbnowBGCLQ
 ww0BCCXcgnggX,,[9??A $t'@'@@NNA(+ #mm//@G77O#D#D--k7C(+``0@(JX_/``B $$&$$&! !**;DDD   "{d.B.BB((5''++K> '(9=,W4"

 Xo #)**]";& 13C(+(S(S^U0S%%+ZZ0@"%EN%.?i"),,v~~~8?zSW8X #/ #Z Z Z #)**Z"A!__##1+!) +%5%9 -   $$&$$&! !**;DDD   "{d.B.BB((5''++K> '(9=,W4"

 X] l $$&$$&! !**;DDD   "{d.B.BB((5''++K> '(9=,W4"

 X %Q'3###
8T(B(B'+H^$m  		@ 0  ) ! ! % p E,,g.D.DE &&()))"11 	$ #"11 cZ( i"NN+dfghhi& E,,g.D.DE &&()))"11 	$ #"11 ) E,,g.D.DE &&()))"11 	$ #"11 9 $$&$$&! !**;DDD,,g.D.DE &&()))"11 	   "{d.B.BB((5''++K> '(9=,W4"

"11 	 Xsg  A}'Ao *1}}:}!}1A}	}!B}#9}C} A3w( o1$w( 8o49w( #w( ,w( ?"o7 !w( *w( 6w( 	w( p	 ,A7w( $w( 3;w( /w( A0w( 2,w( B<w( w( $w( ,w( *w( .Aw( :$w( w( 9Bw( 3w( 5w( <}7}=ppp}5%}*}rrr}w( 3w( 'w( -w( 60r& &r#'r& +4w( s w( #?}$s?s s}%}*}2u7u 8u<}}
7}u# u u# #};%}!*}www}0}}o.*}-o..}1w( 4w( 7pw( pw( 	pw( pw( p5r q"qq"}"q<7r 8};q<<r  }rr }r  }#r& &s1sw( sw( s5t=ttt}t94t=5}8t99t==} uu}u} u# #5wv'v!v'$}'w<w=} ww}ww% }$w%%}(A }	*yyy}	5z,zz

z}	z(	$z,%}	'z(	(z,,}	%}	-*}	|*"|%
#|*(}	*}	?}	}	}		}c                <   < V ^8  d   Qh/ S[ S[S[3,          ;R&   # )r   r`  )r   r   r  )r   r2  s   "r   r   r3    s      S%Z(- r   )#r  rc  re  ru  rf  rg  rI  r\  r^  r]  rj  rQ  ri  ra  rs  rG  rO  rK  rX  r_  r`  rm  rh  rM  r[  rS  r  rk  rt  rE  r  rW  rr  rp  rV  r9  )r  )F)g       @g      @g      @)Nr5  N)tr  
__module____qualname____firstlineno____doc__r`  ry  r  r   r  rs  r  r  r  r  r  propertyr  r  r  r  r   r  r  staticmethodrF  rH  rJ  rL  rA  rN  rP  rR  r  r  r  r  r  r  rN  rT  r  r  rq  r  r  r  r  r  r  r  r  r  r  r  r  ry  r  r  r  r  r  r  r  r  r  r  rv  r  r  r  r  r  r  r  r  r  r  r  r  _APPROVAL_TIMEOUT_SECONDSr  r  	frozensetr|   r  r  r  r  r  r,  r.  r   r"  r$  r&  r(  r*  r  rr  r  r  r  r  rj  r  rz  r}  r  r  r  r  r  __annotate_func____static_attributes____classdictcell__)r2  s   @r   r0  r0    s	     ,.`, `,N  $&??
 
 @ @, ,
 
h` h`T

 

 " " ' ' ! !
 
 d d; ;z# #
 $ $L  (  4      D    (  \ \|e' e'Nd' d'L1' 1'f* *{ {zc- c-J P: P:d^& ^&@M  M ^E EN   <   2- -<   ,3  3 jF  F P6  6 pHJ HJT!7 !7FS S2
 
:  I. I.V0X 0Xd% %.M M0, 0,d4 4l8 8tJI JIX9( 9(vJ J: B#J #JJy yvQV QVf\ \;R ;RzC. C.J.f .f`KT KTZX
 X
t#; #;J-5 -5^D1 D1T !$7q 7qrK KD !*8++X^^X=N=N,,hooh>O>O	+ ![J [JzX X|? |?|W WrS S$ $B BHQ Qf]> ]>~ %> %>N9 9[ [Eo  r   r0  c                D    V ^8  d   QhR\         P                  R\        /# )r   
stop_eventr  )rb  rZ  r  )r   s   "r   r   r     s     3' 3'9?? 3'X[ 3'r   c                r   ^ RI Hp ^ RIHpHp ^<p^p\
        P                  RV4       ^ p	V P                  4       '       g    V! RWR7       V	^,          p	W,          ^ 8X  d   V'       d    ^ RI
Hp V! V4       W,          ^ 8X  dQ    V! ^R
7      pV'       d   \
        P                  RV4        T! ^R
7      pT'       d   \
        P                  RT4       V P                  VR7       K  \
        P                  R4       R#   \         d!   p
\
        P                  RT
4        Rp
?
LRp
?
ii ; i  \         d!   p
\
        P                  R	T
4        Rp
?
LRp
?
ii ; i  \         d!   p
\
        P                  RT
4        Rp
?
LRp
?
ii ; i  \         d!   p
\
        P                  RT
4        Rp
?
LRp
?
ii ; i)a  
Background thread that ticks the cron scheduler at a regular interval.

Runs inside the gateway process so cronjobs fire automatically without
needing a separate `hermes cron daemon` or system cron entry.

When ``adapters`` and ``loop`` are provided, passes them through to the
cron delivery path so live adapters can be used for E2EE rooms.

Also refreshes the channel directory every 5 minutes and prunes the
image/audio/document cache once per hour.
)tick)cleanup_image_cachecleanup_document_cachez"Cron ticker started (interval=%ds)F)ry  rE  r  zCron tick error: %sNrg  z#Channel directory refresh error: %s)max_age_hoursz-Image cache cleanup: removed %d stale file(s)zImage cache cleanup error: %sz0Document cache cleanup: removed %d stale file(s)z Document cache cleanup error: %sr  zCron ticker stopped)cron.schedulerr  r  r  r  r  r  is_setr   r  r  rh  r  )r  rE  r  r  	cron_tickr  r  IMAGE_CACHE_EVERYCHANNEL_DIR_EVERY
tick_countrx  rh  r@  s   &&&&         r   _start_cron_tickerr    st    1R
KK4h?J!!	3ehB 	a
)Q.8GM'1 )Q.A-B?KK OQXYD0rBKK RT[\ 	)
KK%&7  	3LL.22	3  GBAFFG  A<a@@A  D?CCDsl   
D +D/ E E /F  F D,D''D,/E:EEF(FFF6F11F6c                t    V ^8  d   QhR\         \        ,          R\        R\         \        ,          R\        /# )r   r  r   	verbosityr   )r   r}   r}  r  )r   s   "r   r   r     s;     u u 7 u ubjknbo ux| ur   c           
     
  a"   ^ RI p^ RIHpHp V! 4       pVEeV   V\        P
                  ! 4       8w  Ed;   V'       d   \        P                  RV4        \        P                  ! V\        P                  4       \        ^4       F,  p \        P                  ! T^ 4       TP                  R4       K.  	  \        P!                  RT4        \        P                  ! T\        P"                  4       TP                  R4       T! 4         ^ RIHp T! 4       p	T	'       d   \        P                  R	T	4       M:\)        \+        4       4      p
\        P                  R
Wj4       \-        RV R24       R#  ^ RIHp V! RR7       ^ RIHp V! \6        RR7      p^ RIHp ^ RIHp V! \>        P@                  ! 4       VR,          \>        PB                  R#^V! R4      R7       Ve   ^ \>        PD                  ^\>        PB                  /PG                  V\>        PH                  4      p\>        PJ                  ! 4       pVPM                  V4       VPO                  V! R4      4       \>        P@                  ! 4       PQ                  V4       V\>        P@                  ! 4       PR                  8  d%   \>        P@                  ! 4       PM                  V4       \U        V 4      oV3R lp\V        PX                  ! 4       p\        PZ                  \        P                  3 F  p VP]                  VV4       K  	  SPa                  4       G Rj  xL
 pV'       g   R# SPb                  '       d5   SPd                  '       d!   \        P                  RSPd                  4       R# ^ RI3p^ RIH4pHp V! 4        VPk                  V4       \l        Pn                  ! 4       p\l        Pp                  ! \r        V3RSPt                  R\V        Pv                  ! 4       /RRR7      pVPa                  4        SPy                  4       G Rj  xL
  SPz                  '       d5   SPd                  '       d!   \        P                  R SPd                  4       R# TP}                  4        VP                  ^R!7        ^ R"I@HAp V! 4        R#   \         d     EL?\         d    \        P                  RT4        R# i ; i  \        \        3 d      EK  i ; i  \        \        3 d     ELi ; i  \&         d     ELi ; i  \&         d     ELi ; i  \^         d     EK6  i ; i EL EL  \&         d     R# i ; i5i)$a  
Start the gateway and run until interrupted.

This is the main entry point for running the gateway.
Returns True if the gateway ran successfully, False if it failed to start.
A False return causes a non-zero exit code so systemd can auto-restart.

Args:
    config: Optional gateway configuration override.
    replace: If True, kill any existing gateway instance before starting.
             Useful for systemd services to avoid restart-loop deadlocks
             when the previous process hasn't fully exited yet.
N)get_running_pidr  z<Replacing existing gateway instance (PID %d) with --replace.z1Permission denied killing PID %d. Cannot replace.Fg      ?zAOld gateway (PID %d) did not exit after SIGTERM, sending SIGKILL.)release_all_scoped_locksz2Released %d stale scoped lock(s) from old gateway.zAnother gateway instance is already running (PID %d, HERMES_HOME=%s). Use 'hermes gateway restart' to replace it, or 'hermes gateway stop' first.u"   
❌ Gateway already running (PID z).
   Use 'hermes gateway restart' to replace it,
   or 'hermes gateway stop' to kill it first.
   Or use 'hermes gateway run --replace' to auto-replace.
)sync_skillsT)quiet)setup_loggingr	  )r'   r  )RedactingFormatter)_add_rotating_handlerzgateway.logz/%(asctime)s %(levelname)s %(name)s: %(message)s)r  	max_bytesbackup_count	formatterz#%(levelname)s %(name)s: %(message)sc                  P   < \         P                  ! S P                  4       4       R # r9  )rY  r  r  )runners   r   signal_handler%start_gateway.<locals>.signal_handler  s    FKKM*r   zGateway exiting cleanly: %s)write_pid_filer  rE  r  zcron-ticker)r  r   r  daemonr   z Gateway exiting with failure: %sr  )r5  i  P )Br  r  r  r  r   getpidr  r  killsignalSIGTERMProcessLookupErrorPermissionErrorr  r  r  r  SIGKILLr  r   r   r#   printtools.skills_syncr  hermes_loggingr  r   agent.redactr  r  logging	getLoggerINFOWARNINGr   DEBUGStreamHandlersetLevelsetFormatter
addHandlerr  r0  rY  r  SIGINTadd_signal_handlerNotImplementedErrorr  r  r  atexitr	  registerrb  rZ  Threadr  rE  r  r  r  r   r   r9  r5  )r  r   r  _timer  r  existing_pidr   r  	_releasedr'   r  r  log_dirr  r  _stderr_level_stderr_handlerr	  r  sigr  r	  r	  	cron_stopcron_threadr5  r 	  s   &&&                        @r   start_gatewayr(	    s]    & ?"$LLBIIK$?KKN	fnn5 2YGGL!,KK$  W GGL&..9KK$ C46	KK TV_` o/0KLL^
 5l^ DN O 1$ -9EG 04-ll!$%VW GOOQ=AA)W]][!//1  /$$%78]%^_&&77,,.444((76"F+ !!#Dv~~.	##C8 / LLN"G!!!LL68J8JK >
OOO$ !I""!\FOOVW5M5M5OPK  
"
"
$$$&&&LL;V=O=OP MMOQ7 o & " G   +O<  +O<   *  \ # 		 #6 %  s]  ;U"U"%R, ;U"
(S!2U"6S; U"T  T 6;U"2T% FU"T7&U"=U
>U"
U"U"0B?U"/U0U"U"AU"U *U",S7U":SSU"SU"!S82U"7S88U";TU"TU"T"U"!T""U"%T40U"3T44U"7UU"UU"U"UU"UU"c                    ^ RI p V P                  RR7      pVP                  RRRR7       VP                  RR	R
RR7       VP                  4       pRpVP                  '       dU   ^ RIp\        VP                  RR7      ;_uu_ 4       pVP                  ! V4      p\        P                  ! V4      pRRR4       \        P                  ! \        V4      4      pV'       g   \        P                  ! ^4       R# R#   + '       g   i     LQ; i)z CLI entry point for the gateway.Nz)Hermes Gateway - Multi-platform messaging)rF  z--configrp  zPath to gateway config file)ru  z	--verbosez-v
store_truezVerbose output)actionru  r*   r+   )argparseArgumentParseradd_argument
parse_argsr  r   r  r   r}   	from_dictrY  r  r(	  r*  exit)r,	  parserr   r  r   r  r  r  s           r   mainr3	    s    $$1\$]F

D/LM
T,EUVDF{{{$++00A99Q<D",,T2F 1 kk-/0G  10s   )C99D		__main__)rb  rl   r1   r9  )NNrt  )NFr5  )zr  rY  r   r	  r   r  rk  r*  r	  r)  rb  r  r&  r,  r   r   typingr   r   r   r	   r"   r   ri  r   r   r   r   r#   utilsr$   r   dotenvr%   hermes_cli.env_loaderr&   r\  r   r  rk  r   r  _yamlr  r%  r  _cfgr~  r-   r  _key_valr  r  r  r}  r   r   _terminal_cfgr   _terminal_env_map_cfg_key_env_varr   r  _auxiliary_cfg_aux_task_env	_task_key_env_map	_task_cfgr   _provr  r  r  
_agent_cfg_tz_cfg_security_cfg_redactr   r   rw   _configured_cwdr   r-  messaging_cwdrL  r|   r}   r~   gateway.sessionr   r   r   r   r   r   gateway.deliveryr   r  r   r   r   r   r   r	  r  r  objectr  r   r   r   r  r  r  r   r.  r0  r  r(	  r3	  r   r   r   <module>rP	     s      	 	  
        , ,#J   3tH~,,334 5 - #   46!	 |h9O9O9Q9Y9YZ[9\_e9e f m+j,11R??2&,,"D 2 	7%**,JD$$c5$ 788T=S#&t9

4  '
 R0Zt<<!>!~! -! #$?	!
  7! %&C! $%A! 5!  !9! /! /! /! -!  !9! #$?!  !";!!" '(G#!$ !";5"$?)!, '8&=&=&?"(},(2D!$--/3zz$/?

8,/24y

8, '@ +r2>j>> ;5 ;9	  @: @>	   =7 =;	M( (5':':'<#	8*..y"=	!)T22IMM*b9:@@BY]]7B78>>@	j" =>DDF	y}}Y;<BBDUf_7<BJJx
344:BJJx017@BJJx
3486>BJJx	23 (=  XXgr*
*Z66j(69*[:Q6R

23 !J.3IQSQ[Q[3[58DU9V5W

12 ((:r*z'3//4ERZZ4W,3MMOBJJ()R0mT**#''(89G"69'l6H6H6J

23
	7
 !

>  !$

 
 **..4/-AAIIo.BB#diik2BM!.BJJ~ 
  , Q Q> 
		8	$ !( 2,-`C

 6}g }g@P3'lup0 zF ic 211N    		s   Z9 )Z%<Z9 Z9 2Z9 Z9 AZ9 8Z9 AZ9 %Z9 5C9Z9 /$Z9 Z9 2Z9 4Z9 Z9 A0Z9 Z9 AZ9 &8Z9 [ %Z6	0	Z9 9[[[[