
    `gj	                    ?   U d dl Z d dlZd dlZd dlZd dlZd dlZd dlZd dlZd dl	Z	d dl
Z
d dlZd dlZd dlZd dlZd dlZd dlmZ d dlmZ d dlmZmZmZ d dlmZmZmZmZ d dlmZ d dlmZ d dl m!Z! d d	l"m#Z# d d
l$m%Z% d dl&m'Z'm(Z(m)Z)m*Z*m+Z+  ejX                  e-      Z. e       Z/ ee/ ee0      jb                  jb                  dz         e	jd                  jg                  e/dd      Z4d Z5e5e_6        d Z7e7e_6        	 d dl8m9Z9  e9        d dl;m<Z<m=Z=m>Z> i Z?e@eAe@f   eBd<   i ZCe@eAeDf   eBd<   i ZEe@eAeFeAej                  f   f   eBd<   i ZHe@eAeFeAe@f   f   eBd<   i ZIe@eAeAf   eBd<   daJdaKeAdz  eBd<    ej                         ZM ej                         ZN ej                         ZP ej                         ZQdaRe@dz  eBd<   daSeTdz  eBd<   daU ej                         ZV	  eTe	j                  j                  d      xs d      ZY e\deY      Z]	  eTe	j                  j                  d       xs d!      Z^ e\d#e^      Z_d$Z` eah d%      Zb eah d&      Zc	  e\d' ede	j                  j                  d(      xs d)            Zeej                  j                  eed+,      Zh e j                  d-        ej                  Zkej                  e_j         G d. d/      Zm e'd0 eM      Zn em       Zo G d1 d2      Zpd3eAfd4Zqd3erfd5Zs	 d=d6eAd7eAdz  d8eAdz  d3dfd9Ztd:d;d<eAd=eAd>eAd3eFeeAdz  f   fd?Zud@e@dz  d3dfdAZvdBeAd@e@dCeAd3erfdDZw eah dE      ZxdFeAd3erfdGZyd>d@e@dz  dIeAd3dfdJZzdHdKd@e@dz  dIeAd3dfdLZ{dBeAd@e@d3dfdMZ|dBeAd3e@dz  fdNZ}dHdKd@e@dz  dIeAd3erfdOZ~dHdKdBeAdIeAd3erfdPZd@e@dz  d3erfdQZdBeAd3dfdRZdSdKdIeAd3eFededf   fdTZd?dUZ	  eTe	j                  j                  dV      xs dW      Z e\d#e      ZdXZd3erfdYZdBeAd@e@dZeTd3erfd[Zd?d\Zd3edfd]ZdBeAd@e@d3erfd^Zd?d_Zd?d`Zd?daZ e j                  e        e        db ZdcedfddZdeeAdz  d3edz  fdfZdg Zh dhZdie@dz  d3eAdz  fdjZdkedz  d3eAdz  fdlZd3eAdz  fdmZd3eAfdnZdoe@d3erfdpZd=dqeAdBeAdre@dz  fdsZda ej                         Zd3erfdtZd=die@dz  d3erfduZd=d@e@die@dz  d3erfdvZd=die@dz  fdwZdxeAdBeAd@e@dyed3e@f
dzZd@e@dz  d3e@fd{Zd@e@d|e@dz  d3dfd}ZdxeAdBeAd@e@d|e@d3df
d~ZdxeAdBeAd@e@dyed3e@f
dZdddddBeAdeAdeAdre@dz  derd3e@fdZdBeAde@dz  d3dfdZd=dBeAdeAdyeAdz  fdZdeddedd3edfdZded3e@fdZde@d3e@fdZdceddeAd3e@fdZdeAfdZded3eFeeAe@f   e@z  fdZde@d3e@dz  fdZd=de@dee(   d3e@dz  fdZd@d@e@dxeAdeTd3e@dz  fdZdBeAd@e@d3dfdZd Zd ZdeAd3eAfdZd=de@dz  d3eAfdZd@e@dz  d3eAfdZe%jl                  Ze%jp                  Ze%jt                  Ze%jx                  Ze%j|                  Zd@e@dz  d3eAfdZdeAd3eAfdZd3erfdZd@e@dz  d3eAfdZd@e@dz  d3eAfdZd@e@dz  d3dfdZd@e@d3dfdZd@e@d3dfdZej                  d@e@fd       Zd@e@deAd3dfdZd@e@deAd3eAfdZdZeFeAdf   eBd<   dZdZdZdZdededdedd3edfdZѐd=die@dz  d3e@eAef   fdZd3e@fdZdie@d3e@fdZdie@fdZd<eAd3eAfdZ	 d=ddd<eAdeAdz  deAd3efdÄZded3dfdńZِd?dƄZڐdAdqeAdBeAdre@dedd3eAf
dǄZېd=dBeAdz  d3dfdȄZd3e@fdɄZd3eAfdʄZd3eAfd˄ZdeAdz  d3eAfd̈́ZdFeAdz  d3eAfd΄Zd3eFeAeAf   fdτZd3eFeAeAdz  f   fdЄZh dѣZde@dz  d3e@fdӄZd=de@dz  d3e@fdՄZd@e@dz  d3dfdքZd@e@dz  d3dfdׄZd@e@dz  deAdeAd3dfdڄZdeAfd܄Z eah dݣ      Z eah dޣ      Zd3eAfd߄Zd3eAfdZi ddddddddddddddddddddddddddddddddZde@d3eAfdZdBdeAd3e@dz  fdZd3eAdz  fdZd3e@fdZd3erfdZd3eAfdZd3eAfdZd3eeA   dz  fdZdBeAd3eAfdZdBeAd3erfdZdBeAd3erfdZdBeAd@e@fdZd?dZd3e@fdZd e@dz  d3dfdZddddddBeAd@e@deAderderdedz  derdz  d3e@fdZdBeAd@e@d3dfd	Z 	 	 	 	 dCd@e@d
eAdz  deddz  dedz  deddz  d3eFede@f   fdZddddBeAd@e@derderd3df
dZd3e@fdZd3eAfdZdie@d3eAfdZd3eAfdZdZd@e@dz  d3e@fdZdeAd3e@dz  fdZ	d=d@e@dz  d3e@fdZ
deAde@d3eAfdZdBeAd@e@d3dfdZdZdZdyeAd3eAfd ZdyeAd3eAfd!Zde@d3eAfd"Zded3eAfd#Zd$eTdz  d3eAfd%ZdoedeAd3eddz  fd&ZdeAdeAd'eTdz  d3eAdz  fd(ZdBeAd)eAdeAde@fd*ZdBeAd)eAdeAde@deAf
d+Z	 	 	 dDdBeAd6eAdeAdz  d,eAdz  d-e@dz  f
d.Zi Ze@eAe@f   eBd/<    ej                         Zi Ze@eAeTf   eBd0<   d1Zd2eAd3erfd3Zd6eAdre@d3dfd4ZdBeAd3e@fd5Z dBd6eAdeAd7eAd3dfd8Z!dBeAfd9Z"d3eAfd:Z#d=die@dz  d3e@fd;Z$d=deAdie@dz  d3eFeAeAf   fd<Z%d3eAfd=Z&	 dBdBeAd@e@d>eAd?eAd3eFere@dz  f   f
d@Z'die@dedd3edfdAZ(d3eeA   fdBZ)dC Z*dD Z+d6eAd3e@fdEZ,d6eAd3e@fdFZ-dEd@e@dGeddHedd3ee@   fdIZ.deAdeAd3eAfdJZ/dKeAd6eAd3e@fdLZ0dBeAd@e@d3e@fdMZ1dBeAd3dfdNZ2 G dO dPe      Z3	 d=dQe@dz  d3e3fdRZ4	 	 	 	 	 	 	 dFdBeAdSeAd7eAdz  dTe@eAz  dz  dUeAdz  dVe@dz  dWeAdz  dXeAdz  fdYZ5	 	 	 	 dGdBeAdSeAdZeאd[eddeAdz  dFeAdz  fd\Z6d3eAfd]Z7d^ Z8deAd_eAd3eAfd`Z9daed3eFeAeAf   fdbZ:dceAddeeA   d3eAfdeZ;dfed3eAfdgZ<dfed3eAfdhZ=dZee@   d3ee@   fdiZ>ded3ee@   fdjZ?dfed3eAfdkZ<ded3eAfdlZ@d@e@dyed3dfdmZAd@e@dned3dfdoZBd@e@d3dfdpZCd@e@dyeded3dfdqZDdBeAd@e@daed3dfdrZEdBeAd@e@dyeded3e@dz  f
dsZFdBeAd@e@d3erfdtZGd@e@d3e@dz  fduZHd@e@d3e@dz  fdvZI edw      de@d3e@fdx       ZJ edy      de@d3e@fdz       ZJ ed{      de@d3e@fd|       ZJ ed}      de@d3e@fd~       ZJ ed      de@d3e@fd       ZJddddeAdeAdeAd3e@fdZKd:dddddddd<eAd[eddeAdZedFeAderdedz  dkedz  derde@dz  d3e@fdZLdBeAd<eAde@d3eFeAe@f   dz  fdZMdHdBeAdeTd3dfdZN ed      de@d3e@fd       ZJ ed      de@d3e@fd       ZJdBeAd3eAfdZOdBeAd@e@d3eAfdZPdZed3eAfdZQd@e@dSeAd3eAfdZRdBdBeAd@e@deAd3e@fdZSddd@e@deAd3eAfdZTd<eAd3eFeAe@f   dz  fdZUd@e@d3e@fdZVdddddBeAd@e@d[eddz  derde(dz  d3e@fdZW ed      de@d3e@fd       ZJ ed      de@d3e@fd       ZJ ed      de@d3e@fd       ZJ ed      de@d3e@fd       ZJd3e@dz  fdZX ed      de@d3e@fd       ZJ ed      de@d3e@fd       ZJ ed      de@d3e@fd       ZJ ed      de@d3e@fd       ZJ ed      de@d3e@fd       ZJ ed      de@d3e@fd       ZJd3e@fdZY ej                         ZZi Z[e@eFe@f   eBd<   d3eAfdZ\deTd3eFdz  fdZ]dre@d3e@fdZ^d3e@fdZ_d3eTfdZ`deTd3e@fdZad Zbd3eeA   fdZc ed      ede@d3e@fd              ZJ ed      ede@d3e@fd              ZJ edë      ede@d3e@fdĄ              ZJ edū      ede@d3e@fdƄ              ZJ edǫ      ede@d3e@fdȄ              ZJ edɫ      ede@d3e@fdʄ              ZJ ed˫      ede@d3e@fd̄              ZJ edͫ      ede@d3e@fd΄              ZJ edϫ      ede@d3e@fdЄ              ZJ edѫ      ede@d3e@fd҄              ZJ edӫ      ede@d3e@fdԄ              ZJdՄ Zdd1d֜deTd3dfd؄Zedِdڜdedd3eAfd܄Zf ej                         Zg eh       ZieheA   eBd<   dސdߐdߐdddZj	  e\d ede	j                  j                  d      xs	  eAd                  ZkdeAd3efdZldeAd3dfdZmdeAd3dfdZndeAd3erfdZodeAd3dfdZp ed      de@d3e@fd       ZJ ed      de@d3e@fd       ZJ ed      de@d3e@fd       ZJ ed      de@d3e@fd       ZJd3e@fdZqd3e@fdZrd3e@fdZs ed      de@d3e@fd       ZJd3ee@   fdZtd3e@fdZu ed      de@d3e@fd       ZJd3e@fdZv ed      de@d3e@fd        ZJd3e@fdZw ed      de@d3e@fd       ZJ ed      de@d3e@fd       ZJ ed      de@d3e@fd       ZJ ed      de@d3e@fd	       ZJ ed
      de@d3e@fd       ZJ ed      de@d3e@fd       ZJ ed      de@d3e@fd       ZJ ed      de@d3e@fd       ZJ ed      de@d3e@fd       ZJ ed      de@d3e@fd       ZJ ed      de@d3e@fd       ZJ ed      de@d3e@fd       ZJ ed      de@d3e@fd       ZJ ed      de@d3e@fd       ZJ ed      de@d3e@fd       ZJ ed       de@d3e@fd!       ZJ ed"      de@d3e@fd#       ZJ ed$      de@d3e@fd%       ZJ ed&      de@d3e@fd'       ZJd( Zxd7eAfd)Zyd*Zzd+e@d3dfd,Z{d3ee@   fd-Z| ed.      de@d3e@fd/       ZJ ed0      de@d3e@fd1       ZJ ed2      de@d3e@fd3       ZJ ed4      de@d3e@fd5       ZJ ed6      de@d3e@fd7       ZJ ed8      de@d3e@fd9       ZJdBeAd@e@d:e@d3erfd;Z}dBeAd@e@d:e@d3erfd<Z~d:e@d3erfd=Zd:e@d3eFfd>Zd?ej                  dBeAd@e@d3dfd@Zd?dAZdBeAd@e@d3ej                  fdBZdBeAd@e@dyed3dfdCZ edD      de@d3e@fdE       ZJ edF      de@d3e@fdG       ZJdHZdIZdJZdKZeFeFeeAf   df   eBdL<   dMeAdNeAd3edz  fdOZdBdPedQeAd3eAfdRZd3eaeA   fdSZd@e@dPedTeAdUeAd3ef
dVZ edW      de@d3e@fdX       ZJ edY      de@d3e@fdZ       ZJdadeAd3eAfd[Zd@e@d\ed3eAfd]Zd@e@d3efd^ZdeAd3eAfd_Zd`edQeAd3efdaZdMeAd3edz  fdbZdceAd3efddZd@e@deeAdceAdeAd3eFeerf   f
dfZ edg      de@d3e@fdh       ZJ edi      de@d3e@fdj       ZJ edk      de@d3e@fdl       ZJ edm      de@d3e@fdn       ZJ edo      de@d3e@fdp       ZJddqdrZ eds      de@d3e@fdt       ZJ edu      de@d3e@fdv       ZJ edw      de@d3e@fdx       ZJ edy      de@d3e@fdz       ZJ ed{      de@d3e@fd|       ZJ ed}      de@d3e@fd~       ZJdZdZdZ G d de:      Zd3e@fdZdeAfdZde@fdZ ed      d3e@fd       ZJ ed      d3e@fd       ZJ ed      d3e@fd       ZJ ed      d3e@fd       ZJ ed      d3e@fd       ZJ ed      d3e@fd       ZJ ed      d3e@fd       ZJ ed      d3e@fd       ZJ ed      d3e@fd       ZJ ed      d3e@fd       ZJ ed      d3e@fd       ZJd`eAd3erfdZdeAd3erfdZdddderd3ee@   fdZ ed      de@d3e@fd       ZJ ed      de@d3e@fd       ZJdgZde@d3e@fdZdedderd3eFee@   ee@   ee@   eAdz  f   fdZdedderdedderd3eFe@eAdz  f   f
dZ ed      de@d3e@fd       ZJ ed      de@d3e@fd       ZJ ed      de@d3e@fd       ZJ ed      de@d3e@fd       ZJ ed      de@d3e@fd       ZJ ed      de@d3e@fd       ZJd@e@d3efdZ ed      de@d3e@fd       ZJ ed      de@d3e@fd       ZJ ed      de@d3e@fd       ZJ ed«      de@d3e@fdÄ       ZJ eah dģ      ZeaeA   eBd<   g dƢZeeFeAeAeAf      eBd<    eah dȣ      ZeaeA   eBd<    ead dh      ZeaeA   eBd<    ed̫      de@d3e@fd̈́       ZJdeeA   d3eAdz  fdτZ edЫ      de@d3e@fdф       ZJ edҫ      de@d3e@fdӄ       ZJdeAd3eAfdԄZ edի      de@d3e@fdք       ZJd a ed׫      de@d3e@fd؄       ZJdZdِZ eah dڣ      Z ej                         Zi Ze@eAeFeTeeA   f   f   eBd<   d`eAd3eeA   fd܄ZdeAdeAd3eFededf   dz  fdބZ ed߫      de@d3e@fd       ZJdBdeAdeAd3e@fdZdeAdeAderd3e@fdZdyeAd3ee@   dz  fdZ ed      de@d3e@fd       ZJ ed      de@d3e@fd       ZJ ed      de@d3e@fd       ZJ ed      de@d3e@fd       ZJ eah d      Z eah d      Zd@e@d3eAfdZd@e@d3eAfdZd@e@d3eAfdZd@e@d3eAfdZd@e@d3eAfdZd3eAfdZd@e@d3eAfdZdBeAd@ee@   deAdeAd3eeA   f
dZdBeAd@e@deAd3eAfdZ ed      de@d3e@fd       ZJ ej                         ZdaeAeBd<   d=dqeAdre@dz  d3dfdZd3erfdZd3erfdZd3e@fd Zd3eAfdZ ed      de@d3e@fd       ZJ ed      de@d3e@fd       ZJ ed      de@d3e@fd       ZJ ed      de@d3e@fd	       ZJ ed
      de@d3e@fd       ZJ ed      de@d3e@fd       ZJ ed      de@d3e@fd       ZJd3eAfdZd3erfdZːdeAdeTd3erfdZd3eeA   fdZd3eAfdZΐdeAdeddeAd3eeA   fdZ ed      de@d3e@fd       ZJde@d3e@fdZd3e@fdZ ed      de@d3e@fd       ZJ ed      de@d3e@fd        ZJ ed!      de@d3e@fd"       ZJ ed#      de@d3e@fd$       ZJ ed%      de@d3e@fd&       ZJ ed'      de@d3e@fd(       ZJ ed)      de@d3e@fd*       ZJ ed+      de@d3e@fd,       ZJ ed-      de@d3e@fd.       ZJ ed/      de@d3e@fd0       ZJ ed1      de@d3e@fd2       ZJ ed3      de@d3e@fd4       ZJ ed5      de@d3e@fd6       ZJ ed7      de@d3e@fd8       ZJ ed9      de@d3e@fd:       ZJ ed;      de@d3e@fd<       ZJy# e:$ r Y %w xY w# eZe[f$ r dZYY >w xY w# eZe[f$ r d"Z^Y w xY w# eZe[f$ r d*ZeY w xY w# e[eZf$ r  eTdW      ZY w xY w# e[eZf$ r dZkY w xY w(I      NdatetimePath)Any
NamedTupleOptional)get_hermes_homeget_hermes_home_overridereset_hermes_home_overrideset_hermes_home_override)load_hermes_dotenv)is_truthy_value)hermes_subprocess_env)sanitize_replay_history)	git_probe)StdioTransport	Transportbind_transportcurrent_transportreset_transportz.env)hermes_homeproject_envlogsztui_gateway_crash.logc                    dd l }dj                  |j                  | ||            }	 t        j                  t        j
                  j                  t              d       t        t        dd      5 }|j                  dt        j                  d	       d
       |j                  |       d d d        t        |      j                         r*t        |      j                         j                         d   n| j                   }t#        d| j                    d| t$        j&                  d       t%        j(                  | ||       y # 1 sw Y   xY w# t        $ r Y w xY w)Nr    Texist_okautf-8encodingu   
=== unhandled exception · %Y-%m-%d %H:%M:%S ===
z[gateway-crash] : fileflush)	tracebackjoinformat_exceptionosmakedirspathdirname
_CRASH_LOGopenwritetimestrftime	Exceptionstrstrip
splitlines__name__printsysstderr__excepthook__)exc_type	exc_valueexc_tbr)   traceffirsts          E/root/.hermes/venv/lib/python3.12/site-packages/tui_gateway/server.py_panic_hookrE   ;   s#   GGI..xFKLE
BGGOOJ/$?*cG4 	GG/>Q0R/SSYZ GGEN		 y>! 	I))+A. 

 
X../r%
9

RVWxF3#	 	
  s*   A
E 2:E,E EE 	EEc                 ~   dd l }dj                  |j                  | j                  | j                  | j
                              }	 t        j                  t        j                  j                  t              d       t        t        dd      5 }|j                  dt        j                  d	       d
| j                  j                    d       |j                  |       d d d        t%        | j                        j'                         r4t%        | j                        j'                         j)                         d   n| j                  j*                  }t-        d| j                  j                    d| j                  j*                   d| t.        j0                  d       y # 1 sw Y   xY w# t"        $ r Y w xY w)Nr   r   Tr   r   r    r!   u   
=== thread exception · r#   u    · thread=r$   z[gateway-crash] thread z raised r%   r&   )r)   r*   r+   r>   r?   exc_tracebackr,   r-   r.   r/   r0   r1   r2   r3   r4   threadnamer5   r6   r7   r8   r9   r:   r;   r<   )argsr)   rA   rB   
first_lines        rD   _thread_panic_hookrL   X   sb   GG""4==$..$BTBTUE	
BGGOOJ/$?*cG4 	GG,T]];N-O,P Q![[--.f6 GGEN	 t~~$$& 	DNN!!#..03]]## 
 

!$++"2"2!38DMM<R<R;SSUV`UabZZ	 	  s,   A
F0 AF$!F0 $F-)F0 0	F<;F<)prefetch_update_check)make_stream_rendererrender_diffrender_message	_sessions_methods_pending_pending_prompt_payloads_answers	_db_error
_cfg_cache
_cfg_mtimeHERMES_TUI_SLASH_TIMEOUT_S45g     F@g      @!HERMES_TUI_WS_ORPHAN_REAP_GRACE_S20g      4@        thinkingtools	subagentsactivity>   hiddenexpanded	collapsed>(   cli.execpet.info	pet.cells	pet.hatch	pet.thumb
pet.select
shell.exec
slash.exec
usage.barsllm.oneshotpet.gallerypet.generateprocess.listsession.listsetup.statusbilling.statecomplete.pathmodel.optionsprojects.treesession.usageskills.managebrowser.managecomplete.slashplugins.managesession.branchsession.resumebilling.step_uplearning.framesprojects.for_cwdsession.compresssubscription.statesession.active_listsetup.runtime_checksubscription.changesubscription.resumesubscription.previewsubscription.upgradeprojects.record_reposprojects.discover_reposprojects.project_sessions   HERMES_TUI_RPC_POOL_WORKERS8   ztui-rpc)max_workersthread_name_prefixc                  0    t         j                  dd      S )NFT)waitcancel_futures)_poolshutdown     rD   <lambda>r     s    E$G r   c                   (    e Zd ZdZdedefdZddZy)_DropTransportzGDetached WS sink: keep sessions resumable without writing stale frames.objreturnc                      yNFr   )selfr   s     rD   r2   z_DropTransport.write  s    r   Nc                      y Nr   )r   s    rD   closez_DropTransport.close  s    r   r   N)r9   
__module____qualname____doc__dictboolr2   r   r   r   rD   r   r     s    Q $ r   r   c                      t         S r   )_real_stdoutr   r   rD   r   r   %  s    , r   c                   N    e Zd ZdZddedededz  fdZd Zd Zd	ed
efdZd Z	y)_SlashWorkerz3Persistent HermesCLI subprocess for slash commands.Nsession_keymodelprofile_homec                    t        j                         | _        d| _        g | _        t        j                         | _        t        j                  ddd|g}|r|d|gz  }d| _
        ddlm} t        d	      }|rt        |      |d
<   t        j                   |t        j"                  t        j"                  t        j"                  ddt%        j&                         | |       d
      | _        t        j*                  | j,                  d      j/                          t        j*                  | j0                  d      j/                          y )Nr   -mztui_gateway.slash_workerz--session-keyz--modelFwindows_hide_flagsTinherit_credentialsHERMES_HOME   )	stdinstdoutr<   textbufsizecwdenvcreationflagsstart_new_sessiontargetdaemon)	threadingLock_lock_seqstderr_tailqueueQueuestdout_queuer;   
executable_closedhermes_cli._subprocess_compatr   r   r6   
subprocessPopenPIPEr,   getcwdprocThread_drain_stdoutstart_drain_stderr)r   r   r   r   argvr   r   s          rD   __init__z_SlashWorker.__init__0  s   ^^%
	&(6;kkm NN&
 Y&&DD $= "%\!2C $$//????		,."
	 	 2 24@FFH 2 24@FFHr   c                    | j                   j                  xs g D ]1  }	 | j                  j                  t	        j
                  |             3 | j                  j                  d        y # t        j                  $ r Y ew xY wr   )r   r   r   putjsonloadsJSONDecodeError)r   lines     rD   r   z_SlashWorker._drain_stdoutc  sr    II$$* 	D!!%%djj&67	
 	d# '' s   .A++B Bc                     | j                   j                  xs g D ].  }|j                  d      x}s| j                  |gz   dd  | _        0 y )N
i)r   r<   rstripr   )r   r   r   s      rD   r   z_SlashWorker._drain_stderrk  sR    II$$* 	ED{{4((t($($4$4v$=st#D 	Er   commandr   c           
         | j                   j                         t        d      | j                  5  | xj                  dz  c_        | j                  }| j                   j
                  j                  t        j                  ||d      dz          | j                   j
                  j                          	 	 | j                  j                  t              }|ns|j                  d      |k7  r:|j                  d      st        |j                  d	d
            t        |j                  dd            j!                         cd d d        S t        d| j"                  r0dt%        d      j'                  | j"                  dd        z          d       # t        j                  $ r t        d      w xY w# 1 sw Y   y xY w)Nzslash worker exitedr   )idr   r   timeoutzslash worker timed outr   okerrorzslash worker failedoutputr   zslash worker closed piper%   
   i)r   pollRuntimeErrorr   r   r   r2   r   dumpsr(   r   get_SLASH_WORKER_TIMEOUT_Sr   Emptyr6   r   r   chrr*   )r   r   ridmsgs       rD   runz_SlashWorker.runp  s   99>>'455ZZ 	IINI))CIIOO!!$**CG-L"MPT"TUIIOO!!#A++//8O/PC ;774=C'wwt}&swww8M'NOO3778R0188:#	 	& *Y]YiYi4#b',,t?O?OPRPS?T2U+U*rs oq*rs  {{ A&'?@@A	 	s,   BF:8 FA,F:A
F:F77F::Gc                    t        | dd      ry d| _        | j                  }	 |j                         #|j	                          	 |j                  d       |j                  |j                  |j                  fD ]  }	 |j                           y # t        $ r6 |j                          	 |j                  d       n# t        $ r Y nw xY wY xw xY w# t        $ r6 	 |j                          |j                  d       n# t        $ r Y nw xY wY w xY w# t        $ r Y w xY w# |j                  |j                  |j                  fD ]"  }	 |j                          # t        $ r Y  w xY w w xY w)Nr   FTr   r   )getattrr   r   r   	terminater   r5   killr   r   r<   r   )r   r   streams      rD   r   z_SlashWorker.close  sV   4E*yy	yy{" IIaI(  ::t{{DKK@ LLN ! IIK		!	,$ 	  					!	$ 		 !   ::t{{DKK@ LLN  s    C B =DC*B=<C=	C	CC		CC CC 	D"C?>D?	DD
DDD# DD# 	D D #'E-EE-	E(	%E-'E(	(E-r   )
r9   r   r   r   r6   r   r   r   r   r   r   r   rD   r   r   -  sK    =1IC 1I 1I3: 1If$E
3 3 6r   r   r   c                      t               j                  d      } t        | t              si } t	        | j                  dd      xs d      j                         j                         }|dv r|S dS )Ndisplaybusy_input_moder   >   r   steer	interruptr  	_load_cfgr   
isinstancer   r6   r7   lowerr   raws     rD   _load_busy_input_moder    sa    kooi(Ggt$
gkk+R06B
7
=
=
?
E
E
GC883IkIr   c                      t               j                  d      } t        | t              syt	        | j                  dd            S )u  Return whether interim assistant commentary should be surfaced to UIs.

    Honors ``display.interim_assistant_messages`` (default true). When false,
    the tui_gateway does not install ``interim_assistant_callback``, so
    interim text from tool-call turns and verify-on-stop candidates is never
    emitted as ``message.interim`` — mirroring the messaging gateway's gating.
    r   Tinterim_assistant_messages)r  r   r  r   r   )r   s    rD    _load_interim_assistant_messagesr    s8     kooi(Ggt$7;;'CTJKKr   
event_type
session_idplatformc                 X    	 ddl m}  || |t        |             y# t        $ r Y yw xY w)z-Fire session lifecycle hooks with CLI parity.r   invoke_hook)r  r  N)hermes_cli.pluginsr  _resolve_agent_platformr5   )r  r  r  _invoke_hooks       rD   _notify_session_boundaryr    s4    	B!,X6	

  s    	))tui)surfacer   live_session_idr  c                    	 ddl m}  || |t               d|i      S # t        $ r }t        j                  d|       Y d }~yd }~ww xY w)Nr   )try_acquire_active_sessionr  )r  r  configmetadataz'Failed to claim active session slot: %sNN)hermes_cli.active_sessionsr  r  r5   loggerwarning)r   r  r  r  excs        rD   _claim_active_session_slotr"    sN    I)";'9	
 	
  @#Fs    	AAAsessionc                     | sy | j                  dd       }|y 	 |j                          y # t        $ r t        j	                  dd       Y y w xY w)Nactive_session_leasez%Failed to release active session slotTexc_info)popreleaser5   r  debug)r#  leases     rD   _release_active_session_slotr,    sR    KK.5E}M M<tLMs   +  AAsidnew_session_idc                   |sy|j                  d      }|y	 ddlm}  |||d| i      ry	 t        || t        |      
      \  }}|+|j                  dd       }|	 |j                          ||d<   y|rt        j                  d| ||       y# t        $ r t        j                  dd	       Y w xY w# t        $ r t        j                  dd	       Y iw xY w)NFr%  Tr   )transfer_active_sessionr  )r  r  z&Failed to transfer active session slotr&  r  r  z+Failed to release stale active session slotz_Compression session lease re-anchor failed (kept old lease): sid=%s new_session_id=%s reason=%s)r   r  r0  r5   r  r*  r"  _session_sourcer(  r)  r   )r-  r#  r.  r+  r0  	new_leaselimit_message	old_leases           rD   _transfer_active_session_slotr6    s    KK./E}
NF"%'-

 
  :( I}
 KK 6=	 [!!# +4&'1	
 ?  N=MN$  [JUYZ[s#   B B6  B32B36 CC>   r   acpclir  crontestlocalwebuidesktopwebhooksubagent
api_servermsgraph_webhooksourcec                     | xs dj                         j                         }|t        v ry	 ddlm}  ||       y# t
        $ r Y yw xY w)u  True when ``source`` names a messaging-gateway platform whose session
    lifecycle belongs to the gateway, not to this TUI backend.

    Structural rather than a hardcoded platform list: any source that
    resolves to a known gateway ``Platform`` (built-in enum member OR a
    registered platform plugin, via ``Platform._missing_``) counts, so new
    platforms are covered automatically.  Local/self-owned sources are
    excluded explicitly — ``local``/``webhook``/``api_server`` are Platform
    members but their sessions are not owned by a remote chat surface that
    routes by session_key, so reaping them is safe and keeps /resume clean.
    r   Fr   )PlatformT)r7   r  _NON_GATEWAY_SOURCESgateway.configrD  r5   )rB  srcrD  s      rD   _is_gateway_owned_sourcerH  1  sO     <R


 
&
&
(C
""+ s   < 	AA	tui_close
end_reasonc                    | r| j                  d      ryd| d<   t        |        | j                  d      }||j                          | j                  d      }| j                  d      }|'|5  t        | j                  dg             }ddd       nt        | j                  dg             }|-t	        |d      r!t        |d	d      }|r	 |j                  |       |N	 d
dlm	}  |dt        |dd      xs | j                  dd      ddt        |dd      t        |dd      xs d       | rt	        |d      r	 |j                  |       | j                  d      }t        |dd      xs |}	t        d|	t        |              d}
|	rT	 t               }|G|j                  |	      }|xs i j                  dd      }t        |       }
|
r|j!                  |	|       	 d
dlm} t'        | j                  d      xs d      }|s4	 t(        5  t*        j-                         D ]  \  }}|| u s|} n ddd        ||
rt'        |xs d      nd||       	 | j                  d      }|r|j/                          yy# 1 sw Y   xY w# t        $ r Y w xY w# t        $ r Y xw xY w# t        $ r Y fw xY w# t        $ r Y w xY w# 1 sw Y   xY w# t        $ r d}Y w xY w# t        $ r Y w xY w# t        $ r Y yw xY w)uk  Best-effort finalize hook + memory commit for a session.

    Fires ``on_session_end`` plugin hook and attempts to persist any
    unflushed messages before closing the session.  This mirrors the
    CLI's exit-path behaviour and prevents data loss when the TUI is
    force-quit (double Ctrl‑C, terminal‑close, SIGHUP) while the agent
    is mid‑turn.
    
_finalizedNT_notif_stopagenthistory_lockhistory_persist_session_session_messagesr   r  on_session_endr  r   r   Fr   unknownr  r  )r  	completedinterruptedr   r  commit_memory_sessionon_session_finalizerB  )interrupt_for_session_sid)r   origin_ui_session_idreasonslash_worker)r   r,  setlisthasattrr   rQ  r5   r  r  rW  r  r2  _get_dbget_sessionrH  end_sessiontools.async_delegationrY  r6   _sessions_lockrQ   itemsr   )r#  rJ  
stop_eventrN  lockrP  snapshotr  r   r  _tui_owns_lifecycledbrowrB  rY  _own_sid	_cand_sid_candworkers                      rD   _finalize_sessionrq  I  s8    gkk,/ GL )]+JKK E;;~&D 	77;;y"56G	7 	7 w{{9b12 WU,>?5"5t<&&x0 	6 "5,= 2;;}b1 eWi8 
D9BU W8O)P	''0 ++m,Kd3B{J2JPW@XY 	B~ nnZ0)26*B6*J&J#&NN:z:@w{{6*0b1# ",5OO,= "(	5 G+'0H!"" 	2EK-2.2!)	
 ^,LLN m	7 	7*  ,  		  		8  		 " "
      s   .I<J	  AJ >J) AJ9  &K% K K-K2K :K% #K4 <J		JJ	J&%J&)	J65J69	KKKK K"K% !K""K% %	K10K14	L ?L rJ  c                   | syt        | |       	 ddlm} | j                  d      x}r ||       	 | j                  d      }|t        |d      r|j                          yyy# t        $ r Y >w xY w# t        $ r Y yw xY w)a  Fully tear down a session: finalize, unregister, close agent + worker.

    Shared by ``session.close`` and the orphaned-WS-session reaper. The
    slash-worker subprocess is closed inside ``_finalize_session`` (the single
    finalize chokepoint); this still unregisters the approval notifier and
    closes the in-process agent. Idempotent: the ``_finalized`` guard in
    ``_finalize_session`` and the ``poll()`` guard in ``_SlashWorker.close``
    make repeat calls harmless.
    Nrr  r   unregister_gateway_notifyr   rN  r   )rq  tools.approvalru  r   r5   r`  r   )r#  rJ  ru  keyrN  s        rD   _teardown_sessionrx    s     g*5<++m,,3,%c*G$!8KKM "9	    s"   !A& /A5 &	A21A25	B Bc                     t         5  t        j                  |       |u r||d<   	 ddd       y	 ddd       |j                          y# 1 sw Y   xY w)u   Store worker on session iff sid still maps to it, else close it — a
    concurrent teardown already popped the session and would orphan the
    worker. Closes the create/close race at every slash-worker spawn site.r]  N)re  rQ   r   r   )r-  r#  rp  s      rD   _attach_workerrz    sR     
 ==(&,GN# ( LLN	 s   AAc                 x    t         5  t        j                  | d      }ddd       y| |d<   |S # 1 sw Y   xY w)a  Atomically detach one live session from the registry.

    Detaching is the ownership claim for teardown: once the record is no
    longer in ``_sessions``, a concurrent close/reaper becomes a no-op.  Keep
    this operation separate from ``_teardown_session`` because finalization can
    flush SQLite state, invoke plugins, commit memory, interrupt delegations,
    and close agents/workers.  None of that slow external work belongs under
    the global ``_session_resume_lock``.
    NrZ  )re  rQ   r(  )r-  r#  s     rD   _pop_session_by_idr|    sD     
 +--T*+ GFON+ +s   09c                $    | yt        | |       y)zDFinish a close after the caller has atomically detached the session.Frr  T)rx  )r#  rJ  s     rD   _teardown_popped_sessionr~    s     g*5r   c                .    t        t        |       |      S )a}  Single idempotent teardown funnel for callers needing no resume race.

    Resume-sensitive callers first pop under ``_session_resume_lock`` and then
    call ``_teardown_popped_session`` after releasing it.  Other reapers can use
    this convenience wrapper directly.  The pop remains the single atomic
    ownership claim, so concurrent/repeat close attempts stay harmless.
    rr  )r~  r|  )r-  rJ  s     rD   _close_session_by_idr  #  s     $3J r   c                 |    | r| j                  d      ry| j                  d      ry| j                  d      t        u S )a  True if a WS session has no live transport and no in-flight turn.

    After ``handle_ws`` detaches a disconnected client it points the session at
    ``_detached_ws_transport``. A session left on that transport (and not
    mid-turn) is genuinely orphaned and safe to reap.
    rL  Frunning	transport)r   _detached_ws_transportr#  s    rD   _ws_session_is_orphanedr  0  s9     gkk,/{{9;;{#'===r   c                      t         dk  ryd fd}t        j                  t         |      }d|_        |j	                          y)a+  After a grace window, reap session ``sid`` iff it's still orphaned.

    Called from the WS-disconnect path. The grace window lets a transient
    reconnect (or a ``session.resume`` that reattaches the transport) cancel
    the reap by re-binding a live transport. Disabled when the grace is 0.
    r   Nc                      t         5  t        t        j                              s
	 d d d        y t	              } d d d        t         d       y # 1 sw Y   xY w)Nws_orphan_reaprr  )_session_resume_lockr  rQ   r   r|  r~  r#  r-  s    rD   _reapz'_schedule_ws_orphan_reap.<locals>._reapH  sT     " 	.*9==+=>	. 	. )-G	. 	!5EF		. 	.s    AAATr   )_WS_ORPHAN_REAP_GRACE_Sr   Timerr   r   )r-  r  timers   `  rD   _schedule_ws_orphan_reapr  >  s9     !#G" OO3U;EEL	KKMr   ws_disconnectc                z   t         5  t        j                         D cg c]  \  }}|j                  d      | u s||f }}}ddd       d}d}D ]C  \  }}|j                  d      rt	        ||       |dz  }*t
        |d<   |dz  }	 t        |       E ||fS c c}}w # 1 sw Y   _xY w# t        $ r Y gw xY w)u  On transport disconnect, reap the sessions that opted into
    close_on_disconnect (sidecar/dashboard) immediately via the unified
    ``_close_session_by_id`` path, and re-point the rest back to stdio so later
    emits don't hit a dead socket.

    Non-flagged detached sessions are handed to the grace-windowed WS-orphan
    reaper (``_schedule_ws_orphan_reap``): a quick reconnect / session.resume
    that re-binds a live transport cancels the reap, otherwise the orphan is
    torn down through the same idempotent ``_teardown_session`` path. This is
    the single WS-disconnect teardown entry point — there is no second
    independent reap loop in ``handle_ws``.

    Returns ``(reaped, detached)`` counts for disconnect-path observability.r  Nr   close_on_disconnectrr  r   )re  rQ   rf  r   r  r  r  r5   )r  rJ  r-  sownedreapeddetachedr#  s           rD   _close_sessions_for_transportr  ^  s      
 ^(1(9]fc1QUU;=OS\=\#q]]^FH W;;,- <aKF
 $:GK MH(- 8# ^^ ^   s3   B"BBB"B.B""B+.	B:9B:c                      t         5  t        t              } d d d         D ]  }t        |d        y # 1 sw Y   xY w)Ntui_shutdownrr  )re  r_  rQ   r  )sidsr-  s     rD   _shutdown_sessionsr    s<    	 I =S^<= s   4=HERMES_TUI_SESSION_TTL_Si`T  g     r@c                 2    | t         u ryt        | dd       du S )NTr   )r  r   )r  s    rD   _transport_is_deadr    s$    
 **9i.$66r   nowc                    |j                  d      st        |       ry|j                  d      }|"|j                         s|j                  d      syt        |j                  d            syt	        |j                  d      xs d      }t	        |j                  d      xs d      }||z
  t
        kD  xr ||z
  t
        kD  S )	Nr  Fagent_readylazyr  last_activer]   
created_at)r   _session_pending_kindis_setr  float_SESSION_TTL_S)r-  r#  r  readyr  r  s         rD   _session_is_evictabler    s    {{9!6s!;KK&E F8Kgkk+67M29c:Kw{{<07C8J+/WS:5E4WWr   c            
         t        j                          } t        5  t        j                         D cg c]  \  }}t	        |||       s| }}}d d d        D ]  }t        |d        t                y c c}}w # 1 sw Y   .xY w)Nidle_timeoutrr  )r3   re  rQ   rf  r  r  _enforce_session_cap)r  r-  r  victimss       rD   _reap_idle_sessionsr    s{    
))+C	 ^%.__%6]63:OPSUVX[:\3]]^ =S^<= ^^ ^s"   A=A7	A7A=7A==Bc                     	 ddl m}  t               xs i }|j                  d      }|2|j                  d      }t	        |t
              r|j                  d      } | |d      }|rt        |      S dS # t        $ r Y yw xY w)Nr   )coerce_max_concurrent_sessionsmax_live_sessionsgatewayrw  )r  r  r  r   r  r   intr5   )r  cfgr  gateway_cfgcoerceds        rD   _max_live_sessionsr    s    MkRgg)*;''),K+t,!oo&9:0:MN&s7|-A- s   A/A4 2A4 4	B ?B c                     |j                  d      st        |       ry|j                  d      }|"|j                         s|j                  d      syt        |j                  d            S )Nr  Fr  r  r  )r   r  r  r  r-  r#  r  s      rD   _session_is_lru_evictabler    sY     {{9!6s!;KK&EF8Kgkk+677r   c            	      p   t               } | dk  ry t        5  t        t              }|| k  r
	 d d d        y t        j	                         D cg c]  \  }}t        ||      s||f }}}d d d        j                  d        | z
  }|d | D ]  \  }}t        |d        y c c}}w # 1 sw Y   BxY w)Nr   c                 D    t        | d   j                  d      xs d      S )Nr   r  r]   )r  r   )kvs    rD   r   z&_enforce_session_cap.<locals>.<lambda>  s    %1		-(@(GC"H r   r  	lru_evictrr  )r  re  lenrQ   rf  r  sortr  )captotalr-  r  	evictableoverflow_ss          rD   r  r    s    

C
ax	 
IC<
 

 $-??#4
a8QRUWX8YS!H
	 
	
 NNHNIs{HYh' :RS[9:
	
 
s(   B,B,B&"B&(B,&B,,B5c                  d    d } t        j                  d|       }d|_        |j                          y)zHRun the LRU sweep off the response path (eviction can call agent.close).c                  f    	 t                y # t        $ r t        j                  dd       Y y w xY w)Nzsession cap enforcement failedTr&  )r  r5   r  r*  r   r   rD   _runz/_schedule_session_cap_enforcement.<locals>._run  s0    	J " 	JLL9DLI	Js   
  00皙?TNr   r  r   r   )r  r  s     rD   !_schedule_session_cap_enforcementr    s*    J OOC&EEL	KKMr   c                  T    d } t        j                  | d      j                          y )Nc                  l    	 t        j                  t               	 t                %# t        $ r Y w xY wr   )r3   sleep_REAPER_SCAN_Sr  r5   r   r   rD   _loopz!_start_idle_reaper.<locals>._loop  s5    JJ~&#%   s   
' 	33Tr   )r   r   r   )r  s    rD   _start_idle_reaperr    s"     E$/557r   c                      t         ddlm}  	  |        a d at         S t         S # t        $ r+}t        |      at        j                  d|       Y d }~y d }~ww xY w)Nr   	SessionDBuJ   TUI session store unavailable — continuing without state.db features: %s)_dbhermes_stater  rV   r5   r6   r  r   )r  r!  s     rD   ra  ra    sX    
{*		+CI J3J  	CINN\ 	s   	# 	A!AAcodec                6    t         xs d}t        | |d|       S )Nzstate.db unavailablezstate.db unavailable: )rV   _err)r   r  details      rD   _db_unavailable_errorr  !  s$    00FT3F8<==r   profilec                 <   | xs dj                         }|sy	 ddlm} t        |j	                  |            }|j                         t        t              j                         k(  ry|dz  j                         s|j                         r|S dS # t
        $ r Y yw xY w)zLResolve a named profile's home on THIS host, or None for the launch profile.r   Nr   )profilesstate.db)	r7   
hermes_clir  r   get_profile_dirr5   resolve_hermes_homeexists)r  rI   profiles_modhomes       rD   _profile_homer  .  s    Mr  "D7L0067 ||~l+3355:%--/4;;=4JdJ  s    B 	BBc                       fd}|S )a  Bind ``params['profile']``'s HERMES_HOME around a pet RPC handler.

    Pets are per-profile: ``display.pet.*`` lives in the profile's config.yaml and
    sprites install under its ``pets/`` dir (both resolve via ``get_hermes_home``).
    The desktop sends ``profile`` on pet calls so config + pets dir resolve to the
    focused profile even in app-global remote mode, where one backend serves every
    profile. No-op for the launch profile (own-profile backends already resolve it).
    c                     t        t        |t              r|j                  d      nd       }|	 | |      S t	        |      }	  | |      t        |       S # t        |       w xY w)Nr  )r  r  r   r   r   r   )r   paramsr  tokenhandlers       rD   wrapperz _profile_scoped.<locals>.wrapperI  s_    j6NVZZ	2TXY<3''(.	.3'&u-&u-s   A A&r   )r  r  s   ` rD   _profile_scopedr  ?  s    . Nr   >   r   auto.r  c                    t        | t              sy| j                  d      }t        |t              syt        |j                  d      xs d      j	                         }|r|t
        v ryt        j                  j                  t        j                  j                  |            }t        j                  j                  |      r|S dS )zReturn an absolute, existing ``terminal.cwd`` from a config mapping.

    Returns None for placeholders (``.``/``auto``/``cwd``), missing values, or
    paths that don't resolve to a real directory.
    Nterminalr   r   )r  r   r   r6   r7   _CWD_PLACEHOLDERSr,   r.   abspath
expanduserisdir)r  terminal_cfgr  resolveds       rD   _configured_cwd_from_cfgr  \  s     c4 77:&LlD)
lu%+
,
2
2
4C#**wwrww11#67Hww}}X.88D8r   r   c                     | y	 ddl }t        |       dz  }|j                         syt        |d      5 }|j	                  |      xs i }ddd       t              S # 1 sw Y   xY w# t        $ r Y yw xY w)a  Resolve a non-launch profile's ``terminal.cwd`` from its own config.yaml.

    The desktop's app-global remote mode serves every profile from one backend,
    so the process-global ``TERMINAL_CWD`` belongs to the *launch* profile. A new
    session bound to another profile must take its workspace from THAT profile's
    config, not the stale env var (issue #40334). Returns an absolute, existing
    directory, or None for placeholders / missing / invalid paths.
    Nr   config.yamlr    r!   )yamlr   r  r1   	safe_loadr  r5   )r   r  prB   datas        rD   _profile_configured_cwdr  n  s     
.xxz!g& 	+!>>!$*D	+'--	+ 	+  s-   "A* A* AA* A'#A* *	A65A6c                  H    	 t        t                     S # t        $ r Y yw xY w)u3  Resolve the launch profile's ``terminal.cwd`` from config.yaml.

    Dashboard ``/chat`` for the launch profile attaches to the dashboard
    process's in-memory TUI gateway. The Node PTY child receives a bridged
    ``TERMINAL_CWD`` env var, but this in-memory process does not — so reading
    the process env alone leaves a fresh chat starting in ``os.getcwd()``
    (wherever ``hermes dashboard`` was launched) instead of the configured
    ``terminal.cwd``. Read config directly so changing ``terminal.cwd`` affects
    new in-memory TUI sessions too.
    N)r  r  r5   r   r   rD   _launch_configured_cwdr    s&    '	44 s    	!!c                  p    t               xs+ t        j                  d      xs t        j                         S )aO  Fallback cwd for a session with no explicit / stored / profile cwd.

    Mirrors the launch-config-aware tail of :func:`_completion_cwd` so freshly
    created AND resumed sessions land in the configured ``terminal.cwd`` rather
    than ``os.getcwd()`` when the in-memory gateway's process env has no bridged
    ``TERMINAL_CWD``.
    TERMINAL_CWD)r  r,   getenvr   r   r   rD   _default_session_cwdr	    s&     "#Oryy'@OBIIKOr   r   c                 6   | j                  d      dk(  re| j                  d      xs i j                  d      xs d}|r;t        j                  |      xs i j                  d      x}|j                  |       S t               xs t        j                  |       S )uA  Emit one JSON frame. Routes via the most-specific transport available.

    Precedence:

    1. Event frames with a session id → the transport stored on that session,
       so async events land with the client that owns the session even if
       the emitting thread has no contextvar binding.
    2. Otherwise the transport bound on the current context (set by
       :func:`dispatch` for the lifetime of a request).
    3. Otherwise the module-level stdio transport, matching the historical
       behaviour and keeping tests that monkey-patch ``_real_stdout`` green.
    methodeventr  r  r   r  )r   rQ   r2   r   _stdio_transport)r   r-  ts      rD   
write_jsonr    s     wwxG#!'R,,\:Ar)--,277DDAQ773<3#3::3??r   r  payloadc                 :    | |d}|||d<   t        dd|d       y )N)typer  r  2.0r  )jsonrpcr  r  )r  )r  r-  r  r  s       rD   _emitr    s+    3/F#y5GvFGr   c                  F    t         j                  j                  d      dk(  S )NHERMES_COMPUTE_HOST_CHILD1)r,   environr   r   r   rD   _inside_compute_host_childr    s    ::>>56#==r   c                 h    t               ry| xs
 t               }t        |j                  d            S )NFturn_isolation)r  (_load_dashboard_process_isolation_configr   r   )r  isolation_cfgs     rD   _turn_isolation_enabledr    s0    !#ECEM!!"2344r   c                     t        |      syt        | j                  d            xs( | j                  d      d u xr | j                  d      d uS )NF_compute_host_activerN  r  )r  r   r   )r#  r  s     rD   _session_uses_compute_hostr"    sO    "3' 234 G$O])C4)Or   c           
         | xs
 t               }t        5  t        Mddlm}  |t
        t        |j                  d      xs d      t        |j                  d      xs d            at        cd d d        S # 1 sw Y   y xY w)Nr   )HostSupervisorcompute_host_heartbeat_secs   compute_host_respawn_max   )rpc_sinkheartbeat_secsrespawn_max)r  _compute_host_supervisor_lock_compute_host_supervisortui_gateway.host_supervisorr$  r  r  r   )r  r  r$  s      rD   _get_compute_host_supervisorr/    sx    ECEM	& 	(#+B'5#"=#4#45R#S#YWYZ 1 12L M RQRS($
 (	( 	( 	(s   AA88Br   r   c                     |d   5  t        |j                  dg             }t        |j                  dd            }t        |j                  dg             }d d d        d|| |j                  d      xs ||t        |j                  dd	      xs d	      t        |      |j                  d
      xs d|j                  d      |j                  d      |j                  d      t	        |      dS # 1 sw Y   xY w)NrO  rP  history_versionr   attached_imagesz
turn.startr   colsP   r   r   model_overridecreate_reasoning_overridecreate_service_tier_override)r  r-  
request_idr   r   rP  r1  r3  r   r   r5  reasoning_config_overrideservice_tier_overriderB  r2  )r_  r   r  _session_cwdr2  )r   r-  r#  r   rP  r1  r2  s          rD   _compute_host_turn_framer<    s    		  Cw{{9b12gkk*;Q?@w{{+<bABC
 {{=18S*GKK+1r2G$N39r!++&67%,[[1L%M!(-K!L!'** 	C Cs   AC44C=c                 T    | xs i j                  d      }t        |t              r|S i S )N_metadata_mirror)r   r  r   )r#  mirrors     rD   r>  r>    s+    m  !34F-6525r   framec           	         t        |t              sy| j                  dt        j                               5  |j                  d      rt        |j                  d            | d<   |j                  d      E	 t        t        | j                  dd            t        |j                  d      xs d            | d<   |j                  d      "	 t        |j                  d      xs d      | d<   ddd       |j                  d      }t        |t              rBt        t        |             }|j                  |       || d	<   t        j                         | d
<   yy# t        $ r Y w xY w# t        $ r Y w xY w# 1 sw Y   xY w)a%  Mirror host-owned session metadata in the serving process.

    The compute host is the only writer of live agent/history state while turn
    isolation is active. The serving process keeps read metadata from the last
    host frame so UI reads do not construct a second in-process agent.
    NrO  r   r1  r   message_count_metadata_message_countsession_infor>  _metadata_mirror_updated_at)r  r   r   r   r   r6   maxr  r5   r>  updater3   )r#  r@  infor?  s       rD   #_apply_compute_host_metadata_mirrorrI    sb    eT"	^Y^^%5	6 99]#%(=)A%BGM"99&'3-0$5q9:		"349:.)* 99_%158?9S9XWX5Y12  99^$D$&w/0d&,"#15-.	   
   sO   A E87AE;E8!E)	E&#E8%E&&E8)	E52E84E55E88Fc           	      2   |j                  d      dk(  }|d   5  |j                  d      rt        |j                  d            |d<   |j                  d      E	 t        t        |j                  dd            t        |j                  d      xs d            |d<   d|d<   t        j
                         |d	<   t        |       d d d        |r1t        |j                  d
      xs d      }t        d|d| dd       t        ||       	 t        |j                  d      |      }|j                  d      st        d||       t        | ||       y # t        $ r Y w xY w# 1 sw Y   xY w# t        $ r t        |j                  d            }Y lw xY w)Nr  z
turn.errorrO  r   r1  r   Fr  r  messagezcompute host turn failedmessage.completeError: r   )r   statusrN  session_info_emittedsession.info)r   r6   rF  r  r5   r3   _clear_inflight_turnr  rI  _session_info	TypeError_drain_queued_prompt)r   r-  r#  r@  is_errorrK  rH  s          rD   _on_compute_host_turn_donerV  %  s   yy L0H		  &99]#%(=)A%BGM"99&'3-0$5q9:		"349:.)* #	!%W%& eii	*H.HI #''0Cw'WX'73W[[17; 99+,nc4(c7+  & &(  3W[[123sC   A E$AE'E$E0 	E!E$ E!!E$$E-0#FFc                 D    t               }t         |      }dt        dd f fd}	 t        |      j	                  ||       d   5  dd	<   g d
<   d d d        t         ddd      S # t
        $ r}t         dd|       cY d }~S d }~ww xY w# 1 sw Y   >xY w)Ndoner   c                 L    | j                  d      dk(  ry t        |        y )Nr\  send_failed)r   rV  )rX  r   r#  r-  s    rD   	_completez1_submit_prompt_to_compute_host.<locals>._completeF  s'    
 88H."3Wd;r   )on_complete  zcompute-host dispatch failed: rO  Tr!  r2  	streamingrN  r  )r  r<  r   r/  submit_turnr5   r  _ok)r   r-  r#  r   r  r@  r[  r!  s   ```     rD   _submit_prompt_to_compute_hostrb  B  s    
2
4C$S#w=E< < <G$S)55e5S 
	  (*.&'%'!"( s{dCDD  GC!?uEFFG( (s)   A0 B0	B9BBBBr   T)r   r  r   
route_namer   r   c                    t        |xs i       }|j                  dd       |j                  d|       t               j                  | |||      S )Nr  controlr   )rc  r  r   )r   
setdefaultr/  re  )r-  rc  r   r  r   r@  s         rD   _send_compute_host_controlrg  Y  sY     BE	VY'	Y(')11	 2  r   r  c                 
   t        |xs i       }d|vr?|j                  d      rddg|d<   n&|j                  d      du rg d|d<   nd|v rg d|d<   d	|v r d
dlm}  ||j                  d	            |d	<   t	        d| |       y)u  Emit an ``approval.request`` event to the TUI client with the command
    redacted. The approval payload is built from the RAW command string, so a
    credential-shaped value Tirith flagged would otherwise be echoed verbatim
    to the TUI client (#48456 — third egress transport alongside the chat
    platforms and the SSE/API stream fixed in #50767). Reuse the shared gateway
    seam so all approval transports redact consistently.choicessmart_deniedoncedenyallow_permanentF)rk  r#  rl  )rk  r#  alwaysrl  r   r   )_redact_approval_commandzapproval.requestN)r   r   gateway.runro  r  )r-  r  r  ro  s       rD   _emit_approval_requestrq  l  s     4:2G;;~&"(&!1GI[[*+u4!<GI')!FGIG85gkk)6LM		
c7+r   kindc                     ||n|j                         }|sy ||nd}|dk(  rddlm} ||v rd}t        d| ||d       y )NrN  	lifecycler   )COMPACTION_STATUS_MARKER
compactingstatus.updaterr  r   )r7   agent.conversation_compressionru  r  )r-  rr  r   bodyout_kindru  s         rD   _status_updater|    sT    $D$557D'tXH ;K#t+#H	/34 @Ar   widthheightc                 h    | dk  s|dk  ryt        d| dz   dz        t        d|dz   dz        z  dz  S )zVery rough UI estimate for image prompt cost.

    Uses 512px tiles at ~85 tokens/tile as a lightweight cross-provider hint.
    This is intentionally approximate and only used for attachment display.
    r   r   i  i   U   )rF  )r}  r~  s     rD   _estimate_image_tokensr    sD     zVq[q53;3&'#a&3,31F*GG"LLr   r.   c                 4   d| j                   i}	 ddlm} |j                  |       5 }|j                  \  }}d d d        t              |d<   t              |d<   t        t        |      t        |            |d<   |S # 1 sw Y   HxY w# t        $ r Y |S w xY w)NrI   r   Imager}  r~  token_estimate)rI   PILr  r1   sizer  r  r5   )r.   metar  imgr}  r~  s         rD   _image_metar    s    DIID	ZZ 	%HHME6	%E
WVX!7E
CK!P K	% 	%
  Ks(   B
 A>AB
 >BB
 
	BBresultc                     d| |dS )Nr  )r  r   r  r   )r   r  s     rD   ra  ra    s    C6::r   r   c                     d| ||ddS )Nr  )r  rK  )r  r   r   r   )r   r  r   s      rD   r  r    s    C4C2PQQr   rI   c                       fd}|S )Nc                     | t         <   | S r   )rR   )fnrI   s    rD   deczmethod.<locals>.dec  s    	r   r   )rI   r  s   ` rD   r  r    s     Jr   reqc                 0   t        | t              st        ddd      S | j                  d      }| j                  d      }t        |t              r|st        |dd      S | j                  di       }|i }nt        |t              st        |dd	      S |||fS )
z;Validate a JSON-RPC request enough for safe local dispatch.Niz#invalid request: expected an objectr   r  z2invalid request: method must be a non-empty stringr  iz"invalid params: expected an object)r  r   r  r   r6   )r  r   r  r  s       rD   _normalize_requestr    s    c4 D&"GHH
''$-CWWXFfc"&C!UVVWWXr"F~%C!EFFr   c                     t        |       }t        |t              r|S |\  }}}t        j	                  |      }|st        |dd|       S  |||      S )Nizunknown method: )r  r  r   rR   r   r  )r  
normalizedr   r  r  r  s         rD   handle_requestr    s\    #C(J*d#$C	f	BC#3F8!<==c6?r   r  c                 n   	 |xs t         	t        	      }	 t               }t        |t              r|t        |       S |\  }}}|t        vrt               t        |       S t        j                          	fdt        j                  fd       	 t        |       y# t        |       w xY w)u  Route inbound RPCs — long handlers to the pool, everything else inline.

    Returns a response dict when handled inline. Returns None when the
    handler was scheduled on the pool; the worker writes its own response
    via the bound transport when done.

    *transport* (optional): pins every write produced by this request —
    including any events emitted by the handler — to the given transport.
    Omitting it falls back to the module-level stdio transport, preserving
    the original behaviour for ``tui_gateway.entry``.
    c                      	 t              } | j	                  |        y y # t        $ r)}t        j                  d      dd|       } Y d }~Bd }~ww xY w)Nr   i zhandler error: )r  r5   r  r   r2   )respr!  r  r  s     rD   r   zdispatch.<locals>.run  s\    L%c*     LCGGDM6_SE3JKLs   # 	AAAc                  &     j                        S r   )r   )ctxr   s   rD   r   zdispatch.<locals>.<lambda>  s    SWWS\ r   N)r  r   r  r  r   r   _LONG_HANDLERSr  contextvarscopy_contextr   submit)
r  r  r  r  _ridr  _paramsr  r   r  s
   `      @@@rD   dispatchr    s     	%%A1E',
j$'* 	' !+fg'!#&" 	 &&(	 	)*s   B' B' '3B' 'B4r   c                     | j                  d      }||j                  |      st        |dd      S | j                  d      }|rt        |d|      S d S )Nr  r     zagent initialization timed outagent_error)r   r   r  )r#  r   r   r  errs        rD   _wait_agentr    sW    KK&EG!<C?@@
++m
$C#&4T30D0r   c                     |j                  d      y|j                  d      r(t        t        |j                  d      xs d            ry|j                  dt	        j
                               }|5  j                         s|j                  d      r
	 ddd       yd|d<   |j                  dd       ddd       |d   d fd	}t	        j                  |d
      j                          y# 1 sw Y   <xY w)a  Start building the real AIAgent for a TUI session, once.

    Classic `hermes` shows the prompt before constructing AIAgent; the TUI used
    to eagerly build it during session.create, making startup feel blocked on
    tool discovery/model metadata even though the composer was visible.  Keep
    the shell responsive by deferring this work until the first prompt (or any
    command that actually needs the agent), while retaining the same ready/error
    event contract for the frontend.
    r  Nr  r   r   agent_build_lockagent_build_startedTc            	      H   t         5  t        j                        } d d d         j                          y d }d}d }| j                  d      }	 t	              }d }|r't        |      }	 ddlm}  |t        |      dz        }	 d|i}| j                  d      x}	r|	|d	<   t        |       |d
<   | j                  d      }
t        |
t              r|
r|j                  |
       nH| j                  d      x}r||d<   | j                  d      x}||d<   | j                  d      x}||d<   t        fi |}t        |       || d<   t!               | d<   	 t#        t%        |dt'                     | j                  d            }t)        | |       	 ddlm}m}  |fd       d} |        t1               	 fd|_        t5               |_        	 ddlm}  ||       t         5  t        v rt=        t                 t           d<   d d d        t?        dt        |              tA        ||       }tC        tE                     }|r||d<   tF        jI                  |       tK        d|       tM        |       |tQ        |       t         5  t        j                        | u}d d d        r|r	 dd"lm)}  |       j                          y # 1 sw Y   xY w# t        $ r d }Y rw xY w# t        |       w xY w# t        $ r Y w xY w# t        $ r Y tw xY w# t        $ r Y _w xY w# t        $ r Y `w xY w# 1 sw Y   :xY w# t        $ r+}tO        |      | d<   tK        dd d!| i       Y d }~d }~ww xY w# 1 sw Y   xY w# t        $ r Y w xY w# |tQ        |       t         5  t        j                        | u}d d d        n# 1 sw Y   nxY wr!|r	 dd"lm)}  |       n# t        $ r Y nw xY wj                          w xY w)#NFr   r   r  r  db_path
session_dbresume_session_idr  platform_overrideresume_runtime_overridesr5  r6  r9  r7  r:  rN  config_model_seenr   r   register_gateway_notifyload_permanent_allowlistc                     t        |       S r   rq  r  r-  s    rD   r   z4_start_agent_build.<locals>._build.<locals>.<lambda>z  s    &<S$&G r   Tc                 2    t        d|dt        |       i      S Nzreview.summaryr   r  r6   rK  rZ  s     rD   r   z4_start_agent_build.<locals>._build.<locals>.<lambda>  s    U$dVS\,BN r   )seed_credits_at_session_startrM  on_session_resetconfig_warningrP  r  r   rK  zagent init failed: rt  )*re  rQ   r   r^  _set_session_contextr   r  r  r   r5   r2  r  r   rG  _make_agent_clear_session_context_config_model_targetr   r   _resolve_modelrz  rv  r  r  _wire_callbacksbackground_review_callback_load_memory_notificationsmemory_notificationsagent.credits_trackerr  _start_notification_pollerr  rR  _probe_config_healthr  r  r   r  _schedule_mcp_late_refreshr6   r   ru  )currentrp  notify_registered
home_tokenr   tokensr  r  kw
resume_sidresume_overridesoverride	reasoningtierrN  r  r  r  rH  cfg_warnereplacedru  rw  r  r-  s                          rD   _buildz"_start_agent_build.<locals>._build+  sd    	)mmC(G	)?IIK!
{{>2D	)#.F J5lC
&6!*43E
3R!SJ/ #J/!(-@!AA:A'1B|$*9'*B&'#*;;/I#J .5:J II./
 $+;;/?#@@x@/7+,%,[[1L%MM	Z:C67 ',J KKX6:23#C33&v.  %GG ,@+AG'(%E7N,<=!(^!<
 sGV4
 (G %)!(* C HK 40 .H-I*O-e4   d)#4NsT]^aTb4cIcN=1d %%7og>VW 0D+IK8H)1%&x(.#t,
 'sE2
 %*:6   =$==-W<=-H-c2 IIK]	) 	), ! &!%J&< 'v.         d d   	H%(VGM"'3.A!,E FGG	H= = !  %*:6   =$==-W<= = =-H-c2  IIKsc  KM ,K+ B4K= <M =L L 5M L- L= )M /&MA2M N?N K(+K:6M 9K::M =L

M 	LM LM 	L*&M )L**M -	L:6M 9L::M =	M
M 	M

M MM 	N# N	N, 	NN, N	N)(N),P! O!	P!!O*&P!2P P!	P
P!PP!r   r   )
r   _child_run_activer6   rf  r   r   r  r(  r   r   )r-  r#  rh  r  rw  r  s   `   @@rD   _start_agent_buildr    s     KK&E} {{60W[[5O5USU1VW0)..2BCD	 "<<>W[[)>?" " *.%& 	FD!" -
 COb F40668u" "s   7#C5#C55C>c                 |    t         j                  | j                  d      xs d      }|r|d fS d t        |dd      fS )Nr  r     session not found)rQ   r   r  )r  r   r  s      rD   _sess_nowaitr    s>    fjj.4"5AAt9Kd36I&JKKr   c                     t        | |      \  }}|rd |fS t        | j                  d      xs d|       |t        ||      fS )Nr  r   )r  r  r   r  )r  r   r  r  s       rD   _sessr    sI    &#&FAs
c{vzz,/52q9{1c"##r   	path_partc                 (   t         j                  j                  |       }t         j                  dk7  r_|j	                  dd      }t        |      dk\  r?|d   dk(  r7|d   dk(  r/|d   j                         rd	|d   j                          d|dd   S |S )
Nnt\/r(  r   :r   r   z/mnt/)r,   r.   r  rI   replacer  isalphar  )r  rd   r  s      rD   _normalize_completion_pathr    s    ww!!),H	ww$%%dC0

Oq 1$1$1%%':a=..01:ab>2BCCOr   r  c                    | xs i } | j                  d      xs t        j                  | j                  d      xs di       j                  d      xsf t        t        | j                  d                  xsA t	               xs5 t
        j                  j                  d      xs t        j                         }	 t
        j                  j                  t
        j                  j                  t        |                  }t
        j                  j                  |      r|S 	 t        j                         S # t        $ r Y t        j                         S w xY w)Nr   r  r   r  r  )r   rQ   r  r  r  r,   r  r   r.   r  r  r6   r  r5   )r  r  r  s      rD   _completion_cwdr    s   \rF

5 	==L17R<@@G	 #=I1F#GH		 "#	 ::>>.)	 99; 77??277#5#5c#h#?@77=="O # 99;  99;s   ;A%D6 6	EEc                    t         j                  j                  d      xs dj                         j	                         }|r|dk(  rn	 t               j                  di       }t        |t              rCt        |j                  d      xs d      j                         j	                         }|r|dk7  r|}|r|dk7  rt         j                  j                  dd      j                         }|sW	 t               j                  di       }t        |t              r,t        |j                  d      xs d      j                         }|r|dvr|S t        |       S # t        $ r Y w xY w# t        $ r d}Y /w xY w)	a  Return the cwd that terminal_tool should use for this TUI session.

    ``_completion_cwd`` validates paths on the host so file completion does not
    point at nonsense.  Non-local terminal backends are different: their cwd is
    inside the target environment, so an SSH path like /home/user/workspace may
    not exist on the local macOS host but is still the correct execution cwd.

    When ``TERMINAL_ENV`` is unset (dashboard/TUI process) the config's
    ``terminal.backend`` is consulted as a fallback so the non-local cwd
    resolution path is taken even when the dashboard entrypoint did not call
    ``apply_terminal_config_to_env`` on its own ``os.environ``.
    TERMINAL_ENVr   r;  r  backendr  r   >   r   r  r  )r,   r  r   r7   r  r  r  r   r6   r5   r;  )r#  r  r  cfg_backendr  s        rD   _terminal_task_cwdr    sI    zz~~n-3::<BBDGg(	$;??:r:L,-!,"2"29"="CDJJLRRT;'#9)G 7g%jjnn^R0668({z2>lD1l..u5;<BBDC 322J    		  s&   A-E -AE% 	E"!E"%E32E3c                 X    | r| j                  d      rt        | d         S t               S )Nr   )r   r6   r  r  s    rD   r;  r;  &  s(    7;;u%75>""r   r   c                    | xs dj                         }|rt        j                  j                  |      r|S |}t	        d      D ]M  }t        j                  j                  |      }|r||k(  r n%|}t        j                  j                  |      sM n t        j                  j                  |      s|S 	 t        |      xs t        |      }|xs |S # t        $ r d}Y w xY w)u  Resolve a session cwd that points at a now-deleted directory.

    A session anchored to a linked worktree (``<repo>/.worktrees/<name>``) keeps
    that path after the worktree is removed (branch merged, `git worktree
    remove`, etc). The literal dir is gone, so a probe of it returns nothing and
    the composer shows no branch — while the sidebar still folds the path up to
    the repo's main lane. Heal the mismatch: walk up to the first existing
    ancestor, then resolve its common git root, so a dead-worktree cwd collapses
    to the live repo root (and its real current branch).

    Only meaningful for local backends; a remote/SSH cwd may legitimately not
    exist on the host, so callers must skip healing there.
    r   @   )	r7   r,   r.   r  ranger/   _git_common_repo_root_for_cwd_git_repo_root_for_cwdr5   )r   r  probe_parentroots         rD   _heal_dead_cwdr  ,  s     9"


C"''--$
E2Y '577== 77==
,U3T7Me7T =5  s   7C C#"C#c                      t         j                  j                  d      xs dj                         j	                         } |  xs | dk(  S )Nr  r   r;  )r,   r  r   r7   r  )r  s    rD   _is_local_terminal_backendr  S  s=    zz~~n-3::<BBDG;,'W,,r   c                 T   t        |       }t               s|S t        |      }|rQ||k7  rL| J|| d<   	 t        |       5 }|"|j	                  | j                  dd      |       ddd       t        | |       |S # 1 sw Y   xY w# t        $ r t        j                  dd       Y <w xY w)a  Session cwd for display/probe surfaces, healed past deleted worktrees.

    Persists the healed value back to the session row (best-effort, local only)
    so the next load is already coherent and the sidebar lane stops showing a
    session pinned to a vanished path.
    Nr   r   r   z$failed to persist healed session cwdTr&  )
r;  r  r  _session_dbupdate_session_cwdr   r5   r  r*  _persist_session_git_meta)r#  r   healedrk  s       rD   _display_session_cwdr  X  s     w
C%'
C F&C-G$7	PW% R>))'++mR*H&QR
 	"'62MR R  	PLL?$LO	Ps(   B %A8"B 8B=B  B'&B'c                 z    | r0t        | j                  d      xs d      j                         }|r|S t               S )NrB  r   )r6   r   r7   _resolve_session_platform)r#  rB  s     rD   r2  r2  q  s7    W[[*0b1779M$&&r   c                 d    | sy 	 ddl m}  || d   dt        |       i       y # t        $ r Y y w xY w)Nr   register_task_env_overridesr   r   )tools.terminal_toolr  r  r5   )r#  r  s     rD   _register_session_cwdr  y  sA    C#M"U,>w,G$H	
  s   # 	//c           
      .   | j                  d      }|sy| j                  d      }|rddlm} 	  |t        |      dz        }d	}nt               }d}|y| j                  d      }t        |t              r|ni }t        |j                  d      xs d      j                         xs
 t               }i }dD ]'  \  }	}
|j                  |	      x}st        |      ||
<   ) t        |j                  d      xs d      j                         j                         dk(  r*	 ddlm}  ||j                  d      xs d      }|r||d<   | j                  d      x}||d<   | j                  d      }|	|xs d|d<   | j                  d      xs d}|r||d<   	 |j!                  |t#        |       ||xs d|| j                  d      rt%        |       nd       |r	 |j'                          yy# t        $ r t
        j                  dd	
       Y yw xY w# t        $ r t
        j                  dd	
       Y w xY w# t        $ r t
        j                  dd	
       Y w xY w# t        $ r Y yw xY w# |r!	 |j'                          w # t        $ r Y w w xY ww xY w) u
  Idempotently persist the session's DB row on first real activity.

    Called from prompt.submit so a row only exists once the user actually sends
    a message — abandoned drafts never leave an empty "Untitled" session behind.
    Uses INSERT OR IGNORE under the hood, so re-calls (and the AIAgent's own
    lazy create) are no-ops.

    Only an *explicitly chosen* workspace is persisted as the session's cwd.
    The agent still runs in the auto-detected directory (session["cwd"]), but
    we don't stamp that onto the row — otherwise every session the user never
    picked a folder for gets grouped under whatever directory the desktop
    happened to launch in (e.g. "desktop"). Leaving it null groups them under
    "No workspace", which is the desired default.
    r   Nr   r   r  r  r  z)failed to open profile db for session rowTr&  Fr5  r   r   ))r   r   )providerr  )base_urlr  )api_moder  r  customcanonical_custom_identityr  r  z1custom provider identity recovery failed (db row)r6  reasoning_configr7  normalservice_tierparent_session_id_branched_fromexplicit_cwdrB  r   model_configr  r   z%failed to persist desktop session row)r   r  r  r   r5   r  r*  ra  r  r   r6   r7   r  r  hermes_cli.runtime_providerr  create_sessionr2  r;  r   )r#  rw  r   r  rk  close_dbr  	row_modelr  src_keycfg_keyvalr  r  r  r7  r  s                    rD   _ensure_session_db_rowr&    s    ++m
$C ;;~.L*	4#5
#BCB Y	z {{+,H%h5x2HHLL)/R0668LN<LIL - ,,w''3'$'HL!-  <J'-2.446<<>(J	M.%))*5=F +1Z(
 [[!<==	J+4'(#*;;/M#N #/
 (D'Ox^$  $78@D):%&
"7+%-/)0^)DW%$ 	 	
 
 _  	LLDtLT	`  	LLCd  	8  M<tLM   
  s~   G. )H A H: I  . HH H76H7: II/ II/  	I,+I,/J3JJ	JJJJc           	      0   | j                  d      r| j                  d      ry| j                  d      }|sy| d   5  | j                  d      xs g D cg c]  }t        |       }}ddd       syt        |       5 }|
	 ddd       y	 |D ]5  }|j                  ||j                  dd      |j                  d	      
       7 d| d<   ddd       yc c}w # 1 sw Y   rxY w# t        $ r t
        j                  dd       Y <w xY w# 1 sw Y   yxY w)a  First-turn persist of a branch's copied transcript.

    A branch is a draft until its first submit: the parent's messages live only
    in ``session["history"]`` (they ride into the agent as ``conversation_history``,
    which ``_flush_messages_to_session_db`` skips by identity). Without this the
    branch row would resume missing its pre-branch context. Runs once; the row +
    parent link are written by ``_ensure_session_db_row`` just before this.
    r  _branch_seed_persistedNr   rO  rP  roleusercontentr  r)  r+  Tzbranch seed persist failedr&  )r   r   r  append_messager5   r  r*  )r#  rw  r   seedrk  s        rD   _persist_branch_seedr/    s5    ;;*+w{{;S/T
++m
$C		  E&-kk)&<&BDcS	DDE	W	 F:F F	F l!!Sswwvv7NX[X_X_`iXj!kl04G,-F F EE E  	FLL5LE	FF FsG   CC'C?D?C&CC#& D	DD		DDc              #     K   d\  }}| j                  d      }|rddlm} 	  |t        |      dz        d}}n
t               }	 | |r6|3t        j                  t              5  |j                          d
d
d
       y
y
y
# t        $ r t
        j                  dd	       Y `w xY w# 1 sw Y   y
xY w# |rB|?t        j                  t              5  |j                          d
d
d
       w # 1 sw Y   w xY ww w xY ww)aU  Yield the SessionDB that owns this session's row (profile-aware).

    Mirrors :func:`_ensure_session_db_row`: a remote/profile session persists
    into its own profile's ``state.db`` (a fresh handle we close on exit);
    everything else borrows the shared ``_get_db()`` handle (left open). Yields
    None when the db is unavailable.
    r   r   r   r  r  r  Tz%failed to open profile db for sessionr&  N)r   r  r  r   r5   r  r*  ra  
contextlibsuppressr   )r#  rk  r!  r   r  s        rD   r  r    s      LB;;~.L*	Q$T,-?*-LMtB Y$$Y/ 
  '8  	QLL@4LP	Q  $$Y/ 
   '8so   C=B C=B4 	C=&B(7C= B%"C=$B%%C=(B1-C=4C:C,#	C:,C51	C::C=c                     | j                  dd      rsy| j                  d      dd
fd}t        j                  |dd	      j                          y)a  Resolve + persist a session's git branch / repo root WITHOUT blocking.

    Branch and root come from ``git`` subprocess probes; running them inline on
    the session-init / cwd-set path would stall startup whenever ``cwd`` is slow
    or on an unreachable mount. Run them on a short-lived daemon thread instead
    and persist via the same profile-aware db the caller writes ``cwd`` to.

    Best-effort: ``cwd`` itself is persisted synchronously by the caller, so a
    probe failure just leaves these enrichment columns unset (the project tree
    falls back to its live resolver / lazy backfill). Daemon, so a mid-flight
    probe never delays gateway shutdown.
    r   r   Nr   )r   r   c                      	 t              } t              }| s|sy t              5 }||j                  | |       d d d        y # 1 sw Y   y xY w# t        $ r t
        j                  dd       Y y w xY w)Nz&failed to persist session git metadataTr&  )_git_branch_for_cwdr  r  r  r5   r  r*  )branchr  rk  r   
db_sessionr   s      rD   r  z'_persist_session_git_meta.<locals>._runD  s    		R(-F05DdZ( JB>))+sFDIJ J J  	RLLADLQ	Rs3   A A A	 A 	AA A  A87A8zgit-metaTr   rI   r   r   )r   r   r   r   )r#  r   r  r7  r   s    ` @@rD   r  r  0  sU     ++mR0Kc "-gkk.>YZJ
R Dz$?EEGr   c                 b   ddl m}  |t        |            }t        j                  j                  t        j                  j                  |            }t        j                  j                  |      st        d|       || d<   d| d<   t        |        t        |       5 }|#	 |j                  | j                  dd      |       d d d        t!        | |       	 ddlm}  || d          |S # t        $ r t        j                  d	d
       Y Jw xY w# 1 sw Y   OxY w# t        $ r Y |S w xY w)Nr   )translate_cwd_for_wsl_backend"working directory does not exist: r   Tr  r   r   zfailed to persist session cwdr&  )
cleanup_vm)hermes_constantsr:  r6   r,   r.   r  r  r  
ValueErrorr  r  r  r   r5   r  r*  r  r  r<  )r#  r   r:  r  rk  r<  s         rD   _set_session_cwdr?  S  s!   >
'C
1Cwwrww11#67H77=="=cUCDDGEN #GN'"	W	 M>M%%gkk-&DhOM gx027=)* O  M<tLM	M M  Os<   !D%"C/D! / DDDDD!	D.-D.)asciiemojikaomojiunicode._INDICATOR_STYLESrB  Fr&  r(  valuedefault	min_valuec                Z    	 t        |       }||k\  r|S |S # t        t        f$ r |cY S w xY wr   )r  rS  r>  )rE  rF  rG  r  s       rD   _coerce_int_config_valuerI  ~  s?    e* *777 z" s    **c                 L   | 
t               n| }t        |t              r|j                  d      ni }t        |t              si }t	        |j                  d      t
              t        |j                  d      t        d      t        |j                  d      t        d      d	S )
a^  Return dashboard process-isolation config with read-site defaults.

    ``_load_cfg()`` intentionally returns raw ``config.yaml`` plus the managed
    overlay; it does not deep-merge ``hermes_cli.config.DEFAULT_CONFIG``. Keep
    the Phase-0 defaults here so dashboard runtime and the REST editor's
    DEFAULT_CONFIG-backed schema cannot drift.
    	dashboardr  rF  r%  r   )rG  r'  r   )r  r%  r'  )	r  r  r   r   r   !_DASHBOARD_TURN_ISOLATION_DEFAULTrI  ._DASHBOARD_COMPUTE_HOST_HEARTBEAT_SECS_DEFAULT+_DASHBOARD_COMPUTE_HOST_RESPAWN_MAX_DEFAULT)r  r  rK  s      rD   r  r    s     +9;3D)3D$)?%RIi&	)MM*+5
 (@MM78:(

 %=MM457%
 r   c                     	 dd l } t               }t        |t              r|r|nt        }t        |      dz  }|j                         r|j                         j                  nd }t        5  t        =t        |k(  r4t        |k(  r+t        t        j                  t                    cd d d        S d d d        |j                         r,t!        |d      5 }| j#                  |      xs i }d d d        ni }t        5  t        j                        a
|a|ad d d        t              S # 1 sw Y   zxY w# 1 sw Y   HxY w# 1 sw Y   ,xY w# t$        $ r Y i S w xY w)Nr   r  r    r!   )r  r   r  r6   r  r   r  statst_mtime	_cfg_lockrW   rX   	_cfg_path_apply_managedcopydeepcopyr1   r   r5   )r  r  r  r  mtimerB   r  s          rD   r  r    s=    ,-%h4x|J&%&XXZ!!T 	A%**=)q.%dmmJ&?@	A 	A 	A 88:a'* /a~~a(.B/ / D 	
 t,JJI	 d##!	A 	A/ /	 	  Is`   A(E *:D'$	E .%E D3)E :D?E 'D0,E 3D<8E ?EE 	EEc                     	 ddl m} |j                  t        | t              r|       S i       S # t
        $ r | cY S w xY w)ut  Overlay administrator-pinned managed-scope values on a config dict.

    The TUI/desktop backend builds config independently of
    hermes_cli.config.load_config, so without this a managed skin / reasoning_effort
    / service_tier / provider_routing would be silently ignored here. Read-side
    only — the raw user config is what gets cached and saved. Fail-open.
    r   )managed_scope)r  rZ  apply_managed_overlayr  r   r5   )r  rZ  s     rD   rU  rU    sA    ,22*S$:O3XXUWXX 
s   &/ / ==c                     ddl m} t        dz  } |||        t        5  t	        j
                  |       a|a	 |j                         j                  a
d d d        y # t        $ r d a
Y w xY w# 1 sw Y   y xY w)Nr   )atomic_config_writer  )hermes_cli.configr]  r  rS  rV  rW  rW   rT  rQ  rR  rX   r5   )r  r]  r.   s      rD   	_save_cfgr_    sw     6-'Dc"	 ]]3'
		--J	 
  	J	 s(   A,AA)&A,(A))A,,A5c                     | syt         5  t        t        j                               D ]?  }|j	                  d      | k(  st        |j	                  d      xs d      c cddd       S  	 ddd       y# 1 sw Y   yxY w)zReverse-map session_key to the session's logical cwd.

    Snapshots ``_sessions`` first: concurrent RPC handlers mutate it from the
    thread pool, so iterating the live view risks ``RuntimeError: dictionary
    changed size during iteration``.
    r   r   r   N)re  r_  rQ   valuesr   r6   )r   sesss     rD   _cwd_for_session_keyrc    sw     	 2))+, 	2Dxx&+5488E?0b112 2	22 	2 s   5A4 A4)A44A=ui_session_idre  c                8   	 ddl m} ||n
t        |       }t               }t        5  t        t        j                               D ]#  }|j                  d      | k(  st        |      } n d d d         || |||      S # 1 sw Y   xY w# t        $ r g cY S w xY w)Nr   )set_session_varsr   )r   rB  r   re  )gateway.session_contextrg  rc  r	  re  r_  rQ   ra  r   r2  r5   )r   r   re  rg  r  rB  rb  s          rD   r  r    s    < /3/CK/P*, 	Y--/0 88M*k9,T2F	
  #'	
 	
	 	  	s.   %B 5A?A?+B ?BB BBr  c                 F    | sy 	 ddl m}  ||        y # t        $ r Y y w xY w)Nr   )clear_session_vars)rh  rj  r5   )r  rj  s     rD   r  r  	  s*    >6" s    	  c                  v    dt         j                  d<   dt         j                  d<   dt         j                  d<   y)zARoute approvals through gateway callbacks instead of CLI input().r  HERMES_GATEWAY_SESSIONHERMES_EXEC_ASKHERMES_INTERACTIVEN)r,   r  r   r   rD   _enable_gateway_promptsro   	  s/    +.BJJ'($'BJJ !'*BJJ#$r   c                 *   t        j                         j                  d d }t        j                         }t
        5  ||ft        |<   ||d<   | t        |      ft        |<   d d d        d}d}d}	 t        | ||       |j                  |      }t
        5  t        j                  |d        t        j                  |d        |t        v }t        j                  |d      }d d d        |s'|s%| dv r!t        | j                  d       d|d|i       |S # 1 sw Y   xY w# 1 sw Y   @xY w# t
        5  t        j                  |d        t        j                  |d        |t        v }t        j                  |d      }d d d        w # 1 sw Y   w xY wxY w)	Nr   r8  Fr   r   >   sudo.requestsecret.request.requestz.expire)uuiduuid4hexr   Event_prompt_lockrS   r   rT   r  r   r(  rU   removesuffix)	r  r-  r  r   r   evansweredansweranswer_presents	            rD   _blockr~  *	  sw   
**,

2A
C		B	 ?b	 #).W(> %? HFN+eS'"7777+ 	+LLd#$((d3 H_N\\#r*F		+ Nu8Z/Z!!*-.g63	

 M/? ?	+ 	+\ 	+LLd#$((d3 H_N\\#r*F		+ 	+ 	+s=   %D0D+ ADDD(+F2AF=	FFFc                     t         5  t        t        j                               D ])  \  }\  }}| || k(  sdt        |<   |j                          + 	 ddd       y# 1 sw Y   yxY w)u|  Release pending prompts with an empty answer.

    When *sid* is provided, only prompts owned by that session are
    released — critical for session.interrupt, which must not
    collaterally cancel clarify/sudo/secret prompts on unrelated
    sessions sharing the same tui_gateway process.  When *sid* is
    None, every pending prompt is released (used during shutdown).
    Nr   )rx  r_  rS   rf  rU   r^  )r-  r   	owner_sidrz  s       rD   _clear_pendingr  G	  s^     
 $()9$: 	 C)R{i3. "	  s   .AAA$c            
      ,   	 ddl m} m}  | t                       |       }|j                  |j
                  |j                  |j                  |j                  |j                  |j                  xs i j                  dd      dS # t        $ r i cY S w xY w)Nr   )init_skin_from_configget_active_skinhelp_headerr   )rI   colorsbrandingbanner_logobanner_herotool_prefixr  )hermes_cli.skin_enginer  r  r  rI   r  r  r  r  r  r   r5   )r  r  skins      rD   resolve_skinr  Z	  s    Qik* IIkk++++++ MM/R44]BG
 	
  	s   BB BBc                     t         j                  j                  dd      xs  t         j                  j                  dd      j                         } | r| S t	               j                  dd      }t        |t              r-t        |j                  dd      xs d      j                         S t        |t              r|r|j                         S 	 ddlm	}  |       S # t        $ r Y yw xY w)	NHERMES_MODELr   HERMES_INFERENCE_MODELr   rF  r   )"get_preferred_silent_default_modelzz-ai/glm-5.2)r,   r  r   r7   r  r  r   r6   hermes_cli.modelsr  r5   )r   mr  s      rD   r  r  m	  s    


~r* 	8::>>2B7eg  
$A!T155B'-2.4466!SawwyH133 s   C 	C('C(c                      t        t        j                  j                  d            r)t        t        j                  j                  d            syy)u  Resolve the platform tag for a tui_gateway-routed session.

    The desktop app's chat panel and the standalone TUI both speak to this
    gateway; without a branch they all get stamped ``platform="tui"``,
    which makes the agent think it's talking to a terminal user. That
    mis-tag is the root cause of the desktop chat agent suggesting
    TUI-only slash commands (``/reload-mcp``, …) to chat-panel users.

    Resolution:
      * ``HERMES_DESKTOP=1`` and ``HERMES_DESKTOP_TERMINAL`` unset → "desktop"
        (the chat-panel backend — a graphical React surface, not a terminal).
      * ``HERMES_DESKTOP_TERMINAL=1`` → "tui"
        (``hermes --tui`` running in the desktop's embedded terminal pane;
        it IS a TUI, just embedded. The clarifier attached to the tui hint
        in system_prompt.py tells the agent about the embedding.)
      * neither set → "tui"
        (standalone ``hermes --tui``.)
    HERMES_DESKTOPHERMES_DESKTOP_TERMINALr=  r  )r   r,   r  r   r   r   rD   r	  r	  	  s;    & rzz~~&678


01B r   explicitc                     | r| S t               S )uQ  Default the session DB ``source`` field from the resolved platform.

    A caller that explicitly passes ``source`` (e.g. a plugin session tagged
    ``"telegram"``) keeps its value. Only an empty/None ``source`` falls back
    to the env-resolved platform — so env-driven resolution never silently
    rewrites a caller's intent.
    )r	  )r  s    rD   _resolve_session_sourcer  	  s     $&&r   c                     t        |       S r   )r  )rB  s    rD   r  r  	  s    "6**r   c                     t               j                  d      } d}d}t        | t              rrt	        | j                  dd      xs d      j                         }t	        | j                  d      xs d      j                         }|j                         dk(  rd}||fS t        | t              r| j                         }||fS )u  (model, provider) currently selected by config.yaml — and ONLY config.

    Unlike `_resolve_model()`, this never reads HERMES_MODEL /
    HERMES_INFERENCE_MODEL. Those env vars are a launch-scoped seed
    (`hermes --tui -m <model>`, hosted-instance provisioning); if they
    fed the per-turn sync, the seed would be replayed as a /model switch
    and persisted globally, or would pin the session so dashboard/CLI
    model changes never reach an open chat.
    r   r   rF  r  r  r  )	cfg_modelr   r  s      rD   r  r  	  s     (IEH)T"IMM)R06B7==?y}}Z06B7==?>>v%H (? 
Is	#! (?r   c                     t               } t        j                  j                  dd      j	                         }|r| |fS t        j                  j                  dd      xs  t        j                  j                  dd      j	                         }|s| d fS 	 ddlm} t               j                  d      xs i }t        |t              r:t        |j                  d      xs d      j	                         j                         ndxs@ t        j                  j                  d	d      j	                         j                         xs d
} |||      }|r	|\  }}||fS 	 | d fS # t        $ r Y | d fS w xY w)NHERMES_TUI_PROVIDERr   r  r  r   ) detect_static_provider_for_modelr   r  HERMES_INFERENCE_PROVIDERr  )r  r,   r  r   r7   r  r  r  r  r   r6   r  r5   )	r   explicit_providerexplicit_modelr  r  current_providerdetectedr  detected_models	            rD   _resolve_startup_runtimer  	  sf   E

'<bAGGI''' 	

~r* 	8::>>2B7eg  d{Fkoog&," c4( CGGJ'-2.446<<>
 zz~~92>DDFLLN  	 4NDTU'/$Hn!8++ 
 $;  $;s   CE   	E/.E/>   r  r  
openrouterrl  c                 j   | si S | j                  d      }i }t        |t              r|}nHt        |t              r8|j	                         r(	 t        j                  |      }t        |t              r|}i }t        | j                  d      xs |j                  d      xs d      j	                         }t        |j                  d      xs d      j	                         }t        |j                  d      xs | j                  d      xs d      j	                         }|}|s|j                         t        vr|}t        |j                  d	      xs d      j	                         }	t        |j                  d
      xs d      j	                         }
|j                  d      }t        |j                  d      xs d      j	                         }|j	                         j                         dk(  r d}	 ddlm}  ||	xs d      }|xs |	sdn|}|r||xs d|	xs d|
xs dd|d<   |r||d<   t        |t              r||d<   |j                         dk(  rd|d<   |S |r||d<   |S # t        $ r t        j                  dd       Y w xY w# t        $ r t        j                  dd       Y w xY w)a  Return runtime fields persisted with a stored session.

    ``session.resume`` is a session-scoped operation: reopening an older chat
    must restore the model/provider/reasoning state that chat actually used,
    not whatever global model the user most recently selected in another chat.
    The durable session row stores the model directly, the billing provider in
    ``billing_provider``, and richer runtime knobs in JSON ``model_config``.
    r  z+failed to parse stored session model_configTr&  r   r   r  billing_providerr  r  r  r  r  Nr   r  r  z(custom provider identity recovery failed)r   r  r  r  r5  provider_overrider9  r  r:  )r   r  r   r6   r7   r   r   r5   r  r*  r  _BARE_BILLING_PROVIDERSr  r  )rl  
raw_configr  parsed	overridesr   r  r  r  r  r  r  r  r  r  s                  rD   !_stored_session_runtime_overridesr  	  s    	(JL*d#!	J	$)9)9);	WZZ
+F&$'% I CL$4$4W$=CDJJLE L,,Z8>B?EEG+,Q8J0KQreg  !H(..08OO#<##J/526<<>H<##J/526<<>H#''(:;|''7=2>DDFL ~~8+	M.8HDIF
 ?bh  (D (D (D	'
	"# )1	%&"D)1A	-.x' .0	)*  
-9	)*G  	WLLFQULV	WL  	LL:T  	s$   'I( 4J ( JJ J21J2existingc                 X   t        |xs i       }t        t        | dd      xs d      j                         }t        t        | dd      xs d      j                         }t        t        | dd      xs d      j                         }t        t        | dd      xs d      j                         }t        | dd       }t        | dd       }|r||d<   |r:|j                         j	                         dk(  r	 d	d
lm}	  |	|      xs |}||d<   |r||d<   n|j                  dd        |r||d<   n|j                  dd        t        |t               r||d<   n|j                  dd        |r||d<   |S |j                  dd        |S # t        $ r t        j                  dd       Y w xY w)Nr   r   r  r  r  r  r  r  r   r  r  z&custom provider identity lookup failedTr&  )r   r6   r   r7   r  r  r  r5   r  r*  r(  r  )
rN  r  r  r   r  r  r  r  r  r  s
             rD   _runtime_model_configr  R
  s   (.b!Fw+1r288:E75*b17R8>>@H75*b17R8>>@H75*b17R8>>@Hu&8$?5.$7Lw>>!!#x/
 .x@LH  &z%z

:t$%z

:t$"D)%5!"

%t,!-~ M 	

>4(M-  <t  s   5F  F)(F)c                 j   | sy| j                  d      }t        | j                  d      xs d      j                         }||syt        |dd      xs
 t	               }|y	 |j                  |      xs i }|j                  d      }i }t        |t              r|}nGt        |t              r7|j                         r't        j                  |      }t        |t              r|}t        ||      }| j                  d      }	|		|	xs d|d	<   t        t        |d
d      xs d      j                         }
t        |d      r+|j                  |t        j                  |      |
xs d       y|
r t        |d      r|j                  ||
       yyy# t        $ r t         j#                  dd       Y yw xY w)zIPersist active session runtime so future resumes restore the same footer.NrN  r   r   r  r  r7  r  r  r   update_session_metaupdate_session_modelz&failed to persist live session runtimeTr&  )r   r6   r7   r   ra  rb  r  r   r   r   r  r`  r  r   r  r5   r  r*  )r#  rN  r   rk  rl  r  existing_configr  r  r7  r   s              rD   _persist_live_session_runtimer  
  s   KK Egkk-06B7==?K}K	t	,	9	B	zNnn[)/RWW^,
j$'(O
C(Z-=-=-?ZZ
+F&$'"(,UOD'.{{3Q'R$'3 ,H+S8L(GE7B/526<<>2,-"";

<0H%-SWXwr#9:##K7 ;U N=MNs   #DF , F  F21F2c                    | sy| j                  d      }t        | j                  d      xs d      j                         }||rt        |d      syt	        |dd      xs
 t               }|t        |d      sy	 |j                  d      }||_        |j                  t	        |dd      xs ||       y# t        $ r t        j                  d	d
       Y yw xY w)zFRefresh the stored system prompt after a live runtime identity change.NrN  r   r   _build_system_promptr  update_system_promptr  z,failed to persist live session system promptTr&  )r   r6   r7   r`  r   ra  r  _cached_system_promptr  r5   r  r*  )r#  rN  r   rk  prompts        rD   #_persist_live_session_system_promptr  
  s    KK Egkk-06B7==?K}Kwu>T/U	t	,	9	B	z%;<T++D1&,#
|T B QkSYZ TCdSTs   ;9B5 5 CCr   r  c                4   | syt        | j                  d      xs d      j                         }|sy|rd| nd}d| | d}d|d}| j                  d	      }|N|5  | j                  d
g       j	                  |       t        | j                  dd            dz   | d<   ddd       nB| j                  d
g       j	                  |       t        | j                  dd            dz   | d<   	 | j                  d      }|t        |dd      nd}	|	|	j                  |d|       yt        |        t        |       5 }
|
|
j                  |d|       ddd       y# 1 sw Y   yxY w# 1 sw Y   yxY w# t        $ r t        j                  dd       Y yw xY w)z=Record a real system-history pivot after a live model switch.Nr   r   z via provider z7[System: The active model for this chat has changed to zs. From this point forward, use this runtime metadata when answering questions about what model/provider is active.]r*  r)  r+  rO  rP  r1  r   r   rN  r  r,  z%failed to persist model switch markerTr&  )r6   r   r7   rf  appendr  r   r-  r&  r  r5   r  r*  )r#  r   r  r   provider_partmarkerentryrh  rN  rk  	scoped_dbs              rD   _append_model_switch_markerr  
  s   gkk-06B7==?K3;nXJ/MA'- !R	R  /E;;~&D 	Ty"-44U;),W[[9JA-N)ORS)SG%&	T 	T 	9b)007%(5F)J%Ka%O!"MG$494EWUM404>66Rw'! 	Y$((* ) 	 		T 	T	 	
  M<tLMsC   AE-8E4 &E4 <E(E4 E%(E1-E4 1E4 4 FFkey_pathc                     t               }|}| j                  d      }|d d D ]/  }||vst        |j                  |      t              si ||<   ||   }1 |||d   <   t        |       y )Nr  )r  splitr  r   r   r_  )r  rE  r  r  keysrw  s         rD   _write_config_keyr  
  st    
+CG>>#DCRy gZC0@$%GGCL#, GDHcNr   >   offtopbottom>   r  smartmanualc                      ddl m} m} ddlm} t               } || t        |t              r|ni       }|j                  d      }t        |t              r|j                  d      nd } ||      }|t        v r|S dS )Nr   )DEFAULT_CONFIG_deep_merge_normalize_approval_mode	approvalsmoder  )
r^  r  r  rv  r  r  r  r   r   _APPROVAL_MODES)r  r  r  raw_cfgr  r  r  r  s           rD   _load_approval_moder    sj    =7kG
nGT1JgPR
SC$I#-i#>)--
DC#C(D?*488r   c                 ~    | du ryt        | t              r(| j                         j                         x}t        v r|S y)NFr  r  )r  r6   r7   r  _STATUSBAR_MODES)r  r  s     rD   _coerce_statusbarr    s:    
e|#sciik&7&7&9!9>N Nr   0r  r  allanybuttonbuttonsclickfalsefullnoonscrollwheeltrueyesr   c                 J   t        | t              syd| v r| j                  d      }n| j                  dd      }|du s|dk(  ry|du s|yt        |t        t        f      ryt        |t
              r2t        j                  |j                         j                         d      S y)u  Resolve display.mouse_tracking to one of ``off|wheel|buttons|all``.

    Boolean values keep their legacy meaning (``True`` → ``all``, ``False`` →
    ``off``). The ``wheel`` preset (DEC 1000+1006) is the tmux-friendly
    subset — wheel + click only, no hover events to trigger prompt-row
    clipboard probes. Legacy ``tui_mouse`` is honored only when
    ``mouse_tracking`` is absent.
    r  mouse_tracking	tui_mouseTFr   r  )	r  r   r   r  r  r6   _MOUSE_TRACKING_ALIASESr7   r  r  s     rD   _display_mouse_trackingr  .  s     gt$7"kk*+kk+t,
e|sax
d{ck#U|$#s&**399;+<+<+>FFr   c                 0    ddl m}  |t               |       S )a  Load reasoning effort from config.yaml, respecting per-model overrides.

    Thin wrapper over the shared chokepoint
    :func:`hermes_constants.resolve_reasoning_config` (per-model override >
    global ``agent.reasoning_effort``; YAML boolean False = disabled).
    Closes #21256.
    r   )resolve_reasoning_config)r=  r  r  )r   r  s     rD   _load_reasoning_configr  H  s     :#IK77r   c                      t        t               j                  d      xs i j                  dd      xs d      j                         j	                         } | r| dv ry | dv ryy )NrN  r  r   >   r  noner  rF  standard>   r  fastpriorityr  )r6   r  r   r7   r  r  s    rD   _load_service_tierr  U  s^    Y[__W%+00DJK		 
 #II
((r   c                  b    	 t               j                  di       xs i S # t        $ r i cY S w xY w)a  OpenRouter provider-routing prefs from config.yaml (``provider_routing``).

    Parity with the messaging gateway (``gateway/run.py::_load_provider_routing``)
    and the classic CLI: without this the desktop/TUI backend builds agents with
    no routing prefs, so OpenRouter falls back to its default (effectively random)
    provider selection even when the user configured ``provider_routing``.
    provider_routing)r  r   r5   r   r   rD   _load_provider_routingr  b  s4    {126<"< 	s     ..c                  n    t        t               j                  d      xs i j                  dd            S )Nr   show_reasoningT)r   r  r   r   r   rD   _load_show_reasoningr   p  s-     +1r667GNOOr   c                      t               j                  d      xs i j                  d      } t        | t              r| rdS dS | rt	        |       j                         S dS )u  Self-improvement review notification mode from config.yaml.

    Parity with the messaging gateway (``gateway/run.py``) and the classic CLI:
    ``display.memory_notifications`` controls whether the background review's
    "💾 Self-improvement review: …" summary is surfaced. Without this the
    TUI/desktop backend always behaved as ``"on"`` and silently ignored a user
    who set ``off``. Accepts ``off`` / ``on`` (default) / ``verbose``; a bool is
    normalized for back-compat.
    r   r  r  r  )r  r   r  r   r6   r  r  s    rD   r  r  v  sT     ;??9%+
0
01G
HC#tt%%"3s8>>,,r   c                  Z   t         j                  j                  dd      j                         j	                         } | dv r| S t               j                  d      xs i j                  dd      }|du ry|d	u ryt        |xs d      j                         j	                         }|dv r|S dS )
NHERMES_TUI_TOOL_PROGRESSr   >   r  newr  verboser   tool_progressr  Fr  T)r,   r  r   r7   r  r  r6   )r   r  r  s      rD   _load_tool_progress_moder    s    
**..3R
8
>
>
@
F
F
HC
..
;??9%+
0
0%
HC
e|
d{s|e""$**,D;;4FFr   c                     t         j                  j                  dd      j                  d      D  cg c]"  } | j	                         r| j	                         $ }} d }d }|s*	 ddlm}  |t                     }|t        h |d      S 	 	 ddl
m} |rV|S|D cg c]  } ||      s| }}|D cg c]	  }||vs| }	}|	rM	 dd	lm}
  |
        |	D cg c]  } ||      s| }}|r%|j                  |       |	D cg c]	  }||vs| }	}t        d
 |D              rE|D cg c]	  }|dvs| }}|r.t!        ddj#                  |       t$        j&                  d       y |	s|S t)               }t)               }	 ddlm} ddlm}  |       }t3        |j                  d      t4              r|j                  d      ni }|j7                         D ]e  \  }}t3        |t4              s ||j                  dd      d      r|j9                  t;        |             L|j9                  t;        |             g 	 |	D cg c]	  }||v s| }}|	D cg c]	  }||v s| }}|	D cg c]  }||vr||vr| }}||z   }|r.t!        ddj#                  |       t$        j&                  d       |r.t!        ddj#                  |       t$        j&                  d       |r|S d}	 ddlm} ddlm} ||n |       } ||dd      }|t!        |t$        j&                  d       |sy t        |dhz        S c c} w # t        $ r Y w xY w# t        $ r d }Y w xY wc c}w c c}w c c}w # t        $ r g }Y w xY wc c}w c c}w # t        $ r t)               }t)               }Y ow xY wc c}w c c}w c c}w # t        $ r! |t!        dt$        j&                  d       Y y w xY w)NHERMES_TUI_TOOLSETSr   ,r   )coding_selection)r  project)validate_toolset)discover_pluginsc              3   $   K   | ]  }|d v  
 yw)>   *r  Nr   .0rI   s     rD   	<genexpr>z)_load_enabled_toolsets.<locals>.<genexpr>  s     9t|#9   >   r  r  zR[tui] HERMES_TUI_TOOLSETS=all enables every toolset; ignoring additional entries: , Tr&   read_raw_config)_parse_enabled_flagmcp_serversenabledrL  z4[tui] ignoring unknown HERMES_TUI_TOOLSETS entries: zf[tui] ignoring disabled MCP servers in HERMES_TUI_TOOLSETS (set enabled: true in config.yaml to use): zI[tui] no valid HERMES_TUI_TOOLSETS entries; using configured CLI toolsetsload_config)_get_platform_toolsr8  include_default_mcp_serverszq[tui] no valid HERMES_TUI_TOOLSETS entries and configured CLI toolsets could not be loaded; enabling all toolsets) r,   r  r   r  r7   agent.coding_contextr  r	  sortedr5   toolsetsr  r  r  extendr  r:   r*   r;   r<   r^  r^  r  hermes_cli.tools_configr  r  r   rf  addr6   r  r  )itemr  r  fallback_noticer  	selectionr  rI   built_in
unresolvedr  plugin_validignored	mcp_namesmcp_disabledr  r  r  r  
server_cfg	mcp_validdisabledrT  validr  r  r  s                              rD   _load_enabled_toolsetsr3    sA    JJNN#8"=CCCH::< 	

H 
 CO 	=(2K2MNI$
 5	59566 % - $0%-HT1A$1GDHH'/Ht4x3GdH
H"? "1;V?OPT?UVV -/9VtT=UdV
V999(0MD4LtMGM448IIg4F3GI	 O!e	!$	!9C%'G gkk-8$? M* 
 %0$5$5$7 0 j!*d3&z~~i'FPTUMM#d), $$SY/0 '1FdDI4ETF	F%/HT4<3GDHH #
9$\)A 
 

 9$FtyyQXGYFZ[ZZ
 >99X&') ZZ L X 	1?_c+- &c5dS&/

$? g+,,[2  		
     IH  W "!"
 W N@  	!I5L	! GH
j  & DZZ
 s   'L>"'M M M%*M%4	M*>M*M4 M/&M/*M4 	NN)	N3NB=N 	N4N4	N9#N9-N>,AO /O 	MMM"!M"/M4 4NNN10N1'O-,O-c                 h    t        t        j                  | i       j                  dd      xs d      S )Ntool_progress_moder  )r6   rQ   r   r-  s    rD   _session_tool_progress_moder7  ,  s+    y}}S"%))*>FO%PPr   c                     t        |       dk(  S )Nr  r7  r6  s    rD   _session_verboser:  0  s    &s+y88r   c                     t        |       dk7  S )Nr  r9  r6  s    rD   _tool_progress_enabledr<  4  s    &s+u44r   c           	      2   |j                  d      }|r	 |j                          	 t        |d   t	        |j                  d      dt                     |j                  d            }t        | ||       y # t        $ r Y \w xY w# t        $ r d |d<   Y y w xY w)Nr]  r   rN  r   r   r  )r   r   r5   r   r   r  rz  )r-  r#  rp  
new_workers       rD   _restart_slash_workerr?  8  s    [[(F	LLN!M"GKK('>3CD ^4

 3,  		  "&s#   A6 AB 6	BBBBc                     ddl m}  |d| j                          |d| j                         | j                  r |d| j                         y  |dd        y )Nr   save_config_valuezmodel.defaultzmodel.providerzmodel.base_url)r8  rB  	new_modeltarget_providerr  )r  rB  s     rD   _persist_model_switchrE  O  sK    
 &ov'7'78&(>(>?*FOO< 	*D1r   c                     t        | dd      t        | dd      t        | dd      t        | dd      t        | dd      t        j                  t        | dd            d	S )
z?Capture the current agent model runtime for a one-turn restore.r   r   r  api_keyr  r  _primary_runtimeN)r   r  rG  r  r  primary_runtime)r   rV  rW  rN  s    rD   _snapshot_agent_model_runtimerK  c  s`     ,E:r25)R0E:r2E:r2==8JD)QR r   ri  c           
         |r| y|j                  d      }|rGt        | d      r;	 t        j                  |      | _        d| _        d| _        | j                         ry	 t        | d      rg| j                  |j                  d	d
      |j                  dd
      |j                  dd
      |j                  dd
      |j                  dd
             yy# t        $ r t        j                  dd       Y w xY w)zCRestore an agent model runtime captured before a one-turn override.NrI  _restore_primary_runtimeTr   z5TUI one-turn model restore via primary runtime failedr&  switch_modelr   r   r  rG  r  r  rC  new_providerrG  r  r  )r   r`  rV  rW  rH  _fallback_activated_rate_limited_untilrM  r5   r  r*  rN  )rN  ri  primarys      rD   _restore_agent_model_runtimerT  o  s    u}ll,-G75"<=	a%)]]7%;E"(,E%()E%--/ 0 un%ll7B/!j"5LLB/\\*b1\\*b1 	 	
 &  	aLLP[_L`	as   8C  C76C7)confirm_expensive_modelpin_session_overrideparsed_flagspersist_override	raw_inputrU  rV  rW  rX  c                *
   ddl m}m}m}	 ddlm}
 | ||      }t        |d      r=|j                  }|j                  }|j                  }|j                  }|j                  }n
|\  }}}}}d}|r|rt        d      ||n |||||      }|st        d      |j                  d	      }|r|st        d
      |rEt        |dd      xs d}t        |dd      xs d}t        |dd      xs d}t        |dd      xs d}nt               }|j!                         }d}d}|s |
d       }t#        |j                  dd      xs d      }t#        |j                  dd      xs d      }|j                  dd      }t%        |      rt'        |t"              s|}nt#        |xs d      }d }d }d }	 ddlm}m}  |       }|j                  d      } ||      } |	|||||||||	      }|j0                  st        |j2                  xs d      |r|rt5        |      nd }|r	 ddlm}  d }!t'        |t:              rA|j                  di       }"t'        |"t:              r|"j                  d      t=        |"d         }! | ||t?        |j                  dg             ||!       |s	 ddl"m#}$  |$|jH                  |jJ                  |jL                  xs ||jN                  xs ||jP                        }%|%:|%jR                  }&|jT                  r|& d|jT                   }&|jH                  |&d|&dS |r	 |j                  |jH                  |jJ                  |jN                  |jL                  |jV                         t[        | |       t]        |       t_        |       ta        ||jH                  |jJ                  %       tc        d&| te        ||             |r||d'<   n|jg                  d'd        |rOt'        |t:              r?|s=|jH                  |jJ                  |jL                  |jN                  |jV                  d(|d)<   |rti        |       |jH                  |jT                  xs dd|rd*d-S |rd+d-S d,d-S # t.        $ r Y w xY w# t.        $ r!}#t@        jC                  d|#       Y d }#~#
d }#~#ww xY w# t.        $ r d }%Y w xY w# t.        $ rF}#t@        jY                  d |#       t        d!|jH                   d"|# d#t        |d|       d$      |#d }#~#ww xY w).Nr   )parse_model_flags_detailedresolve_persist_behaviorrN  resolve_runtime_providermodel_inputFz./model --once cannot be combined with --global)is_oncer  model value requiredrN  z%/model --once requires a live sessionr  r   r   r  rG  	requested)get_compatible_custom_providersr  	providers)	rY  r  current_modelcurrent_base_urlcurrent_api_key	is_globalr  user_providerscustom_providerszmodel switch failed)#merge_preflight_compression_warningcontext_lengthrP  )rN  messagesrk  config_context_lengthz/preflight-compression switch warning failed: %s)expensive_model_warning)r  r  rG  
model_info

T)rE  r   confirm_requiredconfirm_messagerO  z.In-place model switch failed for TUI agent: %szModel switch to z	 failed (z); staying on r  r   r  rP  one_turn_model_restorer   r  r  rG  r  r5  rk  globalr#  )rE  r   rs  scope)5hermes_cli.model_switchr[  r\  rN  r  r^  r`  r_  r  ri  
is_sessionr`  r>  r   r   r  r7   r6   callabler  r^  rd  r  r5   successerror_messagerK  hermes_cli.context_switch_guardrl  r   r  r_  r  r*  hermes_cli.model_cost_guardrp  rC  rD  r  rG  rq  rK  warning_messager  r   r?  r  r  r  r  rR  r(  rE  )'r-  r#  rY  rU  rV  rW  rX  r[  r\  rN  r^  r_  r  is_global_flagr{  one_turn_force_refreshpersist_globalrN  r  rf  rg  rh  runtime_runtime_key
user_provscustom_provsr  rd  r  r  restore_snapshotrl  _cfg_ctx_mcr!  rp  r   confirm_msgs'                                          rD   _apply_model_switchr    sr    
 E1)<|]+"..(::%//!,,
''UaR&
(IJJ ' 	%/	
  /00KK E@AA"5*b9?Rw39r"5*b9?R!%B7=2&(,224 .>G"7;;z2#>#D"E"7;;z2#>#D"E #;;y"5L%js.K"."%l&8b"9 JL
CRmWW[)
6s; )#)' +!%
F >>--F1FGG@HU4U;Y]	Q[H#t$gggr*c4(SWW5E-F-R"3'7#89H/gkk)R89!-&. #	K-  //<,<9/!,,G !//K%%!,T&2H2H1IJ))&$(#.	  	 **#33  ( 	c7+%g.+G4#6++f6L6L	
 	nc=#@A0@G,-KK0$7 
7D 9(%%..~~%
 ! f%!!))/R!#	  7E(	  KT	 o  F  	QLLJCPP	Q  	G	,  	 NNKSQ"6#3#3"4IcU C%eWmDEQH 	sX   .(Q4  A?R "AR1 .AS 4	R R	R.R))R.1S ?S 	TATTc           
         |j                  d      }||j                  d      ryt               }|d   sy|j                  d      }||d<   ||k(  ry|\  }}|t        |dd      k(  r|r|t        |dd      k(  ry|r| d	| n|}	 t        | ||d
dd       y# t        $ r}t        d| dd| d| i       Y d}~yd}~ww xY w)zAdopt a config.yaml model change at turn start, like gateways do per
    message. Sessions pinned with /model keep their choice; a failed switch
    keeps the current model and never blocks the turn.
    rN  Nr5  r   r  r   r   r   --provider TFrU  rV  rX  r   rK  z%Could not switch to configured model r%   )r   r  r   r  r5   r  )	r-  r#  rN  r   seenr   r  r  r  s	            rD   _sync_agent_model_with_configr  X  s    
 KK E}$45!#F!9;;*+D#)G ~OE8 w++GE:r$BB.6UG<z
*EC
$(!& #	
  
?wbLM	
 	

s   B 	C !B;;C focus_topicapprox_tokensbefore_messagesr1  c                    ddl m} | d   }||D| d   5  t        | j                  dg             }t	        | j                  dd            }d d d        |}t        |      dk  rt        |      }d|fS |-t        |dd	      xs d	}	t        |d
d       xs d }
 |||	|
      }|j                  |d ||xs d       \  }}| d   5  t	        | j                  dd            |k7  rt        |      }d|fcd d d        S || d<   |dz   | d<   d d d        t        |      }t        |      t        |      z
  |fS # 1 sw Y   xY w# 1 sw Y   9xY w)Nr   estimate_request_tokens_roughrN  rO  rP  r1     r  r   r`   system_promptr`   )r  r  r   )	agent.model_metadatar  r_  r   r  r  
_get_usager   _compress_context)r#  r  r  r  r1  r  rN  rP  usage_sys_prompt_tools
compressedr  s                rD   _compress_session_historyr    s    CGE
 /"9^$ 	E"7;;y"#=>O!'++.?"CDO	E G
7|a5!%x e%<bAGR.6$5;f
 ++#'4	 , MJ 
	  9w{{,a01_D u%Ee89 9 (	%4q%8!"9 uEw<#j/)500G	E 	E49 9s   7D3-D?:D?3D<?Eclear_pending_titlerestart_slash_workerr  r  c                R    |j                  d      }t        |dd      xs d}|j                  dd      xs d}|r||k(  ryt         ||      }|st        j	                  d ||       	 dd	lm}m}	m}
m	}m
} 	  ||       ||d<   	  |
|      }|r	  |	|        ||       	  || fd       |rd|d<   |r	 t         |       yy# t        $ r Y Qw xY w# t        $ r d
}Y Tw xY w# t        $ r Y Pw xY w# t        $ r Y Rw xY w# t        $ r ||d<   Y fw xY w# t        $ r Y yw xY w)a  Re-anchor session_key when AIAgent._compress_context rotates session_id.

    AIAgent._compress_context ends the current SessionDB session and creates
    a new continuation session, rotating ``agent.session_id``.  The TUI
    gateway keeps the gateway-side ``session_key`` separate (used for
    approval routing, slash worker init, DB title/history lookups, yolo
    state).  Without this sync, those operations would target the ended
    parent session while the agent writes to the new continuation session.

    Policy flags:
        clear_pending_title: True for manual /compress (title belongs to old
            session). False for post-turn auto-compression (preserve user
            intent so pending_title can be applied to the continuation).
        restart_slash_worker: True for manual /compress and post-turn
            auto-compression (worker holds stale session key). False only
            if the caller manages the worker lifecycle separately.
    rN  r  Nr   r   )r.  zWCompression session lease did not re-anchor: sid=%s old_session_id=%s new_session_id=%sr   )disable_session_yoloenable_session_yolois_session_yolo_enabledr  ru  Fc                     t        |       S r   r  r  s    rD   r   z2_sync_session_key_after_compress.<locals>.<lambda>  s    3C> r   pending_title)r   r   r6  r  r   rv  r  r  r  r  ru  r5   r?  )r-  r#  r  r  rN  r.  old_keylease_reanchoredr  r  r  r  ru  yolo_was_ons   `             rD    _sync_session_key_after_compressr    s   0 KK EUL$7=2Nkk-,2G^w64%
 e		
#0	
 	
	%g. "0	 1':K #N3$W-	#> #' 	!#w/ 9  		
  	 K	     		 0 "0	0  		s   +D :C D C D C( $C7 :D 	CD CD C%"D $C%%D (	C41D 3C44D 7	D D DD DD	D&%D&c           
          d fd	}t         dd      xs d |dd       |dd       |d       |d       |d       |d	       |d
      d}t         dd       }|rst        |dd      xs d}|dk  rd}t        |dd      xs d}|r4|r2||d<   ||d<   t        dt        dt        ||z  dz                    |d<   t        |dd      xs d|d<   	 ddlm}  |       |d<   t        t        j                  j                  d            r#	  j                         }|t        |      |d<   |S |S # t        $ r Y Xw xY w# t        $ r Y |S w xY w)Nc                 D    t        | d      xs |rt        |d      S dS )Nr   r   )kfbrN  s     rD   r   z_get_usage.<locals>.<lambda>  s%    75!Q/WRGE2q4I UV r   r   r   session_input_tokenssession_prompt_tokenssession_output_tokenssession_completion_tokenssession_reasoning_tokenssession_total_tokenssession_api_calls)r   inputr   r  r  
completionr  callscontext_compressorlast_prompt_tokensr   rm  context_usedcontext_maxd   context_percentcompression_countcompressions)active_countactive_subagentsHERMES_DEV_CREDITSdev_credits_spent_microsr   )r   rF  minroundrd  r  r5   r   r,   r  r   get_credits_spent_microsr  )rN  gr  complast_promptctx_max_async_active_countspents   `       rD   r  r    s   WA,2)+BC+-HI12+,34)*&'	E 5.5D$ d$8!<A?K$ 0!49{$/E.!#*E- '*1c#u[7=RUX=X7Y.Z'[E#$ '.A1 E JnN$7$9 !
 rzz~~&:;<	224E 47J01 L5L    	L	s$   D. 
 D= .	D:9D:=	E
	E
c                     	 t        | dd      xs d}t        | dd      xs d}|r|dk(  rd| dS 	 y# t        $ r Y yw xY w)uE   Light credential check at session creation — returns warning or ''.rG  r   r  no-key-requiredz$No API key configured for provider 'z'. First message will fail.)r   r5   )rN  rw  r  s      rD   _probe_credentialsr  Q  si    eY+1r5*b17Rc..9(C^__ /   s   .3 	??c                 P   t        | t              syg }t        d | j                         D              }|sn-dj	                  d |D              }|j                  d| d       | j                  d      }| j                  d      }t        |t              rst        |j                  d	d      xs d      j                         j                         }|r6|d
vr2t        |t              r"|j                  d      |j                  d       dj	                  |      j                         S )ut   Flag bare YAML keys (`agent:` with no value → None) that silently
    drop nested settings. Returns warning or ''.r   c              3   ,   K   | ]  \  }}|	|  y wr   r   )r  r  vs      rD   r  z'_probe_config_health.<locals>.<genexpr>c  s     >TQAIq>s   
r  c              3   (   K   | ]
  }d | d   yw`Nr   )r  r  s     rD   r  z'_probe_config_health.<locals>.<genexpr>g  s     5a1QCq5   z"config.yaml has empty section(s): uZ   . Remove the line(s) or set them to `{}` — empty sections silently drop nested settings.r   rN  personality>   r  rF  neutralpersonalitieszj`display.personality` is set but `agent.personalities` is empty/null; personality overlay will be skipped. )
r  r   r!  rf  r*   r  r   r6   r7   r  )r  warnings	null_keysr  display_cfg	agent_cfgr  s          rD   r  r  ]  s    c4 H>SYY[>>Iyy59550 7< =	

 '')$K I+t$+//-<BCIIKQQS#AA9d+o.6OO7 88H##%%r   c                  D    	 ddl m}   |        xs dS # t        $ r Y yw xY w)Nr   get_active_profile_namerF  )hermes_cli.profilesr  r5   r  s    rD   _current_profile_namer  ~  s*    ?&(5I5 s    	r  c                    | xs i j                  d      }t        |       j                  d      }| xs i j                  d      rt        |t              rt        |      S |t	        |      S t        |t              rt        |      S i S )NrN  r  r!  )r   r>  r  r   r  )r#  rN  mirror_usages      rD   _session_usage_snapshotr    s}    ](E#G,009L212z,PT7UL!!%  !+L$!?4GRGr   c                 j   t        | xs d      j                         sy	 ddlm} |j	                         5 }|j                  ||       }ddd       y|j                  |j                  |j                  |j                  dS # 1 sw Y   ;xY w# t        $ r t        j                  dd       Y yw xY w)	u  Return the first-class Project owning ``cwd`` for UI status surfaces.

    Backed by the per-profile projects.db (the same store the desktop's project
    tree caches), so the TUI status label, the desktop status bar, and ``/status``
    all name the session's workspace identically. Only explicit, named projects
    resolve here — an auto-discovered repo root has no projects.db row, so it
    falls back to the cwd leaf on every surface.
    r   Nr   projects_db)r   slugrI   primary_pathz!failed to resolve project for cwdTr&  )r6   r7   r  r  connect_closingproject_for_pathr   r  rI   r  r5   r  r*  )r   pdbconnr  s       rD   _project_info_for_cwdr    s     syb>!1  " 	6d**45G	6?**LLLL#00	
 	
		6 	6  84Hs.   B B	
B .B BB  B21B2c           
      *	   |0t         j                         D ]  }|j                  d      | u s|} n t        |      }t	        |      }t        |xs i j                  d      xs t        | dd      xs d      }t               j                  d      xs i j                  d      xs d}|xs i j                  d|      }t        | dd       }d}	t        |t              r5|j                  d      d	u rd
}	nt        |j                  dd      xs d      }	t        | dd       xs |j                  d      xs d}
d	}d}	 ddl
m}m} |rt         ||            nd	}t               }t        |      xs	 |xs |dk(  }i d|j                  dt        | dd            d|j                  dt        | dd            d|	d|
d|
dk(  d|d|dt        |j                  d      t              rt        |j                  d      xs i       ni dt        |j                  d      t              rt        |j                  d      xs i       ni d|dt!        |      dt#        |      dt        |xs d      dt        |xs i j                  d            d|rt%        |xs i |      ndd|xs dd t&        ddd dt)        |      t+               d!}	 dd"lm}m}m}  |       } ||      r ||      |d#<   	 dd$lm}m} ||d%<   ||d&<   | |xs i j                  d'      sj	 dd(lm} i |d<   t        | dg       xs g D ]8  }|d)   d*   }|d   j?                   ||      xs d+g       jA                  |       : 	 	 dd,l!m"}  |       |d<   	 dd-l#m$}  |       |d.<   	 d/|v r|j                  d/      nt        | d0d      xs d|d/<   	 dd1l!m%} dd2lm&}  |d34      |d5<    |       |d6<   | '|xs i j                  d'      stO        |       }|r||d7<   |S # t        $ r d	}Y w xY w# t        $ r Y ;w xY w# t        $ r Y 8w xY w# t        $ r Y w xY w# t        $ r Y w xY w# t        $ r g |d.<   Y w xY w# t        $ r Y w xY w# t        $ r Y w xY w)8NrN  r   r  r   r   r  r  r  Fr  effortr  r  r   )_YOLO_MODE_FROZENr  r  r   r  reasoning_effortr  r  yoloapproval_moder`   skillsr   r6  r  r  titlestored_session_iddesktop_contract)versionrelease_dateupdate_behindupdate_commandr  profile_name)detect_install_method"format_unsupported_install_warningis_unsupported_install_methodinstall_warning)__version____release_date__r  r  r!  )get_toolset_for_toolfunctionrI   otherget_available_skills)get_mcp_statusr  r  r  )get_update_result)recommended_update_command      ?r   r  r  credential_warning)(rQ   ra  r   r>  r  r6   r   r  r  r   rv  r  r  r   r  r5   r5  r  _session_live_titleDESKTOP_BACKEND_CONTRACTr  r  r^  r	  r
  r  r  r  r  model_toolsr  rf  r  hermes_cli.bannerr  tools.mcp_toolr  r  r  r  )rN  r#  	candidater?  r   r   cfg_personalityr  r  r  r  r  r  r  r  session_yolorH  r	  r
  r  _install_methodr  r  r  r  rI   r  r  r  r  warns                                  rD   rR  rR    sp   "))+ 	I}}W%.#	 g&F
w
'C	BM*Tge\2.NTRTK "	28b==mLRPRO=b%%m_EKu&8$?"D)	*e3
  &"#3#7#7"#E#KL5.$7[6::n;U[Y[L DM	M ;FD(565 	 ,-%&P,P-5:PGWUGR%@AFJJz75*b+IJ 	, 		
 	
* 	 	 	Jvzz'?RTX4Yfjj)/R0_a 	jHAUW[6\$vzz(+1r2bd 	s 	%c* 	(- 	s;,"- 	4B++I67 	K$W]K@UW  	[.B!" 	4#$ (1-//D2	
 	
 01(9&H&YD"#<%Y/^ '-R!4!45K!L
	8DMUGR06B }V,W(()=d)C)NwPRSZZ	>13DN!1,.] &( JJ' 7<B 	_7@ 1# >_!;!= '-R!4!45K!L!%()-D%&Ku  J      		  		  ! ]!    s   ==P $P% 7P5 !AQ :Q Q# )Q7 "R P"!P"%	P21P25	QQ	QQ	Q Q #Q43Q47	RR	RRrJ   c                 L    	 ddl m}  || |d      xs dS # t        $ r Y yw xY w)Nr   )build_tool_labelr4  )max_lenr   )agent.displayr$  r5   )rI   rJ   r$  s      rD   	_tool_ctxr'  >  s0    2dB7=2= s    	##c                     |j                  d      }|t        |      sy 	 t        d| t        ||             y # t        $ r Y y w xY w)NrN  rP  )r   r>  r  rR  r5   )r-  r#  rN  s      rD   _emit_session_info_for_sessionr)  G  sJ    KK E}-g6nc=#@A s   9 	AA     c                 F   t        |       t        k  r| j                  d      t        k  r| S t        |       }d}t	        t              D ]#  }| j                  dd|      }|dk  rd} n|dz   }% |}t        |t        |       t        z
        }||kD  r1| j                  d|      }d|cxk  rt        |       dz
  k  rn n|dz   }| |d  j                         }t        dt        |       t        |      z
        }| d | j                  d      }|r
d| d| d}	nd| d}	|	 | S )Nr   r   r   z[showing verbose tail; omitted z	 lines / z chars]
)	r  _TUI_VERBOSE_TEXT_MAX_CHARScount_TUI_VERBOSE_TEXT_MAX_LINESr  rfindrF  findlstrip)
r   idxr   r  
line_start
next_breaktailomitted_charsomitted_lineslabels
             rD   _cap_tui_verbose_textr:  \  sF   D	00JJt::
d)CE./ jjq#&7Ea J
CI(CCDEzYYtU+

*SY]*NE< D3t9s4y01M%L&&t,M-oY}oY@ 	
 2-	JWTFr   c                 j    	 ddl m}  |t        |       d      }t	        |      S # t        $ r Y yw xY w)Nr   redact_sensitive_textT)forcer   )agent.redactr=  r6   r5   r:  )r   r=  redacteds      rD   _redact_tui_verbose_textrA    s;    6(T$? !**  s   & 	22c                     	 t        j                  | xs i ddt              }t	        |      S # t        $ r t        | xs i       }Y t	        |      S w xY w)Nr   F)indentensure_asciirF  )r   r   r6   r5   rA  )rJ   r  s     rD   _tool_args_textrE    sU    jjAE3O $C((  $*"o#C((s   !. AAc                 ~    	 ddl m}  ||       }t	        |      S # t        $ r t        |       }Y t	        |      S w xY w)Nr   )_multimodal_text_summary)agent.tool_dispatch_helpersrG  r5   r6   rA  )r  rG  r  s      rD   _tool_result_textrI    sF    H&v. $C((  &k#C((s    <<secondsc                     | y| dk  r| ddS | dk  rt        |        dS t        t        t        |             d      \  }}|r| d| dS | dS )Nr   r   .1fr  <   zm r  )r  divmodr  )rJ  minssecss      rD   _fmt_tool_durationrQ    sr    |#a  |.!##E'N+R0JD$!%dV2dV15dV1:5r   c                     | }|D ]%  }t        |t              s y |j                  |      }' t        |t              rt	        |      S d S r   )r  r   r   r_  r  )r   r.   currw  s       rD   _count_listrT    sJ    
C #t$ggcl "#t,3s86$6r   
duration_sc                 $   	 t        j                  |      }t        |      }|rd| nd}d }| dk(  r/t	        |t
              rt        |dd      }|Qd| d|dk(  rd	nd
 }nA| dk(  r<t	        |t
              r,t        |d      xs t        |dd      }|d| d|dk(  rdnd }t	        |t
              rE|j                  d      r4t        |j                  d      xs d      j                         }|r| | S |r| | S d S # t        $ r d }Y w xY w)N in r   
web_searchr  webzDid r  r   searchsearchesweb_extractresultsz
Extracted pagepagesfallback_warning)
r   r   r5   rQ  r  r   rT  r   r6   r7   )	rI   r  rU  r  dursuffixr   nr   s	            rD   _tool_summaryrd    s5   zz&! Z
(C tC5\bFD|
4 6fe,=!A!q&hjABD		:dD#9i(PKfi,P=s!a1fF'#BCD$$((+=">dhh128b9??AYvh'' $dVF8.$.-  s   D DDtool_call_idc                 x   t         j                  |       }|N	 ddlm}  |||      }|||j	                  di       |<   t        j                         |j	                  di       |<   t        |       r;||t        ||      d}t        |       rt        |      }|r||d<   t        d| |       y y # t
        $ r Y yw xY w)Nr   )capture_local_edit_snapshotedit_snapshotstool_started_at)tool_idrI   context	args_text
tool.start)rQ   r   r&  rg  rf  r5   r3   r<  r'  r:  rE  r  )	r-  re  rI   rJ   r#  rg  ri  r  rl  s	            rD   _on_tool_startrn    s    mmC G	A24>H#IQ""#3R8F CG))+,b1,?c"# t,

 C '-I'0$ 	lC) #  		s   &B- -	B98B9c                    |||d}t         j                  |       }d }d }|D|j                  di       j                  |d       }|j                  di       j                  |d       }|rt	        j                         |z
  nd }	|	|	|d<   	 t        j                  |      |d<   t        |||	      }
|
r|
|d<   t        |       rt        |      }|r||d<   |dk(  rY	 t        j                  |      }t        |t              r3t        |j                  d	      t              r|j                  d	      |d	<   	 d
dlm} g } ||||||j                         rdj#                  |      |d<   t%        |       s|j                  d      rt'        d| |       y y # t        $ r ||d<   Y w xY w# t        $ r Y ~w xY w# t        $ r Y Yw xY w)N)rj  rI   rJ   rh  ri  rU  r  summaryresult_texttodotodosr   )render_edit_diff_with_delta)function_argsri  print_fnr   inline_difftool.complete)rQ   r   rf  r(  r3   r   r   r5   rd  r:  rI  r  r   r_  r&  rt  r  r*   r<  r  )r-  re  rI   rJ   r  r  r#  ri  
started_atrU  rp  rq  r  rt  rendereds                  rD   _on_tool_completer{    s   &dCGmmC GHJ%%&6;??dS''(92>BB<QUV
-7z)TJ *# JJv. D&*5G$	'/%0GM"v~	::f%D$%*TXXg5F*M#'88G#4 = &__
 &*YYx%8GM" c"gkk-&@osG, 'A=  #"#  		  s7   	F AF# 13F2 F F #	F/.F/2	F>=F>preview_argsc           
      T	   t        |       sy |dk(  r|ry |dk(  r|r|j                  d      }t        |t              sy t	        |j                  d      xs d      t	        |      t	        |j                  d      xs d      |j                  dg       D cg c]  }t	        |       c}t        |j                  d	d
            d}t        d| |       y |dk(  r-|r+dt	        |      i}t        |       rd|d<   t        d| |       y |dk(  ru|rst	        |      t	        |xs d      d}	|j                  d      |j                  d      |	d<   |j                  d      |j                  d      |	d<   t        d| |	       y |dk(  rt        d| dt	        |xs d      i       y |j                  d      rt	        |j                  d      xs d      t        |j                  d      xs d      t        |j                  d      xs d      d}|j                  d      rt	        |d         |d<   |j                  d       rt	        |d          |d <   |j                  d!      rt	        |d!         |d!<   |j                  d"      t        |d"         |d"<   |j                  d#      rt	        |d#         |d#<   |j                  d$      t        |d$         |d$<   |j                  d%      r|d%   D 
cg c]  }
t	        |
       c}
|d%<   d&D ]%  }|j                  |      }|	 t        |      ||<   ' |j                  d'      r|d'   D cg c]  }t	        |       c}|d'<   |j                  d(      r|d(   D cg c]  }t	        |       c}|d(<   |j                  d)      rt        |d)         |d)<   |rt	        |      |d*<   |rt	        |      |d<   |j                  d+      rt	        |d+         |d+<   |j                  d,      rt	        |d,         |d,<   |j                  d-      t        |d-         |d-<   |r!|d.k(  rt	        |      |d/<   t	        |      |d<   |d0k7  rt        || |       t        ||       y y c c}w c c}
w # t        t        f$ r Y w xY wc c}w c c}w )1Nztool.startedztool.output_riskrisk_metadatare  r   risklowfindingsr@  F)rj  rI   r  r  r@  zreasoning.availabler   Tr  zmoa.reference)r9  r   	moa_indexindex	moa_countr.  zmoa.aggregating
aggregatorz	subagent.goal
task_countr   
task_indexr   )r  r  r  subagent_id	parent_idchild_session_iddepthr   
tool_countr"  )input_tokensoutput_tokensreasoning_tokens	api_calls
files_readfiles_writtenoutput_tail	tool_namerN  rp  duration_secondssubagent.tooltool_previewsubagent.text)r<  r   r  r   r6   r   r  r:  
startswithr  rS  r>  r_  r  _mirror_subagent_to_child)r-  r  rI   r|  r}  _kwargsr  r&  r  ref_payloadr  int_keyr%  r  s                 rD   _on_tool_progressr    s    "#&^# 	''D;;/(D)7;;~6<"=IV,56/7||J/KLtTLX\\*e<=&
 	 #w/**w&,c'l%;C !%GI#S'2_$ Y2&*
 ;;{#/#*;;{#;K ;;{#/#*;;{#;K osK0&&|S_&EF[)F+1r2gkk,7<1=gkk,7<1=
 ;;}%%()?%@GM";;{##&w{';#<GK ;;)**-g6H.I*JG&';;w+"77#34GG;;w"77#34GG;;|$0$'(=$>GL!;;z"3::3F"Ga3q6"GGJ
 	G ++g&C'*3xGG$	 ;;|$5<\5J$KSV$KGL!;;'8?8P'Q1A'QGO$;;}%%)'-*@%AGM"#&t9GK !'lGFO;;x  #GH$5 6GH;;y!!$WY%7!8GI;;)*6*/8J0K*LG&'z_4&)'lGN#!'lGFO (*c7+!*g6} *; Md #H ":.  %L'Qs*   R 
3R%R
R =R%
RR_child_mirrors_active_child_runsg      @	child_keyc                 t    t         j                  |       }|d uxr t        j                         |z
  t        k  S r   )r  r   r3   _CHILD_RUN_STALE_S)r  tss     rD   r  r    s2    					*BT>Etyy{R/3EEEr   c                 d   t        |j                  d      xs d      }|sy | dk(  rt        j                  |d        nt	        j                         t        |<   t        |      }||d   j                  d      &t        5  t        j                  |d        d d d        y |d   }t        5  t        j                  |dd dd      }|d	   sd
|d	<   t        d|       | dk(  r2t        |j                  d      xs d      x}rt        d|d|i       n~| dk(  r2t        |j                  d      xs d      x}rXt        d|d|i       nG| dk(  r5t        |j                  d      xs d      x}r!t        d|d| di       n| dk(  r|d   rt        d||d          |dxx   dz  cc<   t        |j                  d      xs d      d| d|d    i d}t        |j                  d      xs |j                  d      xs d      x}r||d<   ||d<   t        d||       np| dk(  rk|d   rt        d||d          t        |j                  d      xs |j                  d      xs d      }	t        d |d|	i       t        j                  |d        d d d        y # 1 sw Y   y xY w# 1 sw Y   y xY w)!Nr  r   zsubagent.completer   rN  r   F)seq	open_toolstartedr  Tmessage.startzsubagent.thinkingr   reasoning.deltar  message.deltazsubagent.startr   r  r  rx  r  r  toolz
submirror:r  )rI   rj  rJ   r  r|  rm  rp  rL  )
r6   r   r  r(  r3   _find_live_session_by_key_child_mirrors_lockr  rf  r  )
r  r  r  livecsidstr   r  r|  rp  s
             rD   r  r    s   GKK 239r:I ((y$/(,		9% %Y/D|tAw{{7+7  	0y$/	07D	 %0&&y!$[`2ab)} ByM/4(,,7;;v.4"55t5'~>?* 7;;v.4"55t5otfd^<++ 7;;v.4"55t5otfbk-BC?*+otR_=uINIGKK4>?'	{!BuI;?D
 gkk.9VW[[=PVTVWWwW")Y"B{O,d+..+otR_='++i0MGKK4GM2NG$dVW,=>y$/K%0 %0		0%0 %0s    J+G&J&J#&J/c                       fd fdd fd	 fd fd fd fdd fd	 fd	 fd
 fdd fd	d}t               rdd fd
|d<   |S )Nc                      t        | ||      S r   )rn  )tc_idrI   rJ   r-  s      rD   r   z_agent_cbs.<locals>.<lambda>  s    d:
 r   c                 "    t        | |||      S r   )r{  )r  rI   rJ   r  r-  s       rD   r   z_agent_cbs.<locals>.<lambda>  s    DUdFE
 r   c                 $    t        | |||fi |S r   )r  )r  rI   r|  rJ   kwargsr-  s        rD   r   z_agent_cbs.<locals>.<lambda>  s"    ctT7Dd
4:d
 r   c                 <    t              xr t        dd| i      S )Nztool.generatingrI   )r<  r  )rI   r-  s    rD   r   z_agent_cbs.<locals>.<lambda>  s&    *@*E +:#S64.9 r   c                 "    t        dd| i      S )Nzthinking.deltar   r  r   r-  s    rD   r   z_agent_cbs.<locals>.<lambda>  s    %0@#PT~*V r   c                 "    t        dd| i      S )Nreactionrr  r  )rr  r-  s    rD   r   z_agent_cbs.<locals>.<lambda>  s    %
C&$*P r   c                 N    t        dd| it              r	ddi      S i       S )Nr  r   r  T)r  r:  r  s    rD   r   z_agent_cbs.<locals>.<lambda>  s=    5TR3CC3Hy$/R,
  OQR,
 r   c                 R    t        t        |       |d       S t        |            S r   )r|  r6   )rr  r   r-  s     rD   r   z_agent_cbs.<locals>.<lambda>  s)    >TDLD4
 69$i4
 r   c                     t        d| j                  | j                  | j                  | j                  | j
                  | j                  d      S )Nznotification.show)r   levelrr  ttl_msrw  r   )r  r   r  rr  r  rw  r   )rc  r-  s    rD   r   z_agent_cbs.<locals>.<lambda>  sA    U((uudd&
 r   c                 "    t        dd| i      S )Nznotification.clearrw  r  )rw  r-  s    rD   r   z_agent_cbs.<locals>.<lambda>  s    U #s|.
 r   c                 $    t        d| |d      S )Nzclarify.request)questionri  r~  )qcr-  s     rD   r   z_agent_cbs.<locals>.<lambda>  s    sq$A*
 r   c           
      h    t        dd| fd|ffD ci c]  \  }}|	|| c}}d      S c c}}w )Nzterminal.read.requestr   r.     r   r  )r   r.  r  r  r-  s       rD   r   z_agent_cbs.<locals>.<lambda>  sE    # '/'51ABTdaamQTT	B
  Us   
..)tool_start_callbacktool_complete_callbacktool_progress_callbacktool_gen_callbackthinking_callbackreaction_callbackreasoning_callbackstatus_callbacknotice_callbacknotice_clear_callbackclarify_callbackread_terminal_callbackFalready_streamedc                H    t        dt        |       t        |      d      S Nzmessage.interim)r   r  )r  r6   r   r   r  r-  s     rD   r   z_agent_cbs.<locals>.<lambda>"  s$    E!T=M8NO5 r   interim_assistant_callbackNNNr   r  )r  )r-  	callbackss   ` rD   
_agent_cbsr    sj     
#
#
:V Q



"


#
_5Ix ()-2  	./ r   task_id_namec                    |syt        | xs d      }d}d}t        5  |t        v r|t        |   }}nUt        j                         D ]>  \  }}|j	                  d      |k(  s t        |j	                  d      dd      |k(  s:||}} n ddd       |yt        j                  j                  t        j                  j                  t        |                  }t        j                  j                  |      sy||d<   d|d<   t        |       t        |      5 }	|	#	 |	j                  |j	                  dd      |       ddd       t#        ||       	 |j	                  d      }
|
t%        |
|      n|t'        |      t)        |      dd}t+        d||       y# 1 sw Y   xY w# t        $ r t        j!                  d	d
       Y w xY w# 1 sw Y   xY w# t        $ r t        j!                  dd
       Y yw xY w)u1  Intentional workspace move from the project_* tools: re-anchor the live
    session's cwd to the chosen project's folder and push session.info so the
    desktop follows (refresh tree + scope into the project). This is the ONLY
    auto-cwd path — driven by an explicit tool call, never a terminal `cd`.Nr   r   rN  r  r   Tr  z'failed to persist project workspace cwdr&  r   r6  r  r  rP  z8failed to emit session.info after project workspace move)r6   re  rQ   rf  r   r   r,   r.   r  r  r  r  r  r  r5   r  r*  r  rR  r5  r  r  )r  r.   r  rw  r-  r#  cand_sidcandr  rk  rN  rH  s               rD   _apply_project_workspacer  ,  s   
  gm
C
CG	 )	#C"+//"3 $88M*c1WTXXg=NP\^b5cgj5j#+TC	 wwrww11#d)<=H77=="GEN"GN'"	W	 W>W%%gkk-&DhOW gx0`G$   %)  -h70:	 	 	nc4(S 0  WFQUVW	W W,  `OZ^_`sO   A"F FG"F%AG F"% GGGGG G:9G:c                 t     ddl m} ddlm} ddlm}  | fd        |t               d fd	} ||       y )Nr   )set_sudo_password_callback)set_secret_capture_callback)set_project_workspace_callbackc                  "    t        d i d      S )Nrq  x   r   r  r6  s   rD   r   z!_wire_callbacks.<locals>.<lambda>l  s    vnc2s'S r   c                 v    || d}|r||d<   t        d|      }|sd| ddddS dd	lm} i  || |      dd
dS )N)r  env_varr  rr  TFskipped)r}  	stored_as	validatedr  rK  r   )save_env_value_securer   )r  rK  )r~  r^  r  )r  r  r  plr%  r  r-  s         rD   	secret_cbz"_wire_callbacks.<locals>.secret_cbo  sm    73%BzN%sB/$"$  	<
#GS1

 	
r   r   )r  r  tools.skills_toolr  tools.project_toolsr  r  )r-  r  r  r  r  s   `    rD   r  r  g  s-    >=BST"#;<
*  	*r   c                 .   t        | t              r{| j                  dd      g}| j                  d      r|j                  d| d           | j                  d      r|j                  d| d           dj	                  d |D              S t        |       S )	Nr  r   tonezTone: stylezStyle: r   c              3   &   K   | ]	  }|s|  y wr   r   r  r  s     rD   r  z-_render_personality_prompt.<locals>.<genexpr>  s     /qQ/   )r  r   r   r  r*   r6   )rE  partss     rD   _render_personality_promptr     s    %?B/099VLL6%-1299WLL75>"234yy/E///u:r   c                    	 ddl m}  |       j                  d      xs i j                  di       xs i S # t        $ r 	 ddlm}  |       j                  d      xs i j                  di       xs i cY S # t        $ r< | xs
 t               } | j                  d      xs i j                  di       xs i cY cY S w xY ww xY w)Nr   )load_cli_configrN  r  r  )r8  r  r   r5   r^  r  r  )r  r  _load_full_cfgs      rD   _available_personalitiesr    s    K'!%%g.4"99/2NTRTT K	KG"$((17R<<_bQWUWW 	K$CGGG$*//DJJ	KKs.   36 	B? 3A63B?6A B;6B?:B;;B?c                 D   t        | xs d      j                         }|j                         }|r|dv ryt        |      }||vrNt	        |      }dj                  d |D              }d| d}|r|d| z  }t        |      |d	z  }t        |      |t        ||         fS )
Nr   >   r  rF  r  )r   r   r  c              3   (   K   | ]
  }d | d   ywr  r   )r  rc  s     rD   r  z(_validate_personality.<locals>.<genexpr>  s     61!Ah6r  zUnknown personality: `z`.z

Available: `none`, z

No personalities configured.)r6   r7   r  r  r!  r*   r>  r   )rE  r  r  rI   r  names	availablebases           rD   _validate_personalityr
    s    
ekr

 
 
"C99;D499,S1M= }%II666	'uB/-i[99D  66D+M$,?@@@r   c                     | yt        | t              r| j                         S t        | t              rdj	                  d | D              S t        |       j                         S )zHNormalize config prompt values from YAML before handing them to AIAgent.r   r   c              3      K   | ]7  }t        |      j                         st        |      j                          9 y wr   )r6   r7   r  r&  s     rD   r  z_prompt_text.<locals>.<genexpr>  s(     RtD	@QT*Rs   ??)r  r6   r7   r_  r*   rE  s    rD   _prompt_textr    sR    }%{{}%yyRuRRRu:r   
new_promptr  c                 B   |sy||d<   |j                  d      }|rx|xs d|_        |rd| d}nd}|d   5  |d	   j                  d
|d       t        |j                  dd            dz   |d<   ddd       t	        |      }t        d| |       d|fS y# 1 sw Y   &xY w)u  Apply a personality change to an existing session without resetting history.

    Updates the agent's ephemeral system prompt in-place so the new personality
    takes effect on the next turn.  The cached base system prompt is left intact
    (ephemeral_system_prompt is appended at API-call time, not baked into the
    cache), which preserves prompt-cache hits.

    Also injects a system-role marker into the conversation history so the model
    knows to pivot its style from this point forward (without this, LLMs tend to
    continue the tone established by earlier messages in the transcript).

    Returns (history_reset, info) — history_reset is always False since we
    preserve the conversation.
    )FNr  rN  Nz[System: The user has changed the assistant's personality. From this point forward, adopt the following persona and respond accordingly: ]zv[System: The user has cleared the personality overlay. From this point forward, respond in your normal default style.]rO  rP  r*  r  r1  r   r   rP  F)r   ephemeral_system_promptr  r  rR  r  )r-  r#  r  r  rN  r  rH  s          rD   _apply_personality_to_sessionr    s    " (GMKK E(2(:d%   *|1. R  ^$ 	TI%%v&&IJ),W[[9JA-N)ORS)SG%&	T U#nc4(d{	T 	Ts   9BBc                 $   	 t        t        j                  j                  dd      xs d      }|dkD  r|S 	 | j                  d      xs i }t        |j                  d      xs | j                  d      xs |      S # t        t
        f$ r Y Ww xY w)NHERMES_TUI_MAX_TURNSr   r   rN  	max_turns)r  r,   r  r   rS  r>  )r  rF  env_maxr  s       rD   _cfg_max_turnsr    s    bjjnn%;R@EAFQ;N   &BIy}}[)LSWW[-ALWMM z" s   3A= =BBc                     t         j                  j                  dd      } g }t               }| j	                  dd      j                  d      D ]<  }|j                         }|s||vs|j                  |       |j                  |       > |S )NHERMES_TUI_SKILLSr   r   r
  )	r,   r  r   r^  r  r  r7   r%  r  )r  r   r  partr&  s        rD   _parse_tui_skills_envr    s{    
**..,b
1CFUDD#&,,S1  zz|D$HHTNMM$	 
 Mr   c                  .    ddl m}   | t                     S )a  Return the configured fallback chain for TUI-created agents.

    Delegates to the shared ``get_fallback_chain`` helper so the TUI path
    stays in parity with ``HermesCLI.__init__`` and ``gateway/run.py``:
    ``fallback_providers`` is the primary source of truth and keeps its
    order, with legacy ``fallback_model`` entries merged in afterwards
    (deduped on provider/model/base_url).
    r   get_fallback_chain)hermes_cli.fallback_configr   r  r  s    rD   _load_fallback_modelr"    s     >ik**r   c                     t        | d      rt        | d      xs g S t        | d      rt        | dd      S t               S )zOReturn an agent's fallback chain without rehydrating deliberately empty chains._fallback_chain_fallback_modelN)r`  r   r"  rJ  s    rD   _agent_fallback_modelr&    sD    u'(u/06B6u'(u/66!!r   c                 T   t               }i dt        | dd       xs d dt        | dd       xs d dt        | dd       xs d dt        | dd       xs d dt        | dd       xs d dt        | dd       xs d dt        | dd       xs
 t               dt        |d	      d
t        | d
d       xs
 t	               dddddt        | dd       xs d dt        | dd       dt        | dd       dt        | dd       dt        | dd       dt        | dd      t        | dd       t        | dd       |t        | dd       xs# t        t        t        | dd      xs d            t        | dd       xs
 t               t        t        | di       xs i       dt               t        |       d	S )Nr  rG  r  r  acp_commandacp_argsr   max_iterations   enabled_toolsets
quiet_modeTverbose_loggingFr  providers_allowedproviders_ignoredproviders_orderprovider_sortprovider_require_parametersprovider_data_collectionopenrouter_min_coding_scorer  r   r  request_overridesr  )	r4  r5  r  r  r  r6  r  r  fallback_model)r  r   r  r  r3  r  r6   r  r   ra  r&  )rN  r  r  s      rD   _background_agent_kwargsr8    s1   
+C GE:t4< 75)T2:d  	GE:t4<  	GE:t4<	 
 	wumT:Bd  	GE:t4<  	.B.2B  	.b1  	GE+=tD $!#  	d  	5  	"752KT#R $  	WU,?F   	WU,?F! " 	75*;TB# $ 	>% & 	&w0%(
' , %,E3Mt$T'.u6SUY'Z#E+=tD J!#geWb&A&GR"HI~t<T@R@T!'%1Db"I"ORPi/6?   r   c                 L    t        | |      }|j                  ddgd dd       |S )Nr  r'   T)r,  r  skip_memory)r8  rG  )rN  r  r  s      rD   _ephemeral_preview_agent_kwargsr;  B  s4    %eW5F
MM!+V 4	
 Mr   max_messagesmax_tool_charsc                 $   	 | d   5  t        | j                  dg       xs g       }ddd       sg S d}t        t	        |      dz
  dd      D ]  }||   j                  d      dk(  s|} n t        dt	        |      |z
        }|t        ||      }g }||d D ]  }t        |t              s|j                  d      }	|	d	vr*|j                         D 
ci c]  \  }
}|
d
k7  s|
| }}
}|	dk(  rH |j                  d      }t        |t              r&t	        |      |kD  r|d| dt	        |       dz   |d<   |j                  |        |S # 1 sw Y   +xY w# t        $ r# t        | j                  dg       xs g       }Y Yw xY wc c}}
w )u  Distill the parent session's recent history into a context the
    ephemeral preview-restart agent can actually use.

    The restart agent has no idea what app the user was building, what
    server they ran, what cwd was active, or which port belongs to which
    project. Without this, it would take the bare URL + console logs and
    guess — usually starting the wrong thing.

    We keep the last ``max_messages`` messages from the parent session so
    the restart agent sees recent user prompts, assistant replies, and
    most importantly any terminal/tool calls. Tool result payloads are
    truncated so we don't blow the context window with file dumps.
    rO  rP  Nr   r  r)  r*  r   )r*  	assistantr  systemr  r  r+  z
... (truncated, original z chars))r_  r   r5   r  r  rF  r  r  r   rf  r6   r  )r#  r<  r=  rP  last_user_idxr3  r   trimmedr   r)  r  r  rV  r+  s                 rD   _preview_restart_historyrC  N  s   9^$ 	=7;;y"5;<G	=
 	
 MS\A%r2. 3<F#v-M
 3w<,./E E=)Guv #t$wwv>>!$AA[0@1AA 6>dhhy)G'3'CL>,IO^,3CL>IJ Y 	t#& NS	= 	= 9w{{9b17R896 Bs3   E  EE F&FEE (F	F	c                    	 t        j                  |      }t        |t              sy| dk(  rpt        |j                  d      xs d      j                         }|j                  d      }|r|dd  S |j                  d      rd|j                  d       S |d| S t        |j                  d	      xs d      j                         d d
 S # t        $ r Y yw xY w)Nr   r  r   	exit_codeiPr  zBackground process started: zterminal exited with code r     )r   r   r5   r  r   r6   r   r7   )rI   r  r  r   rE  s        rD   _preview_tool_result_previewrG    s    zz&! dD!zTXXh'-2.446HH[)	%&>!88L!1$((<2H1IJJ /	{;;txx &B'--/66!  s   C 	CCr  c           
          i ddt         dt         dd f fddt         dt         dt        dd ffd}dt         dt         d	t        d
t         dd f
fd}ddt         dt         d z  dt         d z  dd ffd}|||fddfd	dS )NrK  r  r   c                 h    t        | xs d      j                         }|rt        d||d       y y )Nr   preview.restart.progress)r  r  r   )r6   r7   r  )rK  r  r   r  r  s      rD   progressz,_preview_restart_callbacks.<locals>.progress  s8    7=b!''),f'TYcg6hi r   re  rI   rJ   c                 t    t        j                          | <   t        ||      } d| |rd| nd        y )NzRunning r%   r   )r3   r'  )re  rI   rJ   r  rK  ry  s       rD   
tool_startz._preview_restart_callbacks.<locals>.tool_start  s=    #'99;
< d#8D6Bse*!<=>r   r}  r  c                    t        j                          j                  | t        j                                z
  }t        |||      xs d| |rdt        |       nd }t	        ||      } ||rd| z          y dz          y )Nz	Finished rW  r   r   )r3   r   rd  rQ  rG  )	re  rI   r}  r  rU  rp  r   rK  ry  s	          rD   tool_completez1_preview_restart_callbacks.<locals>.tool_complete  s    YY[:>>,		#LL
fj9  Oy  {EQUVhisVtUuOv  KM  ON  >O-dF;VbM<=<=r   r  r|  c                 n    |r t        |             y |r | j                  dd       d|        y y )Nr  r  r%   )r6   r  )r  rI   r|  r  rK  s       rD   r  z1_preview_restart_callbacks.<locals>.tool_progress  s;    S\"
**345Rv>? r   c                      d|        S )Nz
Preparing r   )rI   rK  s    rD   r   z,_preview_restart_callbacks.<locals>.<lambda>  s    (Zv3F*G r   c                 $     ||      S |       S r   r   )rr  r   rK  s     rD   r   z,_preview_restart_callbacks.<locals>.<lambda>  s    8DDTD3_ Z^3_ r   )r  r  r  r  r  )rH  r  r   )r6   r   )r  r  rM  rO  r  rK  ry  s   ``   @@rD   _preview_restart_callbacksrS    s    #%Jj# jc jt j
? ?C ?t ? ?
>C >s >4 > >QU >@# @S4Z @t @jn @  *"/"/G_ r   c                 z   t        |d         }	 |j                  dd        |j                  dd        |j                  dd        |j                  dd        t        | |d   |d   t        |            }t	        |       ||d<   t               |d<   g |d	<   i |d
<   d|d<   d|d<   t               |d<   t               |d<   i |d<   |d   5  g |d<   t        |j                  dd            dz   |d<   d d d        t        ||      }t        d| |       t        | |       |S # t	        |       w xY w# 1 sw Y   @xY w)Nr   r5  r6  r7  rv  r  r  rN  r  r2  rh  r   image_counterFr  r  r5  ri  rO  rP  r1  r   rP  )r  r(  r  r2  r  r  r   r  r  r   rR  r  r?  )r-  r#  r  	new_agentrH  s        rD   _reset_session_agentrX    sm   !'-"89F' 	$d+/62D9,d3M"}--g6	
	 	v& GG#7#9G !#G "G GOGI 4 6G$<$>G !!#G		  P	%(5F)J%Ka%O!"P G,D	.#t$#w'K! 	v&P Ps   A&D! 'D1!D.1D:c                      	 ddl m}m  |       syd fd}t	        j
                  |d  d      j                          y# t        $ r Y yw xY w)	u  Refresh a session's tool snapshot when MCP discovery lands late.

    The agent snapshots ``agent.tools`` once at build time and never re-reads
    the registry (run_agent/agent_init). ``_make_agent`` briefly joins the
    background MCP discovery thread (``wait_for_mcp_discovery``, bounded by the
    ``mcp_discovery_timeout`` config value, default 1.5s) so
    already-spawning servers land in that snapshot — but a server that takes
    longer than the bound to connect (common for an HTTP MCP server on first
    connect) lands *after* the agent is built. Its tools are then absent from
    both the agent and the banner for the whole session, even though the
    classic CLI shows them (the CLI re-derives ``get_tool_definitions`` at
    banner render time, which re-waits, so it picks them up).

    This schedules an off-critical-path daemon that waits for discovery to
    finish, then rebuilds the snapshot and re-emits ``session.info`` so both
    the agent's callable tools and the banner count catch up — the same
    rebuild ``/reload-mcp`` performs, but automatic.

    Cache safety: the rebuild only runs while the session is still pre-first-
    turn (no API call made yet → nothing cached to invalidate). If the user
    has already sent a message, we leave the snapshot frozen rather than
    invalidate the prompt cache mid-conversation — those late tools then
    require an explicit ``/reload-mcp`` (which gates on user consent), exactly
    as today. No-op when discovery already finished before the agent build.
    r   )mcp_discovery_in_flightjoin_mcp_discoveryNc                      d      sy t         5  t        j                        } | | j                  d      ur
	 d d d        y t        t	        dd      xs d      dkD  st        t	        dd      xs d      dkD  r
	 d d d        y 	 ddlm}  |d	      }|s
	 d d d        y t        |       }d d d        t        d       y # t        $ r)}t        j                  d
|       Y d }~d d d        y d }~ww xY w# 1 sw Y   LxY w)N      >@r   rN  _user_turn_countr   _api_call_countrefresh_agent_mcp_toolsT)r-  z9Late MCP refresh: tool snapshot rebuild failed for %s: %srP  )re  rQ   r   r  r   r  ra  r5   r  r   rR  r  )r#  ra  addedr!  rH  rN  r[  r-  s        rD   _wait_then_refreshz6_schedule_mcp_late_refresh.<locals>._wait_then_refresh
  s    "$/ 	1mmC(G'++g"6e"C		1 	1 GE#5q9>Q?!Cwu&7;@qAAE	1 	1
B/$G 3	1 	14 !0D5	18 	nc4(  O
 -	1 	1 !	1 	1sA   ,C?;C?C
C?(C?
	C<C7*C?7C<<C??Dztui-mcp-late-refresh-Tr8  r   )tui_gateway.entryrZ  r[  r5   r   r   r   )r-  rN  rZ  rc  r[  s   ``  @rD   r  r    sZ    4Q #$!)D !$SE* egW  s   A 	AAc                   2    e Zd ZU eed<   edz  ed<   eed<   y)_RuntimeFallbackResolutionr  Nselected_modelused_fallback)r9   r   r   r   __annotations__r6   r   r   r   rD   rf  rf  3  s    M$Jr   rf  resolve_kwargsc                    ddl m} ddlm} | xs i }	 t	         |di |dd      S # |$ r}t               xs g }|D ]  }t        |t              st        |j                  d      xs d      j                         }t        |j                  d      xs d      j                         }|r|sq	 dd	lm}	 ||d
}
|j                  d      r|d   |
d<    |	|      }|r||
d<    |di |
}ddl} |j                  t              j!                  d|||       t	        ||d      c cY d}~S # t"        $ r Y w xY w  d}~ww xY w)ad  Resolve the primary runtime or one complete provider/model fallback.

    Setup-time auth fallback only accepts entries with both fields. Provider-
    only entries are skipped so the unavailable primary model can never leak
    into a different runtime. ``used_fallback`` remains explicit rather than
    overloading a nullable model as control flow.
    r   )	AuthErrorr]  NFr  r   r   )resolve_entry_api_keyrc  target_modelr  explicit_base_urlexplicit_api_keyz5Primary auth failed (%s), falling back to %s model %sTr   )hermes_cli.authrl  r  r^  rf  r"  r  r   r6   r   r7   r!  rm  logging	getLoggerr9   r   r5   )rj  rl  r^  r  primary_excfb_chainr  fb_providerfb_modelrm  	fb_kwargs
fb_api_keyr  rs  s                 rD   _resolve_runtime_with_fallbackr{  9  si    *D!rF')$.v.
 	

  !')/R 	EeT*eii
39r:@@BK599W-34::<HhL "-$,#	 99Z(5::5FI12259
4>I012?Y?!!!(+33K	 2'8TJJ ;	> 	C!s@   ' E BD;/A3D*"D;$E *	D63D;5D66D;;E rw  r5  r  r9  r:  r  c	                 
   ddl m}	  |	|xs ||      }
|
|
S ddlm} 	 ddlm}  |        	 ddlm}  |        t               }|j                  d      xs i }t        |j                  dd            }t               }|rddlm}  |||xs |	      \  }}}|rHd
j                  |      }|r't        j!                  d|d
j                  |             nt#        d|       |r(dj                  d ||fD              j%                         }t'        |t(              r5|j                  d      r#t+        |j                  d      xs d      }|j                  d      xs |xs d }|j                  d      }|j                  d      }|j                  d      }i }t+        |xs d      j%                         j-                         dk(  rddlm}  ||xs d       }|r|}|r||d<   ||d<   |xs d |d<   t3        |      }|j4                  }|j6                  r$|j8                  st;        d      |j8                  }n|r||d<   |r||d<   |rx||d<   nrt=               \  }}t'        |t*              r|r|}|r|}t3        ||xs d d      }|j4                  }|j6                  r#|j8                  st;        d      |j8                  }t?               }  |dBi d|dtA        |d      d|j                  d      d|j                  d      d|j                  d      d|j                  d      d|j                  d      d |j                  d!      d"|j                  d"      d#d$d%d&d'||ntC        t+        |xs d            d(||n	tE               d)tG               d*| j                  d+      d,| j                  d-      d.| j                  d/      d0| j                  d1      d2| j                  d3d&      d4| j                  d5      d6tI        |      d7|xs |d8||n	tK               d9|xs d d:tM        tN        jP                  j                  d;            d<tM        tN        jP                  j                  d=            d>tM        tN        jP                  j                  d?            d@tM        tN        jP                  j                  d?            dAtS               tU        |       S # t        $ r Y w xY w# t        $ r Y w xY w)CNr   )maybe_build_synthetic_agentAIAgent)wait_for_mcp_discoveryrN  r  r   )build_preloaded_skills_promptr  r  zoUnknown skill(s) requested, skipping: %s. Continuing with: %s. List available skills with `hermes skills list`.zUnknown skill(s): rr  c              3   &   K   | ]	  }|s|  y wr   r   )r  r  s     rD   r  z_make_agent.<locals>.<genexpr>  s      (4(r  r   r  r  rG  r  r  r  r  rp  rc  ro  z&Auth fallback resolved without a modelrn  r*  Z   r(  r   r)  rJ   credential_poolr-  Tr.  Fr  r  r,  r/  onlyr0  ignorer1  orderr2  r  r3  require_parametersr4  data_collectionr  r  r  r  checkpoints_enabledHERMES_TUI_CHECKPOINTSpass_session_idHERMES_TUI_PASS_SESSION_IDskip_context_filesHERMES_IGNORE_RULESr:  r7  r   )+tui_gateway.synthetic_turnr}  	run_agentr  hermes_cli.mcp_startupr  r5   rd  r  r   r  r  agent.skill_commandsr  r*   r  r   r>  r7   r  r   r6   r  r  r  r{  r  rh  rg  r   r  r  r  r  r  r3  r  ra  r   r,   r  r"  r  )!r-  rw  r  r  r5  r  r9  r:  r  r}  	syntheticr  r  r  r  r  startup_skillsr  skills_promptloaded_skillsmissing_skillsmissing_displayr   requested_provideroverride_base_urloverride_api_keyoverride_api_moderj  r  	recovered
resolutionr  _prs!                                    rD   r  r  q  s    G+J,=#~NI!A <  +C &BI !CDM*,NF7T%#8
4}n "ii7O G $IIm, !#5o5F!GHH"KK ("/!?( eg  .$'N,>,>w,GN&&w/526+//
;X?PXTX*..z:)--i8*..z:!'R(..0668HD N1;L;TPTUI%."  7H23&8{#).$~&3NC
$$##,,"#KLL--E
 !&7
#%5	" &7
#$<$>!!nc*~"E!23+!MT5
 
 $$##,,"#KLL--E
 
"C ..%c2.. Z(. Z(	.
 I&. Z(. KK	*. V$.  $56. . .$ )4 &'EKR(89'.. %0 "#%1.4 015.< ''&/=.> ''(+?.@ (A.B ggfoC.D %(GG,@%$HE.F "%):!;G.H )):;I.J $K.L ",!7:WYM.N !. 5O.P ,BJJNN;S,TUQ.R (

7S(TUS.T +2::>>:O+PQU.V $BJJNN3H$IJW.X ,-
S/[. .Q    s"   S/ S? /	S<;S<?	TTrP  r3  c                     t        j                          }t        5  i d|d|d|dt        j                         dddd d|d	|d
ddg ddd|xs
 t	               d|dd dt               dt        |      dt               i i d t               xs t        dt         <   d d d        ||n	t               }	|	}|	j                  |      }
|
r8|
j                  d      r't        5   t        v r|
d   t            d<   d d d        n2	 t            d   }|	j                  ||       t        t            |       t'        t                   	 t)         t            t+        |t-        |dt/                     t            j                  d                   	 ddlm}m}  || fd        |        	  fd|_        t9               |_        t=                t        5   t        v rt?         t                  t            d<   d d d        tA        d|tC        t        j                   i                    tE        d  tG        |t        j                   i                    tI         |       y # 1 sw Y   xY w# 1 sw Y   JxY w# t         $ r t"        j%                  dd       Y pw xY w# t         $ r d t            d<   Y 0w xY w# t         $ r Y $w xY w# t         $ r Y w xY w# 1 sw Y   xY w)!NrN  r   rP  rO  r1  r   inflight_turnr  r  r  Fr2  rV  r   r3  r]  r  rB  r5  )rh  ri  r5  r  z%failed to persist resumed session cwdTr&  r   r   r  r  c                     t        |       S r   r  r  s    rD   r   z_init_session.<locals>.<lambda>r  s    2Hd2S r   c                 2    t        d|dt        |       i      S r  r  r  s     rD   r   z_init_session.<locals>.<lambda>|  s    UdVS\$:F
 r   rM  r  rP  )%r3   re  r   r   r  r   r  r  r   r  rQ   ra  rb  r   r  r  r5   r  r*  r  rz  r   r   r  rv  r  r  r  r  r  r  r  r  r2  r  rR  r  )r-  rw  rN  rP  r3  r   r  rB  r  rk  rl  _cwdr  r  s   `             rD   _init_sessionr  *  sW    ))+C	 

U
3
 w
 INN,	

 q
 T
 #
 3
 u
 r
 Q
 3+/+
 D
 D
 24
  -f5!
" !":"<#
$ !! # +,@0@5
	#
: "-79B	~nnS!3775> 7)#,/JIcN5)7 7U ~e,%%c40))C.$? )C.).cNw(89&s^//?	
T%ST "@C ,
( &@%A"
 C	 \),FsIVYN,[IcN=)\ /oimmTWY[F\6]^	.#}UIMM#r4JKLsE*q
 
B7 7  UDtTU  .)-	#~&.     	
\ \sm   BI/)I<1J	 A	J0 K 5K &K,/I9<J	 J-,J-0K	K		KK	K)(K),K5c                      t        j                         j                  d       dt        j                         j
                  d d  S )N%Y%m%d_%H%M%Sr     )r   r  r4   rt  ru  rv  r   r   rD   _new_session_keyr    s9    lln%%o67q9I9I"19M8NOOr   c                 @     || d   j                   t        |             S )NrN  )_checkpoint_mgrr;  )r#  r  s     rD   _with_checkpointsr    s    gg..W0EFFr   refc                     	 | j                  |      }t        |      dz
  }d|cxk  rt        |      k  rn n||   j	                  d|      S t        dt        |       d      # t        $ r |cY S w xY w)Nr   r   hashz!Invalid checkpoint number. Use 1-r  )list_checkpointsr  r>  r  r   )mgrr   r  checkpointsr3  s        rD   _resolve_checkpoint_hashr    s    **3/#hl 	C"#k""3##FC00
8[9I8J!L
MM	  
s   A% %A32A3rN  c                 j    ddl m}m} t        | dd      xs  |       t        | dd      xs  |       fS )zBReturn the live provider/model, falling back before agent startup.r   )_read_main_model_read_main_providerr  r   r   )agent.auxiliary_clientr  r  r   )rN  r  r  s      rD   _active_image_routing_identityr    s;    L 	z2&?*=*?w#9'7'9 r   	user_textimage_pathsc           
         ddl }ddl}ddlm} d}g }|D ]  }t	        |      }|j                         sd| d}		 |j                  |j                   |t        |      |                  }
|
j                  d      r|
j                  d	d
      nd}|j                  |rd| d|	 nd|	         | xs d
}dj                  |      }|r|r| d| S |S |xs dS # t        $ r |j                  d|	        Y w xY w)zMPre-analyze attached images via vision and prepend descriptions to user text.r   N)vision_analyze_toolzDescribe everything visible in this image in thorough detail. Include any text, code, data, objects, people, layout, colors, and any other notable visual information.z9[You can examine it with vision_analyze using image_url: r  )	image_urluser_promptr}  analysisr   z[The user attached an image:
z]
z2[The user attached an image but analysis failed.]
rr  zWhat do you see in this image?)asyncior   tools.vision_toolsr  r   r  r   r   r6   r   r  r5   r*   )r  r  r  _jsonr  r  r  r.   r  hintrdescr   prefixs                 rD   _enrich_with_attached_imagesr    s*   !6	4  E WJxxzJ1#QO	W/#a&fUVA -.EE),<155R($DLL 1c$@J4&QW$ ?D[[F(,&dV$8&8333  	WLLNtfUV	Ws   A4CC;:C;r+  c                 H   | yt        | t              r| S t        | t        t        f      rt        |       S t        | t              rGg }| D ]/  }t        |      j                         }|s|j                  |       1 dj                  |      S t        | t              r{| j                  d      }|dv r1t        | j                  d      xs | j                  d      xs d      S |dv ry|d	v ry
|rd| dS d| v rt        | j                  d      xs d      S yt        |       S Nr   r   r  >   r   
input_textoutput_textr   r+  >   imager  input_image[image]>   audioinput_audio[audio][r  [structured content]r  r6   r  r  r_  _content_display_textr7   r  r*   r   r   r+  r  r  r   rr  s        rD   r  r    !   '3'C<(7|'4  	#D(.446DT"	# yy'4 {{6"88w{{6*Jgkk).DJKK88++tfA;Ww{{6*0b11%w<r   c                    | yt        | t              r| S t        | t        t        f      rt        |       S t        | t              rg }| D ]z  }t        |t              r|j                  |       &t        |t              s7|j                  d      }t        |t              r|j                  |       j|j                  d      }|dv rE|j                  d      xs |j                  d      xs d}|r|j                  t        |             |dv r|j                  d      }d}t        |t              r$|j                  d      }t        |t              r|}nt        |t              r|}|r|j                  d	|        n|j                  d
       K|dv r|j                  d       b|sf|j                  d| d       } dj                  |      S t        | t              r| j                  d      }|dv r1t        | j                  d      xs | j                  d      xs d      S |dv r_| j                  d      }d}t        |t              r$|j                  d      }t        |t              r|}nt        |t              r|}|xs dS |dv ry|rd| dS d| v rt        | j                  d      xs d      S yt        |       S )u  Render ``message['content']`` as a plain string for transport.

    Provider-side, ``content`` may be a string (most common), a list of
    multimodal parts (e.g. ``[{"type": "text", "text": "..."},
    {"type": "image_url", "image_url": {...}}]``), or a single structured
    dict. Calling ``.strip()`` on a list raises ``'list' object has no
    attribute 'strip'`` and breaks session resume entirely.

    Image parts (``image_url``) are preserved by appending the underlying
    URL (data: or http:) into the text. The desktop renderer pulls these
    back out via ``extractEmbeddedImages`` so the user sees the image
    instead of the URL — and it stops the resume payload from disagreeing
    with the cached message (which would otherwise cause the inline image
    to flash, then disappear when the resume payload overwrites the cache).

    Other structured dict shapes (audio, unknown types) fall back to a
    bracketed placeholder so resume doesn't drop the message entirely.
    r   r   r  >   r   r  r  r+  >   r  r  r  r  urlr   z
[image]>   r  r  z
[audio]z
[r  r  r  r  r  )	r  r6   r  r  r_  r  r   r   r*   )	r+  chunksr  r   rr  r  r  r  r  s	            rD   _coerce_message_textr    s   & '3'C<(7|'4  "	-D$$d#dD)88F#D$$d#88F#D<<HHV$A(;ArMM#a&)<< HH[1	i. )e 4I!)S1'	3/#CMMBse*-MM+.//k*D6m,E"	-F wwv'4 {{6"88w{{6*Jgkk).DJKK88K0IC)T*%MM%0	i-#CIs+#)#++tfA;Ww{{6*0b11%w<r   c           	         g }i }| D ]  t        t              sj                  d      }|dvr+t        j                  d            }|dk(  rj                  d      rd   D ]k  }|j                  di       }|j                  dd      }|s*|j                  d	      s<	 t	        j
                  |j                  d
d            }|d	   |f||<   m |j                         s|dk(  ruj                  dd      }|r|j                  |      nd }	|	r|	d   nd xs j                  d      xs d}
|	r|	d   nd xs i }|j                  d|
t        |
|      d       Yd}|dk(  xr t        fd|D              }|j                         s|s||d}|dk(  r2|D ]-  }|v sj                  |      j                  |      ||<   / |j                  |        |S # t        j                  t        f$ r i }Y 8w xY w)Nr)  >   r  r*  r@  r?  r+  r?  
tool_callsr  r   r   rI   	argumentsz{}r  re  r   r  r   )r)  rI   rk  )r  reasoning_contentreasoning_detailscodex_reasoning_itemsc              3   @   K   | ]  }j                  |        y wr   r   )r  rw  r  s     rD   r  z'_history_to_messages.<locals>.<genexpr>t  s      4
AEE#J4
s   )r)  r   )r  r   r   r  r   r   r   rS  r7   r  r'  r  )rP  rn  tool_call_argsr)  content_texttcr  r  rJ   tc_inforI   reasoning_keyshas_reasoningr   rw  r  s                  @rD   _history_to_messagesr  G  s)   HN 3!T"uuV}>>+AEE),<=;155#6o ?VVJ+tR(RVVF^"#zz"&&d*CD .0Z,>N5)?  %%'6>EE."-E38n((/dG")GAJtTk8JTfD")GAJt:DOO)D$:OP 
 + 
 4
"04
 1
 !!#M\2;% *!8c
 6 uuSzCH* 	g3j OO !00)< "!"s   %%G$$HHc                 <   t        | t              sg S g }| D ]  }t        |t              s|j                  d      }|dvr*|j                  d      }||j                  d      }t        |t              r|j                         so|j                  ||d        |S )Nr)  )r*  r?  r@  r+  r   r  )r  r_  r   r   r6   r7   r  )rE  rP  r&  r)  r+  s        rD   _coerce_seed_historyr    s    eT"	G ;$%xx66((9%?hhv&G'3'w}}9:;  Nr   c                 H   | yt        | t              r| S t        | t        t        f      rt        |       S t        | t              rGg }| D ]/  }t        |      j                         }|s|j                  |       1 dj                  |      S t        | t              r{| j                  d      }|dv r1t        | j                  d      xs | j                  d      xs d      S |dv ry|d	v ry
|rd| dS d| v rt        | j                  d      xs d      S yt        |       S r  r  r  s        rD   r  r    r  r   c                 4    t        |       j                         S r   )r  r7   r  s    rD   _inflight_textr    s     '--//r   c                 T    t        j                          }d|d|t        |      d| d<   y )Nr   T)r?  ry  r^  
updated_atr*  r  )r3   r  )r#  r   r  s      rD   _start_inflight_turnr    s-    
))+Ct$ GOr   deltac                     |dn
t        |      }|sy | j                  d      }t        |t              sdddd}|j                  d      xs d | |d<   d|d<   t	        j                         |d<   || d<   y )Nr   r  Tr?  r^  r*  r?  r^  r  )r6   r   r  r   r3   )r#  r  r   turns       rD   _append_inflight_deltar    s    2CJD;;'DdD!dB?88K06B7v>DDD#GOr   c                     d | d<   y )Nr  r   r  s    rD   rQ  rQ    s    #GOr   c                     | j                  d      }|rEt        |j                  d      t              r&t        |t              r|d   }|r	|r| d| n|xs |}||d| d<   y)a  Stash a message to run as the very next turn once the live one ends.

    Used when a prompt arrives mid-turn (see ``_handle_busy_submit``). A single
    slot is kept; a second arrival is merged (lossless, mirroring the
    consecutive-user merge in ``repair_message_sequence``) so nothing the user
    typed is dropped. ``transport`` is pinned so the drained turn streams back to
    the client that sent it even if the session transport is rebound meanwhile.
    queued_promptr   rr  )r   r  N)r   r  r6   )r#  r   r  r  prevs        rD   _enqueue_promptr    se     {{?+Hx||F+S1tS!&*t$tD6"$,$(,9EGOr   c                 2    duxr t        d       xr t              }s|syd   5  j                  d      r
	 ddd       ydd<   ddd       d	 fd}t        j                  |dd        j                          y# 1 sw Y   <xY w)
a  Interrupt a busy turn without blocking the RPC reader or session lock.

    Some providers cannot apply ``interrupt()`` until a synchronous tool or
    network call returns. Running that call inline used to leave
    ``prompt.submit`` holding ``history_lock`` for the whole wait, which in turn
    blocked ``session.resume`` and delayed the queued prompt itself. Keep at
    most one interrupt worker per session so repeated steering cannot leak an
    unbounded number of blocked threads.
    Nr  rO  _busy_interrupt_pendingTc                     	 r j                          nt               j                         d   5  dd<   d d d        y # t        $ r Y w xY w# 1 sw Y   y xY w# d   5  dd<   d d d        w # 1 sw Y   w xY wxY w)NrO  Fr   )r  r/  r5   )rN  r#  r-  	use_agents   rD   r  z*_interrupt_busy_session.<locals>.interrupt  s    		;!,.88= ( ;5:12; ;  		; ;( ;5:12; ; ;sF   ,A A	AA AA AA?$A3*	A?3A<8A?zbusy-interrupt-)r   r   rI   r   )r`  r"  r   r   r   r   )r-  r#  rN  use_compute_hostr  r  s   ```  @rD   _interrupt_busy_sessionr    s     T!Age[&AI$}L)CG)L-		  2;;012 2 .2)*2

; 
; Id?3%9PQWWY#2 2s   BBBc                 ~   t               }|j                  d      }|d   5  |j                  d      s
	 ddd       y	 ddd       |dk(  rT|Rt        |d      rF	 |j                  |      r3|d   5  t	        j                         |d<   ddd       t        | ddi      S 	 |d   5  |j                  d      s
	 ddd       yt        |||       t	        j                         |d<   ddd       |d	k7  rt        |||       t        | dd
i      S # 1 sw Y   xY w# 1 sw Y   xY w# t        $ r Y w xY w# 1 sw Y   PxY w)u  Apply the ``display.busy_input_mode`` policy to a prompt that lands while
    a turn is in flight, instead of rejecting it with ``session busy``.

    The old rejection forced clients into a deadline-bounded busy-retry that
    silently dropped the send when turn teardown outlived the deadline (e.g. a
    slow, non-interruptible tool like ``web_search`` running when the user hits
    stop). The message is instead queued to run as the next turn — and, for the
    default ``interrupt`` policy, the live turn is interrupted so it winds down
    promptly. Drained in ``run``'s tail (see ``_run_prompt_submit``).

    Modes: ``interrupt`` (default) → interrupt + queue; ``queue`` → queue
    without interrupting; ``steer`` → inject into the live turn if accepted,
    else queue.
    rN  rO  r  Nr   r  rN  steeredr   queued)	r  r   r`  r   r3   ra  r5   r  r  )r   r-  r#  r   r  r  rN  s          rD   _handle_busy_submitr    sQ   " !"DKK E		  {{9% 	 %
 w5,1H	{{4 ^, 9-1YY[GM*939 566 ! 
	  -{{9%- - 	y1!%	- wWe4sXx())1 9 9  		
- -sG   DD$ 0DD$ $D3 $D3DD!D$ $	D0/D03D<c                    |d   5  |j                  d      }|r|j                  d      r
	 ddd       yd|d<   d|d<   |j                  d      |d   |d<   ddd       	 t        |      rt        | ||d         }|j                  d	      rqt        |j                  d	      xs i j                  d
      xs d      }|d   5  d|d<   t	        |       ddd       t        d	|d
|i       	 yt        | ||d          y# 1 sw Y   xY w# 1 sw Y   8xY w# t        $ r^}t        dt        |      j                   d| t        j                         |d   5  d|d<   ddd       n# 1 sw Y   nxY wY d}~yd}~ww xY w)u6  Fire a queued next-turn prompt if one is waiting and the session is idle.

    Returns True if a queued prompt was dispatched (the caller should then skip
    lower-priority follow-ups this cycle — the user's message wins). Mirrors the
    claim-under-lock pattern used by the goal-continuation re-fire.
    rO  r  r  NFTr  r   r   rK  zqueued prompt failedz-[tui_gateway] queued prompt dispatch failed: r%   r'   )r   r"  rb  r6   rQ  r  _run_prompt_submitr5   r:   r  r9   r;   r<   )r   r-  r#  r  r  rK  r!  s          rD   rT  rT  >  s    
	  7_-Y/7 7 $( !	::k".#)+#6GK 7'%g.1#sGVF^TDxx  1 7R<<YGbLbc^, 2).GI&(12 gsY$89  sC&.A 77 72 2  ';Cy!!""SE+	

 ^$ 	'!&GI	' 	' 	''s_   &D #D !A#D DD .D  D	DD 	E?!9E:E) 	E:)E2	.E::E?c                 (   | j                  d      }t        |t              sy t        |j                  d      xs d      j	                         }t        |j                  d      xs d      }t        |j                  d            }|s|s|sy |||dS )Nr  r*  r   r?  r^  r  )r   r  r   r6   r7   r   )r#  r  r*  r?  r^  s        rD   _inflight_snapshotr  c  s    ;;'DdD!txx%2&,,.DDHH[)/R0ITXXk*+I	) r   c                     | j                  d      }t        |t              syt        |j                  d            }|rd|iS dS )aw  Return the accepted next-turn prompt without its transport handle.

    A busy ``prompt.submit`` lives only in ``session["queued_prompt"]`` until
    the current turn winds down. Desktop may reconnect or restart during that
    window, so the live-session projection must carry the user-visible text;
    otherwise the accepted prompt disappears until it finally drains.
    r  Nr   r*  )r   r  r   r  )r#  r  r*  s      rD   _queued_prompt_snapshotr  s  sC     [[)Ffd#&**V,-D!FD>+t+r   zsession.createc                 "	   t        j                         j                  d d }t               }t	        |j                  dd            }t        |j                  d            }t        |j                  d      xs d      j                         }t        |j                  d      xs d      j                         xs d }t        |j                  d      xs d      j                         }	 t        |      xrY t        j                  j                  t        j                  j                  t        j                  j                  |                  }	t!        |      }
t#        t        |j                  d
      xs d      j                         xs d       }t%                |j                  d      xs dj                         xs d }t'        |      }t        |j                  d      xs d      j                         }|r3|t        |j                  d      xs d      j                         xs d dnd }d }t        |j                  d      xs d      j                         x}r	 ddlm}  ||      }d }d|v rt-        |j                  d            rdnd}t/        j0                         }t3        j2                         }t5        |||      \  }}|t7        | d|      S t8        5  i dd dd d|dg dt-        |j                  dd	            d|d|d|di d|	d|d t/        j:                         d!dd"dd|
d#d d$||||||xs d |t        |      nd d	|t=               |d t?               i tA               xs tB        d%tD        |<   tG        tD        |          d d d        tI        |       tK                tM        | ||tO        |      tQ        |      d|r|j                  d      n	tS               i|r|j                  d      rd|d   ini i i tD        |   d   tU        tD        |   d         tW        tD        |   d         d&tX        t[               d'd(      S # t        $ r d	}	Y w xY w# t        $ r d }Y w xY w# 1 sw Y   xY w))Nr   r3  r4  rn  r  r   r  r   FrB  r  r   r  ru  r  r   parse_reasoning_effortr  r  r1    rN  r  r  r2  r  r%  r  rh  r  rP  rO  r1  rV  r  r  )r5  r6  r7  r  r  r   r  r   r  rB  r]  r5  ri  r  T)r`   r   r   r6  r  r  r  r  )r  r  rB  rn  rH  ).rt  ru  rv  r  r  r   r  r6   r7   r   r,   r.   r  r  r  r5   r  r  ro  r  r=  r  r   r   rw  r3   r"  r  re  r   r   r  r   r  rQ   r  _schedule_agent_buildr  ra  r  r  r  r5  r  r  r  )r   r  r-  rw  r3  rP  r  r  raw_cwdr  resolved_cwdrB  r  r   create_modelsession_model_overrider6  r  r  r7  r  r  r+  r4  s                           rD   r  r    s   
**,

2A
C

Cvzz&"%&D"6::j#9:G

7#)r*002E FJJ':;ArBHHJRd
 &**U#)r*002GG}drwwrwwGYGYZaGb7c)d #6*L$SH)=)C%D%J%J%L%TPTUF zz)$*113;tG )L vzz'*0b1779L  C

:0F0L",M,S,S,U,]Y]^ 
 !%VZZ 239r:@@BBvB	-?(>v(F% $( )&**V*<=J2 	% OOE
))+C5S&E=  C}--	 ". 
T 
4 
 5 
 r	 

 "?6::>SUZ3[#\ 
 #E 
 D 
 # 
 b 
 L 
 w 
 INN, 
 q 
 Q 
 < 
  T! 
" 3# 
$ 5)B,H!2"]d1=1IC-t24 ":"<!*,@0@? 
	#B 	in-E".^ #%'!$ \,W5 - +..w7') .2H2L2LZ2X  !7
!CD  ~e,-inU.CD031FG$< 5 7-	
   G  <  	-(,%	-&". ".s2   *A&Q! $Q3 $B<R!Q0/Q03RRRrs   c                    t               }|t        | d      S 	 t        dh      }t        |j	                  dd      xs d      }t        |dz  d      }|j                  d |dd      D cg c]7  }|j	                  d	      xs d
j                         j                         |vr|9 c}d | }t        | d|D cg c]m  }|d   |j	                  d      xs d
|j	                  d      xs d
|j	                  d      xs d|j	                  d      xs d|j	                  d	      xs d
do c}i      S c c}w c c}w # t        $ r }t        | dt        |            cY d }~S d }~ww xY w)Ni  r  r  limit   r   TrB  r  order_by_last_activecompact_rowsrB  r   sessionsr   r  r|  ry  r   rB  )r   r  r|  ry  rB  rB  )ra  r  	frozensetr  r   rF  list_sessions_richr7   r  ra  r5   r  r6   )	r   r  rk  rl  r  fetch_limitr  rowsr  s	            rD   r  r    s|   	B	z$St44&' &"FJJw,34 %!)S) **$k`dsw*x
h%2,,.446dB 
 5	
  "
   g!"w!52#$55#3#9r&'eeL&9&>Q)*)?)D1"#%%/"7R

 	


  'Cs1v&&'s=   AD= ,<D3(D= 9A2D8+D= 3
D= =	E&E!E&!E&zsession.most_recentc           
      (   t               }|t        | ddi      S 	 t        dh      }|j                  dddd      }|D ]  }|j	                  d      xs dj                         j                         }||v r9t        | |j	                  d	      |j	                  d
      xs d|j	                  d      xs d|j	                  d      xs dd      c S  t        | ddi      S # t        $ r& t        j                  d       t        | ddi      cY S w xY w)ae  Return the most recent human-facing session id, or ``None``.

    Mirrors ``session.list``'s deny-list behaviour (drops ``tool``
    sub-agent rows).  Used by TUI auto-resume when
    ``display.tui_auto_resume_recent`` is on; the field is also handy
    for any CLI tooling that wants "latest session" without paginating
    the full list.

    Contract: a ``{"session_id": null}`` result means "no eligible
    session found right now".  Errors are also folded into that
    null-result shape (and logged) so callers don't have to special-
    case JSON-RPC error envelopes for what is a normal "no answer".
    Nr  r  r  Tr  rB  r   r   r  ry  r   )r  r  ry  rB  zsession.most_recent failed)
ra  ra  r!  r"  r   r7   r  r5   r  	exception)r   r  rk  rl  r$  rl  rG  s          rD   r  r  K  s%    
B	z3t,--.&"
 $$DRVei$j 	C778$*11399;Cd{"%''$- WWW-3"%'',"7"<1!ggh/52	 		 3t,-- .563t,--.s   B6C" C" ",DDzproject.factsc           	          	 ddl m} t        | d ||j                  d            i      S # t        $ r& t
        j                  d       t        | ddi      cY S w xY w)ud  Structured project facts for a cwd — manifests, package manager, the
    exact verify commands, and context files.

    The same detection the coding-context posture (#43316) bakes into the system
    prompt, exposed so UIs (the desktop verify surface) consume it instead of
    re-sniffing. ``{"facts": null}`` means the cwd isn't a code workspace.
    r   )project_facts_forfactsr   zproject.facts failedN)r   r(  ra  r   r5   r  r&  )r   r  r(  s      rD   r  r  w  sZ    ):3"3FJJu4E"FGHH )/03$(()s   (+ ,AAzverification.statusc           
         	 ddl m} t        | d ||j                  d      xs |j                  d      |j                  d            i      S # t        $ r) t
        j                  d       t        | dd	d
di      cY S w xY w)zBest known coding verification evidence for a cwd/session.

    Read-only consumer of the core ledger. It never runs checks and never
    upgrades targeted evidence into a repository-wide guarantee.
    r   )verification_statusverificationr  r   r   )r  r   zverification.status failedrT  N)rN  evidence)agent.verification_evidencer+  ra  r   r5   r  r&  )r   r  r+  s      rD   r  r    s    SC 3%zz,7T6::m;T

5)!
 	
  S563I4)PQRRSs   AA /B Bru  c          
          | t        |       t        |       |xs
 t               i i dt        t	               d	}|r||d<   |S )zsession.info for a not-yet-built session (the shape session.create
    returns). tools/skills land later when the deferred build emits session.info.T)	r   r6  r  r   r`   r   r  r  r  r  )r5  r  r  r  r  )r   r   r  rH  s       rD   _lazy_resume_infor0    sO     %c*(-*.*4-/
D #ZKr   )rB  r  display_history_prefixr   r  r5  r  r  r1  r  r  c                b   t        j                          }i dddddt        j                         dg d|d|d|d	|d
|d|xs g di ddd|dt        j                         dddddd||	|
d|t	        |      nd|| d| t               d|t               i t               xs t        dS )u|   A live-session record whose AIAgent is built later (lazy watch / cold
    resume) — _init_session's shape minus the agent.rN  Nr  r  r2  r  r%  r3  r  r   r1  rh  r  FrP  rO  r1  r   rV  r  )r  r  r5  r  r   r  r  r  r   r  r]  rB  r5  ri  r  )	r3   r   rw  r   r6   r   r  r   r  )r   r3  r   rP  r+  rB  r  r1  r   r  r5  r  r  s                rD   _deferred_session_recordr3    sF   " ))+C!!t! 	y(! 	2	!
 	2! 	! 	! 	c! 	s! 	!"8">B! 	"! 	! 	7! 		(! 	1!  	!!" 	#!$ (-9-EL)4$<(".068&(<,<A! !r   recordc                     t         5  t        |      }|||j                          |cddd       S t        5  |t        | <   t        t        |           ddd       ddd       y# 1 sw Y   xY w# 1 sw Y   yxY w)u   Register ``record`` as the live session for ``session_key`` under the
    resume lock, or — if a concurrent resume already won — release ``lease`` and
    return the winner for the caller to reuse.N)r  r  r)  re  rQ   r  )r-  r   r4  r+  r  s        rD   _claim_or_reuse_liver6    s|     
 2(5 2 2  	2#IcN!)C.1	22 	2 	22 s'   !A1A1A%A1%A.	*A11A:delayc                 j      fd}t        j                  ||      }d|_        |j                          y)zPre-warm a deferred session's agent off the response path (session.create
    and cold resume both build through here; _sess() also builds on demand).c                  N    t         j                        } | t        |        y y r   )rQ   r   r  r  s    rD   r  z#_schedule_agent_build.<locals>._run   s&    --$sG, r   TNr  )r-  r7  r  r  s   `   rD   r  r    s*    -
 OOE4(EEL	KKMr   r   c                   $% |j                  dd      %%st        | dd      S 	 t        |j                  dd            $|j                  d      xs dj                         xs d }t        |      }|dd	lm}  ||d
z        }n
t               }|t        | d      S |j                  %      }|sO|j                  %      }|r|d   %n6t        |j                  dd            rt        %      ri }nt        | dd      S |rKt        |j                  dd            s0	 |j                  %      }|r|%k7  r|%|j                  %      xs |}t#        |j                  d      xs d      j                         xs t%        |      }dt"        dt&        dt&        f$%fd}	t(        5  t+        %      }
|
t-        |  |	|
       cd d d        S 	 d d d        t        |j                  dd            rEt/        j0                         j2                  d d }t5        t#        |j                  d      xs d      j                         xs d       }t7        %||      \  }}|t        | d|      S 	 |j9                  %       |j;                  %d      }|xs
 t?               }tA        %$||||t        |j                  dd            |d 	      }tC        |%||      x}
t-        |  |	|
       S t        %      }tE        |      }t-        | |%tG        |      |tI        |      d |%|d!   |rd"d$
      S d#d$
      S t        |j                  d%d            st/        j0                         j2                  d d }t5        t#        |j                  d      xs d      j                         xs d       }t7        %||      \  }}|t        | d|      S tK                	 |j9                  %       |jM                  %      \  }}|jO                  %      }tQ        |      }tS        |      xs i }|j                  d&      xs i }|xs
 t?               }tA        %$||||t        |j                  dd            |||j                  d&      |xs d '      }tC        |%||      x}
t-        |  |	|
       S tU        |       tW                tE        |      }t-        | |%tG        |      |tI        ||j                  d(      xs d|j                  d)      xs d*      d d%|d!   d#d$
      S t/        j0                         j2                  d d }t5        t#        |j                  d      xs d      j                         xs d       }t7        %||      \  }}|t        | d|      S tK                |tY        t#        |            nd }	 |j9                  %       |jM                  %      \  }}|jO                  %      }tQ        |      }tE        |      }t[        %      }	 tS        |      }t]        |%f%||d+|}t_        |       	 |ta        |       	 t(        5  t+        %      }
|
n	 tc        |d,      r|je                          ||j=                          |
\  }} tg        || $dti               xs tj        -      }!%|!d.<   t-        | |!      cd d d        S 	 |tY        t#        |            nd }"	 tm        |%||$|||/       |"ta        |"       	 |tn        v rO|j                  d&      |d&   tn        |   d&<   |tn        |   d0<   |t#        |      tn        |   d1<   |tn        |   d2<   tn        j                  |      xs i }#d d d        t-        | |%tG        |      |tq        |#      d d%ts        |#j                  d!      xs tu        jt                               d#d$
      S # t        t        f$ r d$Y w xY w# t         $ r %}Y w xY w# 1 sw Y   7xY w# t         $ r,}||j=                          t        | dd|       cY d }~S d }~ww xY w# t         $ r,}||j=                          t        | dd|       cY d }~S d }~ww xY w# t_        |       w xY w# t         $ r:}||j=                          t        | dd|       cY d }~|ta        |       S S d }~ww xY w# |ta        |       w w xY w# t         $ r Y xw xY w# |"ta        |"       w w xY w# t         $ r5}||j=                          t        | dd|       cY d }~cd d d        S d }~ww xY w# 1 sw Y   xY w)3Nr  r     session_id requiredr3  r4  r  r   r  r  r    r  r   r  F  r  r   r-  r#  r   c                     t        | |dt               xs t              }|d<   |j                  d      t	              r
d|d<   d|d<   |S )NTr3  touchr  resumedrN  r  r^  rN  )_live_session_payloadr   r  r   r  )r-  r#  r  r3  r   s      rD   _reuse_live_payloadz_.<locals>._reuse_live_payloadP  sc    '')=-=
 $	 ;;w',=f,E!%GI +GHr   r   rB  r1  r  Trepair_alternationzresume failed: r  )r3  r   rP  r+  rB  r  r   r  r  r^  idle)
r  rB  rB  rn  rH  inflightr  r   ry  rN  eager_buildr5  )
r3  r   rP  r+  rB  r  r1  r   r5  r  r   r  ru  )r  r  r  r   r@  rB  )r3  r   r  rB  r1  r   r%  );r   r  r  rS  r>  r7   r  r  r  ra  r  rb  get_session_by_titler   r  resolve_resume_session_idr5   r6   r  r   r  r  ra  rt  ru  rv  r  r"  reopen_sessionget_messages_as_conversationr)  r	  r3  r6  r  r  r0  ro  get_resume_conversationsget_ancestor_display_prefixr   r  r  r  r   r  r  r  r   r`  r   rC  r   r  r  rQ   rR  r  r3   )&r   r  r  r   r  rk  foundtipprofile_resume_cwdrD  r  r-  rB  r+  r4  rP  r  r   r4  child_runningrn  raw_historydisplay_historyr  r  r5  r  r1  r  stored_runtime_overridesrN  	other_sidother_sessionr  init_home_tokenr#  r3  r   s&                                       @@rD   r  r  
  s
   ZZb)FC4556::fb)*
 zz)$*113;tG )L *|j89Y	z$St44NN6"E''/4[FVZZ67<Mf<U ET#677 _VZZ%>?	..v6C 3&=FNN6*3eEUYYu-34::< @WA t  $ 
 8(0s/678 88 vzz&%01jjlr"(VZZ-A-GR)H)N)N)P)XTXY9C 
} $T=11	:f% 55fQU5VG
 !:$8$:) /

;PRW0X Y%

 )ffeDDDQs/677 *&1'0!!!$X$)#. (%$\2)6+
 	
 =C
 	
: 6::mU;<jjlr"(VZZ-A-GR)H)N)N)P)XTXY9C 
} $T=11 	 !	:f% ,.+F+Fv+N(K //7)+6 6e<B	"'78>B :$8$:) /

;PRW0X Y#)%$==)9:%.%6$
 )ffeDDDQs/677c")+'8!!!$X$)(,,W5;&]]+>?E2
 ! %$\2 
 	
0 **,

2A
C$SH)=)C%D%J%J%L%TPTUF5VE=  C}--7C7O \!23UY (3
&! (*'B'B6'J$_ "$!?!?!G)+6'8%f-	+ (I'O$ ""( +E #6* !&z2
 
 8+(05'*KKM  '+$I}++-A1AG "(GIsG$'8+ 8+(#	:  + )\):; 
@*!!	 #..?i+//0@AM7O(8IcN#34 <R	#78  +585FIcN>29>	#56
 --$*q8+r  ] !%1!L 9 HTYY[I	
 A z" j  	C	88 8:  	: T_QC#899	:L  	: T_QC#899	:N #6* 6MMOC455!&z2 "6
 !&z2 "  @ #..? /  	: T_QC#899o8+ 8+h	:i8+ 8+s.  _  _1 '`-$` %a >Ab b  2b e!c)=Aed(c9;A%d e_.-_.1` ?` `	a!a :a a	a=!a82a=8a= bb 	c!c:c;c cc c&)	c62e5c66e9d		d	e
!e6e
7ee

eezsession.cwd.setc                    t        ||       \  }}|r|S |j                  d      rt        | dd      S t        |j                  dd      xs d      j	                         }|st        | dd      S 	 t        ||      }|j                  d	      }|t        ||      n|t        |      t        |      d
d}t        d|j                  dd      |       t        | |      S # t        $ r }t        | dt        |            cY d }~S d }~ww xY w)Nr    zsession busyr   r     cwd required  rN  Tr  rP  r  )r  r   r  r6   r7   r?  r>  rR  r5  r  r  ra  )	r   r  r#  r  r  r   r  rN  rH  s	            rD   r  r    s   ,LGS

{{9C~..
fjj#)r
*
0
0
2CC~..'w, KK E,1,==(%c*(-	DD 
.&**\26=sD>  'Cs1v&&'s   /C 	D%D :D Dc                     t        t        j                               D ]D  \  }\  }}|| k7  rt        j	                  |di f      \  }}t        |      j                  d      c S  y)Nzinput.requestrs  r   )r_  rS   rf  rT   r   r6   ry  )r-  r   r  _evr  _payloads         rD   r  r    sg    !%hnn&6!7 3i266s_b<QRx5z&&z22	3
 r   c                     t        |       ry|j                  d      }|"|j                         s|j                  d      ry|j                  d      ryy)Nwaitingr  r  startingr  workingrG  )r  r   r  r  s      rD   _session_live_statusrf    sL    S!KK&E GKK@U4V{{9r   c           
          t        | xs g       D ]a  }t        |j                  d|j                  dd                  j                         }|s?dj	                  |j                               d d c S  y)Nr+  r   r   r     )reversedr  r   r7   r*   r  )rP  r   r   s      rD   _message_previewrj    sg    2& 0$SWWY8K%LMSSU88DJJL)$3//0 r   c                     t        | j                  d      xs d      j                         }t               }|3	 t        |j	                  |      xs |xs d      j                         }|S |S # t
        $ r Y |S w xY w)Nr  r   )r6   r   r7   ra  get_session_titler5   )r#  rw  r  rk  s       rD   r  r    s    O,2399;E	B	~	,,S1@U@bAGGIE L5L  	L	s   0A. .	A;:A;current_sidc                 H   t        ||       }|j                  d      }t        |j                  d      xs g       }t        | |      }t	        |      }t        |      }t        |      }	|rA|j                  d      xs |	}	dj                  t        |	      j                               d d }	nU|rS|j                  d      xs |j                  d      xs |	}	dj                  t        |	      j                               d d }	t        j                         }
| |k(  | t        |j                  d      xs |j                  d	      xs |
      t        |      t        t        |d
d      xs
 t                     |	|t        |j                  d	      xs |
      |t        ||      d
S )NfallbackrN  rP  r*  r  rh  r?  r  r  r   r   )
r  r   r  rB  r   r|  r   ry  rN  r  )_session_lookup_keyr   r_  rf  r  r  rj  r*   r6   r  r3   r  r  r   r  r  )r-  r#  rm  rw  rN  rP  rN  rH  r  r|  r  s              rD   _session_live_itemrr    sj   
g
4CKK E7;;y)/R0G!#w/F!'*H$W-Fw'G**V$/((3w<--/0#6	,,{+Nx||F/CNw((3w<--/0#6
))+C+%W[[7[7;;|;T[X[\WWUGR0DN4DEGKK5<=$Wc2 r   ro  rp  c                    | j                  d      }t        t        |dd       xs | j                  d      xs |xs d      S )NrN  r  r   r   )r   r6   r   )r#  rp  rN  s      rD   rq  rq    sL    KK E|T* 	;;}%		 	 r   c                     t        t        j                               D ]-  \  }}|j                  d      rt	        ||      | k(  s)||fc S  y )NrL  ro  )r_  rQ   rf  r   rq  )r   r-  r#  s      rD   r  r    sN    Y__./  W;;|$w5D<	 
 r   c                     | j                  d      }|t        |      S t               }|t        |      dt	               i i dS )NrN  T)r   r  r  r   r   r`   )r   rR  r	  r  r  )r#  rN  r   s      rD   _fallback_session_inforv    sM    KK EU##

 C(-! r   r@  rA  c                P   |d   5  |||d<   |||d<   |rt        j                          |d<   t        |j                  d      xs g       t        |j                  d      xs g       z   }t        |      }t	        |      }t        |j                  d            }d d d        t        |      t              t        |      | t        ||       t        |j                  d	      xs t        j                                t        | |      d
}	r||	d<   r||	d<   |	S # 1 sw Y   xY w)NrO  r3  r  r  r1  rP  r  ro  r  )rH  rB  rn  r  r  r   ry  rN  rH  r  )r3   r_  r   r  r  r   rv  r  r  rq  r  rf  )
r-  r#  r3  rA  r  rP  rH  r  r  r  s
             rD   rC  rC    s*    
	  /"GFO #,GK %)YY[GM"w{{#;<BCdKK	"(bG
 
 &g.(1w{{9-./ 'w/W(1*7SAGKK5DE&sG4	G &
"N7/ /s   BDD%r   c           	         t        |j                  d      xs d      }	 t        5  t        t        j                               }ddd       D cg c]#  \  }}|j                  d      st        |||      % }}}t        | d|i      S # 1 sw Y   GxY w# t        $ r}t        | dd|       cY d}~S d}~ww xY wc c}}w )zReturn live TUI sessions in this gateway process.

    Unlike ``session.list`` this is not a historical DB browser: it reports only
    sessions with in-memory agents/workers that the current TUI can switch to
    without closing siblings.
    current_session_idr   N  %could not enumerate active sessions: rL  r   )
r6   r   re  r_  rQ   rf  r5   r  rr  ra  )r   r  r  ri  r  r-  r#  r$  s           rD   r  r  )  s     &**128b9GL 	/IOO-.H	/, %C{{<( 	31D 
 sZ&''3	/ 	/ LC!FqcJKKL$s:   B B
B (B<
BB 	B9B4.B94B9zsession.activatec           
          t        |j                  d      xs d      }t        d|i|       \  }}|r|S |J t        | t	        ||dt               xs t                    S )zAttach the frontend to an already-live TUI session.

    This intentionally does not close the previously focused session; it merely
    returns enough state for Ink to redraw around another live session id.
    r  r   T)rA  r  )r6   r   r  ra  rC  r   r  )r   r  r-  r#  r  s        rD   r  r  O  sr     fjj&,"
-Cs 3S9LGS

')=-=		
 r   zsession.deletec                    |j                  dd      }|st        | dd      S t               }|t        | d      S 	 t        5  t        t        j                               }ddd       D ch c]%  }|j                  d	      s|j                  d	      ' }}||v rt        | d
d      S t               dz  }	 |j                  ||      }	|	st        | dd      S t        | d|i      S # 1 sw Y   xY w# t        $ r}t        | dd|       cY d}~S d}~ww xY wc c}w # t        $ r}t        | dd|       cY d}~S d}~ww xY w)u  Delete a stored session and its on-disk transcript files.

    Used by the TUI resume picker (``d`` key) so users can prune old
    sessions without dropping to the CLI.  Refuses to delete a session
    that is currently active in this gateway process — those rows are
    still being written to and removing them out from under the live
    agent corrupts message ordering and trips FK constraints when the
    next message append flushes.
    r  r   r;  r<  Nrz  r  r{  r     zcannot delete an active sessionr   )sessions_dirzdelete failed: r>  r  deleted)r   r  ra  r  re  r_  rQ   ra  r5   r
   delete_sessionra  )
r   r  r   rk  ri  r  r  activer  r  s
             rD   r  r  g  sR    ZZb)FC455	B	z$St44L 	0I,,./H	0 -5Mqm8LaeeM"MFMC@AA"$z1L6##F#F C233sY'((	0 	0 LC!FqcJKKLM  6C4556s_   C3 C' C3 ,DD7D 'C0,C3 3	D<DDD	E'D<6E<Esession.titlec                    t        ||       \  }}|r|S t               }|t        | d      S |d   }d|vr|j                  d      xs d}	 |j	                  |      xs d}|rd|j                  ||      rd |d<   |}nQ|j                  |      }|xs i j                  d      xs dj                         }	|	|k(  rd |d<   |}n|s
|}n|rd |d<   t        |j                  dd      |       t        | ||d      S |j                  dd      xs dj                         }
|
st        | d	d
      S 	 |j                  ||
      r0d |d<   t        |j                  dd      |       t        | d|
d      S |j                  |      }|rCd |d<   t        |j                  dd      |       t        | d|j                  d      xs |
d      S t        |       t        |      5 }|K|j                  ||
      r9d |d<   t        |j                  dd      |       t        | d|
d      cd d d        S d d d        |
|d<   t        |j                  dd      |       t        | d|
d      S # t        $ r |}Y w xY w# 1 sw Y   KxY w# t        $ r }t        | dt        |            cY d }~S d }~wt        $ r }t        | dt        |            cY d }~S d }~ww xY w)N  r  r   r  r  r   r  )r  r   i  ztitle requiredF)pendingr  Ti  )r  ra  r  r   rl  set_session_titlerb  r7   r5   r)  ra  r  r&  r  r>  r6   )r   r  r#  r  rk  rw  rp  resolved_titleexisting_rowexisting_titler  r  r  s                rD   r  r    s   ,LGS

	B	z$St44
-
 Cf;;/52	&11#6<"N''X6/3GO,%-N#%>>##6L'3'9r&>&>w&G&M2%T%T%VN%1370)1+)1+/( 	'vzz,'CWM'"
 	
 ZZ$*113EC/00)'U+'+GO$*6::lB+GQs>??~~c*'+GO$*6::lB+GQ$*..w7@5 " 	w'! 	DY$)D)DS%)P+/(.vzz,/KWU3EE BC		D 	D 	D $) &vzz,'CWM3D59::e  	&%N	&R	D 	D  'Cs1v&& 'Cs1v&&'sp   BI! -AI? /AI? I? AI3	I? )7I? !I0/I03I<8I? ?	KJ#K#K/K
K
Kc                     | yi }dD ]Z  }t        | |d      }t        |t              r$|j                         r|j                         ||<   D|dk(  sJt	        |      sV|||<   \ |xs dS )a  Build an aux-client main_runtime override from a live agent.

    Lets a one-shot inherit the session's provider/model/credentials so its
    output matches the model the user is actually coding with, instead of
    falling back to the cheapest auto-detected backend.
    N)r  r   r  rG  r  	auth_moderG  )r   r  r6   r7   r|  )rN  r  fieldrE  s       rD   _main_runtime_from_agentr    sr     }GV #ud+eS!ekkm"[[]GENiHUO"GEN# ?dr   ro   c           
         |j                  d      xs dj                         xs d}|j                  d      xs d}|j                  d      xs d}t        |j                  d      t              r|j                  d      ni }|j                  d      xs dj                         xs d}	 t	        |j                  d	      xs d
      }|j                  d      }|	 t        |      }|s?t        |      j                         s&t        |      j                         st        | dd      S t        j                  |j                  d      xs d      }	|	rt        |	j                  d            nd}
	 ddlm}  |||||||||nd|
      }t%        | d|i      S # t
        t        f$ r d
}Y w xY w# t
        t        f$ r d}Y w xY w# t        $ r }t        | dt        |            cY d}~S d}~wt        $ r }t        | dt        |            cY d}~S d}~wt        $ r0}t         j#                  d|       t        | dd|       cY d}~S d}~ww xY w)a  Run a single stateless LLM request outside any conversation.

    Generic helper for small generative chores (e.g. a commit message from a
    diff). Accepts either a named ``template`` + ``variables`` or an explicit
    ``instructions`` / ``input`` pair. When ``session_id`` resolves to a live
    session the call inherits that agent's model; otherwise it uses the
    configured auxiliary ``task`` backend. Never mutates session history, so
    prompt caching is untouched.
    templater   Ninstructionsr  	variablestasktitle_generation
max_tokensi   temperature  z5llm.oneshot requires a template or instructions/inputr  rN  r   )run_oneshotg333333?)r  
user_inputr  r  r  r  r  main_runtimei  i  zllm.oneshot failed: %s  zone-shot generation failed: r   )r   r7   r  r   r  rS  r>  r  r6   r  rQ   r  agent.oneshotr  KeyErrorr5   r  r   ra  )r   r  r  r  r  r  r  r  r  r#  r  r  r   r  s                 rD   r  r    s*    

:&,"335=H::n-3LG$*J+5fjj6Mt+T

;'Z\IJJv4"4;;=SASDL19T:
 **]+K	,K C-335c*o>S>S>UCVWW mmFJJ|4:;GEL+GKK,@ARVLC-%!!'2'>C%	
$ sVTN##K z" 
 :& 	K	.  'Cs1v&& 'Cs1v&& C/3C!=aSABBCsf   ,F F0 1G F-,F-0GG	IG+%I+I7HII%I	I	Izhandoff.requestc           	         t        ||       \  }}|r|S |j                  d      rt        | dd      S |j                  dd      xs dj                         j	                         }|st        | dd      S 	 dd	lm}m} 	  ||      }	  |       }	|	j                  j                  |      }
|
r|
j                  st        | dd| d      S |	j                  |      }|r|j                  st        | dd| d      S t        |       t!        |      5 }|t#        | d      cddd       S |d   }	 |j%                  |      s|j'                  |d|dd         |j)                  ||      }	 ddd       st        | dd      S t-        | d||j.                  d      S # t        $ r}t        | d
d|       cY d}~S d}~ww xY w# t        t        f$ r t        | dd| d      cY S w xY w# t        $ r}t        | d
d|       cY d}~S d}~ww xY w# t        $ r)}t        | dt+        |            cY d}~cddd       S d}~ww xY w# 1 sw Y   xY w)a  Queue a handoff of this session to a messaging platform.

    Desktop parity with the CLI ``/handoff`` command: we only write
    ``handoff_state='pending'`` onto the persisted session row. The actual
    transfer is performed by the separate ``hermes gateway`` process, whose
    ``_handoff_watcher`` claims the row, re-binds the session to the platform's
    home channel, and forges a synthetic turn. The desktop then polls
    ``handoff.state`` for the terminal result.
    r  r[  uL   session busy — wait for the current turn to finish, then retry the handoffr  r   r~  zplatform requiredr   )rD  load_gateway_config  zcould not load gateway config: Ni  zunknown platform ''i  z
platform 'z*' is not configured/enabled in the gatewayi  zno home channel configured for u8    — set one with /sethome on the destination chat firstr  r  r   zhandoff-r   i  uN   session is already in flight for handoff — wait for it to settle, then retryT)r  r   r  	home_name)r  r   r  r7   r  rF  rD  r  r5   r>  r  	platformsr  get_home_channelchat_idr&  r  r  rb  r  request_handoffr6   ra  rI   )r   r  r#  r  platform_namerD  r  r  r  	gw_configpcfgr  rk  rw  r   s                  rD   r  r  3  s     ,LGS

{{9Z
 	
 ZZ
B/52<<>DDFMC233
F@FM*F')	 ""8,Dt||'QR
 	

 %%h/Dt||-m_ =5 5
 	
 7#	W	 	+:(48	+ 	+ m$	+>>#&$$SHS!WI*>?##C7B	+ \
 	

 %		
 _  FC!@DEEF ! FC!3M?!DEEF  FC!@DEEF<  	+T3q6**	+ 	+	+	+ 	+s   4F =G  G& I&I,;H	F=#F82F=8F=  G#"G#&	H	/H>H	H		H>H9*H>+I9H>>II
zhandoff.statec                 ^   t        ||       \  }}|r|S t        |      5 }|t        | d      cddd       S |j                  |d         }ddd       xs i }t	        | |j                  d      xs d|j                  d      xs d|j                  d      xs dd	      S # 1 sw Y   XxY w)
zPoll the handoff state for a session.

    Returns ``{state, platform, error}`` where ``state`` is one of
    ``pending|running|completed|failed`` (or empty when no handoff record
    exists). Desktop polls this after ``handoff.request``.
    Nr  r  r   stater   r  r   )r  r  r   )r  r  r  get_handoff_statera  r   )r   r  r#  r  rk  r4  s         rD   r  r    s      ,LGS

	W	 >:(48> > %%gm&<=>
 \rFZZ(.B

:.4"ZZ(.B	
 > >s   B#B##B,zhandoff.failc                    t        ||       \  }}|r|S t        |j                  d      xs d      j                         dd }t	        |      5 }|t        | d      cddd       S |d   }|j                  |      xs i }|j                  d      xs d	}|d
v r*|j                  ||       t        | ddd      cddd       S 	 ddd       t        | dd      S # 1 sw Y   xY w)zMark an in-flight handoff as failed so the user can retry.

    Desktop calls this when its bounded poll times out. Only pending/running
    rows are changed so a late success from the gateway watcher is not clobbered.
    r   zhandoff failedN  r  r  r   r  r   >   r  r  Tfailed)r  r  F)	r  r6   r   r7   r  r  r  fail_handoffra  )	r   r  r#  r  r\  rk  rw  r4  r  s	            rD   r  r    s     ,LGS

G$8(89??A$3GF	W	 A:(48A A m$%%c*0b

7#)r**OOC(sth?@A A +A suu566A As   C'ACC%ry   c                     t        ||       \  }}|r|S |j                  d      }t        |      }|	|sddddd}	 ddlm}  |       }|r||d<   t        | |      S # t
        $ r Y w xY w)NrN  r   )r  r  r   r  )nous_credits_linescredits_lines)r  r   r  agent.account_usager  r5   ra  )r   r  r#  r  rN  r  r  creditss           rD   r  r    s    ,LGS

KK E)'2E}Ua1qA
:$&%,E/" sE?  s   A 	A('A(zsession.context_breakdownc                    t        ||       \  }}|r|S |j                  d      }|t        |      xs t        d       }t	        | g |j                  dd      xs d|j                  dd      xs d|j                  dd      xs d|j                  dd      xs |j                  dd      xs dt        |      j                  dd      d	      S |d
   5  t        |j                  dg             }d d d        	 ddlm}  ||      }t	        | |      S # 1 sw Y   %xY w# t        $ r}	t        | dd|	       cY d }	~	S d }	~	ww xY w)NrN  r  r   r  r  r  r   r   )
categoriesr  r  r  estimated_totalr   rO  rP  )!compute_session_context_breakdownr=  z%Could not compute context breakdown: )r  r   r  r  ra  r>  r_  agent.context_breakdownr  r5   r  )
r   r  r#  r  rN  r  rP  r  r  r!  s
             rD   r  r    sO   ,LGS

KK E}'0DJt4D $yy:?a#(99->#B#Ga %		.! < A#(99^Q#?#]599WVWCX#]\])'266wC

 
	
 
	  3w{{9b123NM3E7C sG3 3  NC!FseLMMNs*   D9D  D 	E)D>8E>Ec                 f    	 ddl m} |j                  t        |             S # t        $ r i cY S w xY w)zReal (padding-trimmed) frame count per state, for the desktop canvas.

    Fail-open: a decode hiccup returns ``{}`` and the canvas falls back to its
    static ``framesPerState`` rather than breaking the (cosmetic) pet.
    r   )render)	agent.petr  state_frame_countsr6   r5   )spritesheetr  s     rD   _pet_frame_countsr    s4    $(([)9:: 	s   " 00_pet_payload_cachec                 x    	 | j                         }|j                   d|j                   S # t        $ r Y yw xY w)z,Stable revision id for one spritesheet file.r  z0:0)rQ  st_mtime_nsst_sizer5   )r  rQ  s     rD   _pet_sheet_revisionr    sC    !""#1T\\N33 s   *- 	99scalec          	          	 | j                   j                         }t        | j                         |j                  |j
                  | j                  | j                  t        |d      fS # t        $ r Y yw xY w)z1Cache key for the expensive sprite payload build.Nr  )	r  rQ  r5   r6   r  r  r  display_namer  )petr  rQ  s      rD   _pet_payload_cache_keyr    sn    ##% 	COOeQ   s   A) )	A54A5c                 <   t        |       }t        | j                  d      t               rt        | d         |d<   t        | j                  d      t               rt        | d         |d<   t        | j                  d      t              rt        | d         |d<   |S )zCShallow-clone cached payloads so callers can't mutate shared state.framesByStateframesByRow	stateRows)r   r  r   r_  )r  outs     rD   _clone_pet_payloadr    s    
w-C'++o.5#GO$<=O'++m,d3!'-"89M'++k*D1 45KJr   c           	         	 ddl m} ddlm}m} |j                  |       5 }|j                  d      }ddd       t        dj                  |j                  z        }t        d|j                  |j                  z        }|j                  |      }i }	t        |d|       D ]  \  }
}|
|j                  z  }d}t        |      D ]X  }||j                  z  }|j                  ||||j                  z   ||j                  z   f      }|j!                  |      r n|dz  }Z ||	|<    |	S # 1 sw Y   xY w# t"        $ r i cY S w xY w)z3Real frame count per concrete spritesheet row name.r   r  )	constantsr  RGBANr   )r  r  r  r  r  r1   convertrF  r}  FRAME_Wr~  FRAME_Hstate_rows_for_grid	enumerater  crop_frame_is_blankr5   )r  r  r  r  openedr  r3  	row_countr$  r  row_idxrI   r  r.  colleftr@  s                    rD   _pet_row_frame_countsr  +  sN   /ZZ$ 	+NN6*E	+1ekkY%6%6675<<9+<+<<=	,,Y7 &tJY'78 		MGTI---CET{ Y...

D#ti6G6G/GyO`O`I`#ab))%0
 CI		 
!	+ 	+"  	s(   D4 D(C4D4 (D1-D4 4EEc                     ddl m}  	 ddlm}  |       }t	        |j                  d      t              r|j                  di       ni }t	        |j                  d      t              r|j                  di       ni }t        |j                  d| j                        xs | j                        S # t        $ r | j                  cY S w xY w)zGConfigured ``display.pet.scale`` (or the engine default), never raises.r   r  r  r   r  r  )
r  r  r^  r  r  r   r   r  DEFAULT_SCALEr5   )r  r  r  r   pet_cfgs        rD   _pet_config_scaler  G  s    #'1m,6swwy7I4,P#'')R(VX,6w{{57I4,P'++eR(VXW[[)*A*AB]iF]F]^^ '&&&'s   B%B. .CCc                   ddl }ddlm} t        | |      }|1t        5  t
        j                  |      }ddd       t        |      S | j                  j                         }| j                  j                  j                         }|dk(  rdnd}| j                  | j                  ||j                  |      j                  d      t!        | j                        |j"                  |j$                  |j&                  t)        | j                        t+        | j                        |j,                  |t/        | j                        d	}	|st        5  |	t
        |<   t1        t
              d
kD  r>t
        j3                  t5        t7        t
                           t1        t
              d
kD  r>ddd       t        |	      S t        |	      S # 1 sw Y   xY w# 1 sw Y   t        |	      S xY w)zBuild the renderer payload (spritesheet bytes + geometry) for *pet*.

    Shared by ``pet.info`` (the active mascot) and ``pet.hatch`` (the unadopted
    preview) so both feed the desktop canvas / TUI from one shape.
    r   Nr  r  .pngz	image/pngz
image/webpr@  )r  displayNamemimespritesheetBase64spritesheetRevisionframeWframeHframesPerStater  r  loopMsr  r  r   )base64r  r  r  _pet_payload_cache_lockr  r   r  r  
read_bytesrb  r  r  r  standard_b64encodedecoder  r  r  FRAMES_PER_STATEr  r  LOOP_MS_pet_state_rowsr  r(  nextiter)
r  r  r  r  	cache_keycachedr  rb  r  r  s
             rD   _pet_sprite_payloadr  V  s    #&s%8I$ 	7'++I6F	7%f--
//
$
$
&C__##))+F F*;D''#66s;BB7K23??C#####44*3??;,S__=##$S__5G $ 	G,3y)()A-"&&tD1C,D'EF ()A-	G g&&g&&9	7 	70	G g&&s   GAGGG(c                  (   ddl m} m} 	 ddlm}  |       }t        |j                  d      t              r|j                  di       ni }t        |j                  d      t              r|j                  di       ni }t        |j                  d            }t        |j                  dd      xs d      }|r|j                  |      nd	}t        |j                  d
| j                        xs | j                        }	|||	fS # t        $ r i }Y w xY w)z2Resolve configured active pet + scale from config.r   )r  storer  r   r  r  r  r   Nr  )r  r  r  r^  r  r  r   r   r5   r   r6   resolve_active_petr  r  )
r  r  r  r  r   r  r  configured_slugr  r  s
             rD   _pet_active_selectionr    s    *1m,6swwy7I4,P#'')R(VX,6w{{57I4,P'++eR(VX 7;;y)*G'++fb17R8O7>%
"
"?
3DC'++gy'>'>?Z9CZCZ[EC  s   A3D DDc                 6   	 ddl m} ddlm} |j	                  |       5 }t        d|j                  |j                  z        }ddd       t        |j                              S # 1 sw Y   #xY w# t        $ r ddlm} t        |j                        cY S w xY w)a  Row taxonomy for the concrete active pet sheet.

    Hermes has to support both the legacy 8-row petdex atlas and the current
    Codex/petdex 9-row atlas. The desktop canvas gets this list and indexes it
    with the same `PetState` names the Python renderer uses.
    r   r  r  r   N)r  r  r  r  r1   rF  r~  r  r_  r  r5   
STATE_ROWS)r  r  r  r  r  s        rD   r  r    s    *'ZZ$ 	BAu||y/@/@@AI	BI11)<==	B 	B  *'I(())*s(   A1 $A%!A1 %A.*A1 1$BBrg   c                    	 t               \  }}}|r||j                  st        | ddi      S t        | ddit        ||            S # t        $ r.}t
        j                  d|       t        | ddi      cY d}~S d}~ww xY w)u=  Return the active petdex pet for surfaces that render sprites.

    Shared by the desktop (canvas) and the TUI (half-block). Carries the
    spritesheet bytes (base64) plus the engine's frame geometry + state-row
    taxonomy so the renderer is a thin, framework-native consumer. The
    activity→state decision is mirrored from ``agent.pet.state`` client-side.

    Agent-independent (reads config + disk), so it works on any session and
    before the agent finishes building. Fail-open: returns ``enabled=False``
    on any error rather than erroring the surface.
    Nr  FTr  zpet.info failed: %s)r  r  ra  r  r5   r  r*  r   r  r  r  r  r!  s         rD   r  r    s    	,35e#+SZZsY.//3DR,?5,QRSS ,*C03E*++,s"   +A	 A	 		B #A;5B ;B zpet.info.metac           
      B   	 t               \  }}}|r||j                  st        | ddi      S t        | d|j                  |j                  |t        |j                        d      S # t        $ r.}t        j                  d|       t        | ddi      cY d}~S d}~ww xY w)z?Cheap active-pet metadata used to avoid full payload refreshes.Nr  FT)r  r  r  r  r  zpet.info.meta failed: %s)
r  r  ra  r  r  r  r  r5   r  r*  r  s         rD   r  r    s    ,35e#+SZZsY.//"//':3??'K	
 		
  ,/53E*++,s"   +A' 8A' '	B0#BBBrh   c                    	 ddl m}m}m} ddlm} 	 ddlm}  |       }t        |j                  d      t              r|j                  di       ni }t        |j                  d      t              r|j                  di       ni }	t        |	j                  d            st        | ddi      S |j                  t        |	j                  d	d
      xs d
            }
|
|
j                   st        | ddi      S t        |j                  d      xs  |j"                  j$                  j&                        }t)        |	j                  d|j*                        xs |j*                        }t-        |j                  d      xs d      xs" |j/                  ||	j                  dd            }|j                  d      rt        |	j                  dd      xs d      j1                         }|dv r|j3                         n|}|dk(  r|j5                  |
j6                        } |t        |
j8                        d|      j;                  ||      }|rrt=        |d         xs d}t        | d|
j6                  |
j>                  |d||jA                  |      |d   |d   |d   |d   |jB                  tE        d|      z  |d      S  |t        |
j8                        d||      }|jG                  |      xs d}g }tI        |      D ]P  }|jK                  |||      }|jM                  |D cg c]  }|D cg c]  \  }}g || c}} c}}}       R t        | d|
j6                  |
j>                  |||jB                  tE        d|      z  ||d       S # t        $ r i }	Y w xY wc c}}w c c}}}w # t        $ r.}tN        jQ                  d!|       t        | ddi      cY d}~S d}~ww xY w)"a  Return half-block cell frames for one pet state (TUI renderer).

    The TUI can't draw a canvas, so the engine downsamples the spritesheet to
    a grid of half-block cells and the Ink side paints them with native color
    props. Each cell is ``[tr,tg,tb,ta, br,bg,bb,ba]`` (top + bottom pixel).

    Params: ``state`` (idle/run/review/failed/wave/jump), ``cols`` (width).
    Fail-open: ``enabled=False`` on any problem.
    r   )r  r  r  )PetRendererr  r   r  r  Fr  r   Nr  r  r3  unicode_colsgraphicsrender_moder  )r   r  kitty)r  r  )image_idframesr   Tr$  placeholder)r  r  r  r  r  imageIdcolorr3  r$  r  r  frameMsr  rC  )r  r  r
  )r3  )r  r  r  r  r3  r  r  r  zpet.cells failed: %s))r  r  r  r  agent.pet.renderr	  r^  r  r  r   r   r5   r   ra  r   r6   r  PetStateIDLErE  r  r  r  resolve_colsr  detect_terminal_graphicskitty_image_idr  r  kitty_payloadr  r  kitty_color_hexr  rF  frame_countr  cellsr  r  r*  )r   r  r  r  r  r	  r  r  r   r  r  r  r  r3  
configuredgmoder  r  kcountrendererr.  r  igridrl  r  r  r!  s                               rD   r  r    s   Z,660	5-C0:3779;Mt0Tcggi,Z\G0:7;;u;Mt0Tgkk%,Z\G GKK	*+sY.//&&s7;;vr+B+Hb'IJ;cjjsY.//FJJw'H9+=+=+B+B+H+HIgkk'9+B+BC^yG^G^_6::f%*+ly/E/EeW[[YgijMk/l ::j!W[[?I6JPPRJ9C|9SF335YcE!00:%(we--9   !238qF'+$'HH+.+;+;%*(/'/%+%;%;H%E$+FO$+FO+2=+A&-h&7'0'8'83q&>'I%* &  	
 $$U+0qu 	A>>%>6DMMGKLLs;msF/C/&/;L	 "//$,,s1e}< 	
 	
C  	G	| <L   ,+S13E*++,s{   N4 A3N 'N4 .A	N4 8GN4 A)N4 *
N-4N'N-
A
N4 N$ N4 #N$$N4 'N--N4 4	O+=#O& O+&O+rp   c           
         t        |j                  d            }	 ddlm} 	 ddlm}  |       }t        |j                  d      t              r|j                  di       ni }t        |j                  d      t              r|j                  di       ni }|j                         D ci c]  }|j                  | }	}g }
t               }	 ddlm}m} |r |        |rg n |       D ]  }|j                  |j                         |
j!                  |j                  |j"                  |j                  |	v |j$                  d|j$                  v |j                  |	v xr |	|j                     j&                  d	        	 |	j-                         D ]5  \  }}||vs|
j!                  ||j"                  dd|j&                  d       7 t/        | t        |j                  d            t1        |j                  dd      xs d      |
d      S # t        $ r i }Y w xY wc c}w # t        $ r }t(        j+                  d
|       Y d}~d}~ww xY w# t        $ r0}t(        j+                  d|       t/        | ddg d      cY d}~S d}~ww xY w)a0  List adoptable pets for the desktop appearance picker.

    Returns the petdex gallery merged with local install state plus the
    current config (active slug + enabled). Agent-independent. Fail-open:
    returns whatever is installed locally if the gallery can't be reached, so
    the picker still works offline.

    Param ``localOnly`` (bool): skip the remote petdex manifest fetch and return
    only locally-installed pets. The desktop loads this first so the user's own
    pets render instantly instead of waiting on the (possibly slow) manifest.
    	localOnlyr   r  r  r   r  )fetch_manifestprefetchz	/curated/)r  r  	installedspritesheetUrlcurated	generatedz%pet.gallery manifest fetch failed: %sNTr   )r  r  r)  r*  r,  r  r  )r  r  petszpet.gallery failed: %sF)r   r   r  r  r^  r  r  r   r5   installed_petsr  r^  agent.pet.manifestr'  r(  r%  r  r  spritesheet_urlr,  r  r*  rf  ra  r6   )r   r  
local_onlyr  r  r  r   r  r  r)  galleryr  r'  r(  r  r!  r  r  s                     rD   r  r  D  sT    fjj-.JAF#	5-C0:3779;Mt0Tcggi,Z\G0:7;;u;Mt0Tgkk%,Z\G ).(<(<(>?1QVVQY?	? 	GC 
)~/? $ %

','9'9%*ZZ9%<*/*?*? $/%2G2G#G%*ZZ9%<%`5::AVA`A`
& #* 
	ID#4 $'*'7'7%)*,%(]]
	 I 67gkk&"5;<
 	
]  	G	 @6  	GLL@#FF	G0  F-s33ERDEEFs   I A3H
 I (H<I B1H! <I A1I 
HI HI !	I
*I I I

I 	J%J;JJrk   c           	         t        |j                  d      xs d      j                         }|st        | dd      S 	 ddlm} ddlm} ddlm	} 	 |j                  |      } ||       t        | d||j                  d      S # |j                  |f$ r}t        | d	d
| d|       cY d}~S d}~ww xY w# t        $ r0}t        j!                  d|       t        | d	d|       cY d}~S d}~ww xY w)zAdopt a pet from the desktop picker: install (if needed) + activate.

    Params: ``slug`` (required). Writes ``display.pet.*`` to config and returns
    ``{ok, slug, displayName}``. The surface re-pulls ``pet.info`` to render it.
    r  r     missing slugr   r&  )ManifestError)_set_active  zcould not adopt 'z': NTr   r  r  zpet.select failed: %szpet.select failed: )r6   r   r7   r  r  r  r/  r6  hermes_cli.petsr7  install_petPetStoreErrorra  r  r5   r  r*  )r   r  r  r  r6  r7  r  r!  s           rD   r  r    s     vzz&!'R(..0DC~..<#4/	G##D)C 	D3tT#BRBRSTT ##]3 	GT%6tfCu#EFF	G  <,c2C!4SE:;;<sM   B4 B !!B4 B1B,&B1'B4 ,B11B4 4	C-=%C("C-(C-z
pet.removec                    t        |j                  d      xs d      j                         }|st        | dd      S 	 ddlm} ddlm} |j                  |      }	  ||       t        | ||d
      S # t        $ r }t        j                  d|       Y d	}~3d	}~ww xY w# t        $ r0}t        j                  d|       t        | dd|       cY d	}~S d	}~ww xY w)a6  Uninstall a pet from the desktop picker (delete its on-disk directory).

    Params: ``slug`` (required). If the removed pet was the active one, the
    display is turned off so nothing tries to render a now-missing sprite.
    Returns ``{ok, slug}`` where ``ok`` reflects whether a directory was deleted.
    r  r   r4  r5  r   r&  )_clear_active_ifz#pet.remove config update failed: %sNr   r  zpet.remove failed: %sr8  zpet.remove failed: )r6   r   r7   r  r  r  r:  r>  
remove_petr5   r  r*  ra  )r   r  r  r  r>  removedr!  s          rD   r  r    s     vzz&!'R(..0DC~..<#4""4(	ET" 3w566  	ELL>DD	E  <,c2C!4SE:;;<sG   B A2 #B 2	B;BB BB 	C'%CCCz
pet.exportc                    t        |j                  d      xs d      j                         }|st        | dd      S 	 ddl}ddlm} |j                  |      \  }}t        | d||j                  |      j                  d	      d
      S # t        $ r0}t        j                  d|       t        | dd|       cY d}~S d}~ww xY w)u  Export an installed pet as a re-importable ``.zip`` (pet.json + sprite).

    Params: ``slug`` (required). Returns ``{ok, filename, zipBase64}`` — the
    client decodes the base64 and saves it. Heavy-ish (reads + zips files) but
    small; runs inline.
    r  r   r4  r5  r   Nr&  Tr@  )r   filename	zipBase64zpet.export failed: %sr8  zpet.export failed: )r6   r   r7   r  r  r  r  
export_petra  r  r  r5   r  r*  )r   r  r  r  r  rC  r  r!  s           rD   r  r    s     vzz&!'R(..0DC~..<#))$/$XF<U<UVZ<[<b<bcj<kl
 	
  <,c2C!4SE:;;<s   AB	 		C%B=7C=Cz
pet.renamec                 X   t        |j                  d      xs d      j                         }t        |j                  d      xs d      j                         }|st        | dd      S |st        | dd      S 	 ddlm} |j                  ||      }|st        | d	d
      S ||k7  r	 ddlm}  |||       t        | d||d      S # t        $ r }t        j                  d|       Y d}~4d}~ww xY w# t        $ r0}t        j                  d|       t        | d	d|       cY d}~S d}~ww xY w)a$  Rename an installed pet's display name + realign its slug/dir.

    Params: ``slug`` + ``name`` (both required). Lets the generate flow hatch
    with a provisional name and apply the user's chosen name at adopt time.
    Returns ``{ok, slug, displayName}`` with the (possibly new) slug.
    r  r   rI   r4  r5  missing namer   r&  r8  zpet.rename failed)_rename_active_ifz#pet.rename config update failed: %sNTr9  zpet.rename failed: %szpet.rename failed: )r6   r   r7   r  r  r  
rename_petr:  rH  r5   r  r*  ra  )r   r  r  rI   r  new_slugrH  r!  s           rD   r  r    s'    vzz&!'R(..0Dvzz&!'R(..0DC~..C~..<###D$/T#677 tI=!$1 3tXdKLL  IBCHHI  <,c2C!4SE:;;<sN   8&C0 C0 %C 4C0 	C-C(#C0 (C--C0 0	D)9%D$D)$D)rj   c           	         t        |j                  d      xs d      j                         }|st        | dd      S 	 ddl}ddlm} |j                  |t        |j                  d      xs d      	      }|st        | d
|d      S t        | d|d|j                  |      j                  d      z   d      S # t        $ r/}t        j                  d|       t        | d
|d      cY d}~S d}~ww xY w)u  Return a small idle-frame PNG (data URI) for one pet — the picker preview.

    Cropped + cached server-side so the renderer gets a same-origin data URL
    instead of a CDN ``<img>`` (which the desktop CSP / R2 hotlink rules break).
    Params: ``slug`` (required), ``url`` (optional petdex spritesheet URL used
    only for not-yet-installed pets). Fail-open: ``{ok: false}`` with no error.
    r  r   r4  r5  r   Nr&  r  )
source_urlFr?  Tdata:image/png;base64,r@  )r   r  dataUrizpet.thumb failed: %s)r6   r   r7   r  r  r  r  thumbnail_pngra  r  r  r5   r  r*  )r   r  r  r  r  r  r!  s          rD   r  r    s     vzz&!'R(..0DC~..5#""4C

58I8OR4P"Qs5$7883f6O6OPT6U6\6\]d6ee
 	
  5+S13ud3445s$   A	B8 0B8 8	C0$C+%C0+C0zpet.disablec                     	 ddl m}  |d       t        | ddi      S # t        $ r0}t        j                  d|       t        | dd|       cY d	}~S d	}~ww xY w)
zITurn the pet off from the desktop picker (``display.pet.enabled=false``).r   )_set_enabledFr   Tzpet.disable failed: %sr8  zpet.disable failed: N)r:  rQ  ra  r5   r  r*  r  )r   r  rQ  r!  s       rD   r  r  4  sY    =0U3t%% =-s3C!5cU;<<=s    	A%AAAz	pet.scalec                     	 ddl m}  ||j                  d            \  }}|rt        | d|      S t	        | d|d      S # t
        $ r0}t        j                  d|       t        | dd	|       cY d
}~S d
}~ww xY w)a  Persist ``display.pet.scale`` from the desktop slider. Params: ``scale``.

    Clamped to the engine bounds. The renderer updates its own ``$petInfo`` for
    instant feedback; this just makes the change durable + visible to the other
    terminal surfaces on their next read.
    r   )set_pet_scaler  r4  T)r   r  zpet.scale failed: %sr8  zpet.scale failed: N)r:  rS  r   r  ra  r5   r  r*  )r   r  rS  r  r  r!  s         rD   r  r  B  s{    	;1"6::g#67
sT3''3te455 ;+S1C!3C59::;s"   .A  A   	A9	%A4.A94A9c                  R    ddl m}   |        dz  dz  }|j                  dd       |S )z=Profile-scoped staging dir for in-progress generation drafts.r   r
   cachezpet-genTparentsr   r=  r
   mkdirr
   r  s     rD   _pet_gen_rootr\  W  s,    0w&2DJJtdJ+Kr   )	max_age_sr]  c                D   ddl }ddl}	  |j                         }| j                         D ]G  }|j                         s||j	                         j
                  z
  |kD  s5|j                  |d       I y# t        $ r }t        j                  d|       Y d}~yd}~ww xY w)z=Drop stale draft staging dirs so cache never grows unbounded.r   NT)ignore_errorszpet-gen sweep failed: %s)
shutilr3   iterdiris_dirrQ  rR  rmtreer5   r  r*  )r  r]  r`  r3   r  childr!  s          rD   _pet_gen_sweepre  `  s    6diik\\^ 	9E||~#

(=(="=	"Ie48	9  6/556s"   4A6  A6  A6 6	B?BBrh  )max_pxrf  c                p   ddl }ddl}ddlm} |j	                  |       5 }|j                  d      }ddd       j                  ||f|j                         |j                         }|j                  |d       d|j                  |j                               j                  d      z   S # 1 sw Y   {xY w)	zBDownscaled PNG data URI for a draft image (small preview payload).r   Nr  r  PNG)formatrM  r@  )r  ior  r  r1   r  	thumbnailLANCZOSBytesIOsaver  getvaluer  )r.   rf  r  rj  r  r  r  bufs           rD   _pet_png_data_urirq  n  s    	D	 %VnnV$%MM66"EMM2
**,CHHSH#f&?&?&O&V&VW^&___% %s   B,,B5_pet_cancelledpngjpgwebpgif)rs  jpegrt  ru  rv  r   HERMES_PET_REFERENCE_MAX_BYTESi   ref_rawc                    ddl }ddl}ddl}|j                  d| |j                        }|st        d      |j                  d      j                         }t        j                  |      }|t        d      dj                  |j                  d      j                               }t        |      d	z  d
z  }	|	t        kD  rt        d      	 |j                  |d      }
t        |
      t        kD  rt        d      |d| z  }|j!                  |
       |gS # |j                  t
        f$ r}t        d      |d}~ww xY w)z@Decode + validate a reference-image data URL into the stage dir.r   Nz*^data:image/([a-zA-Z0-9.+-]+);base64,(.*)$zinvalid reference image formatr   z unsupported reference image typer   r   r(  r  zreference image too largeTvalidatezinvalid reference image dataz
reference.)r  binasciirematchDOTALLr>  groupr  _PET_REFERENCE_MIME_EXTr   r*   r  r  _PET_REFERENCE_MAX_BYTES	b64decodeErrorwrite_bytes)ry  stager  r}  _rer  r  extr  approxr  r!  ref_paths                rD   #_pet_reference_images_from_data_urlr    s7   IICWcjjYE9::;;q>!D
!
%
%d
+C
{;<<ggekk!n**,-G'lQ1$F((455Bw6 3x**455C5))H: NNJ' B78cABs   D D>-D99D>r  c                 d    t         5  t        j                  |        ddd       y# 1 sw Y   yxY w)z?Clear a stale cancel flag at the start of a generate/hatch run.N_pet_cancel_lockrr  discardr  s    rD   _pet_cancel_armr    s(    	 &u%& & &   &/c                 d    t         5  t        j                  |        d d d        y # 1 sw Y   y xY wr   )r  rr  r%  r  s    rD   _pet_cancel_requestr    s(    	 "5!" " "r  c                 J    t         5  | t        v cd d d        S # 1 sw Y   y xY wr   )r  rr  r  s    rD   _pet_is_cancelledr    s"    	 '&' ' 's   "c                 d    t         5  t        j                  |        d d d        y # 1 sw Y   y xY wr   r  r  s    rD   _pet_cancel_releaser    s(    	 &u%& & &r  z
pet.cancelc                     t        |j                  d      xs d      j                         }|rt        |       t	        | ddi      S )a  Signal an in-flight ``pet.generate``/``pet.hatch`` (by token) to stop.

    Best-effort + idempotent: cancelling an unknown/finished token is a no-op.
    Stays off the worker pool so it lands while a heavy generation is occupying
    it. Returns ``{ok: True}``.
    r  r   r   T)r6   r   r7   r  ra  )r   r  r  s      rD   r  r    sA     

7#)r*002EE"sT4L!!r   zpet.generate.statusc                 J   	 ddl m}m}m} 	  |d       d}	  |       }t        | ||d      S # |$ r d}Y  w xY w# t        $ r"}t
        j                  d|       g }Y d}~Bd}~ww xY w# t        $ r/}t
        j                  d	|       t        | dg d      cY d}~S d}~ww xY w)
u#  Whether pet generation is possible right now.

    True only when a reference-capable image backend (Nous Portal / OpenRouter /
    OpenAI gpt-image) is configured — the desktop checks this on open so it can
    offer setup instead of a dead prompt. Cheap (config + plugin discovery).
    r   )GenerationErrorlist_sprite_providersresolve_providerT)require_referencesFzpet provider list failed: %sN)r  re  zpet.generate.status failed: %s)agent.pet.generate.imagegenr  r  r  r5   r  r*  ra  )r   r  r  r  r  r  re  r!  s           rD   r  r    s    ?	
 	
	5I	-/I 3iiHII  	I	  	LL7=I	  ?5s;3e"=>>?sY   
A* / < A* 9A* 9A* 	A'A"A* "A''A* *	B"3$BB"B"rq   c                    t        |j                  d      xs d      j                         }t        |j                  d      xs d      j                         }|s|st        | dd      S 	 t	        dt        dt        |j                  d      xs d                  t        |j                  d	      xs d
      j                         xs d
}	 ddl	ddl
}ddlm} ddlm}m} t!               }	t#        |	        |j$                         j&                  dd t)               |	z  j+                  dd       d}
|r	 t-        |      }
t        |j                  d      xs d      j                         }d}|r	  |t1        |
      |      }|xs d}g 	 t3        ddd       dt        ddffd}	  ||||
||fd       t;              }t/               |rt        | dd      S st        | dd      S j=                  d  !       t?        | dd"      S # t        t        f$ r dY w xY w# t        $ r+}t/               t        | dt        |            cY d}~S d}~ww xY w# |$ r+}t/               t        | dt        |            cY d}~S d}~ww xY w# t4        $ r!}t6        j9                  d|       Y d}~#d}~ww xY w# |$ r+}t/               t        | dt        |            cY d}~S d}~ww xY w# t4        $ r0}t6        j9                  d#|       t        | dd$|       cY d}~S d}~ww xY w)%u  Generate candidate base looks for a new pet (the draft/variant step).

    Params: ``prompt`` (required unless ``referenceImage`` is given), ``count``
    (default 4), ``style`` (default ``auto``), ``referenceImage`` (optional data
    URL — a user photo/reference every draft is grounded on, e.g. to make *their*
    pet). Returns ``{ok, token, drafts:[{index, dataUri}]}`` — the token keys the
    staged base images for a later ``pet.hatch``. Heavy (network): worker pool.
    r  r   referenceImager4  zmissing promptr   r  r.  r  r  r   N)generate_base_draftsr  r     TrW  r  r  preferr8  z"a pet based on the reference imagepet.generate.progress)r  r.  z!pet.generate init emit failed: %sr  r   c           	      T   d|  dz  }	 j                  ||       t        |      }j                  | |d       	 t        dd	| |d       y # t        $ r!}t        j	                  d| |       Y d }~y d }~ww xY w# t        $ r }t        j	                  d|       Y d }~y d }~ww xY w)	Ndraft-r  z pet.generate draft %d failed: %s)r  rN  r  r   )r  r  rN  r.  z%pet.generate progress emit failed: %s)copyfilerq  r5   r  r*  r  r  )
r  rG  destdata_urir!  r.  r  r`  r  r  s
        rD   	_on_draftz_.<locals>._on_draft8  s    VE7$//DT*,T2 JJ8<=K+#eSXY  ?L  KDcJJKs.   A A> 	A;A66A;>	B'B""B'c                      t               S r   r  r  s   rD   r   z_.<locals>.<lambda>T  s    %6u%= r   )rc  r  reference_imagesr  on_draftis_cancelledzgeneration cancelledz$generation produced no usable draftsc                     | d   S )Nr  r   )ds    rD   r   z_.<locals>.<lambda>`  s
    qz r   r  )r   r  draftszpet.generate failed: %szpet.generate failed: ) r6   r   r7   r  rF  r  r  rS  r>  r`  rt  agent.pet.generater  r  r  r  r\  re  ru  rv  r  rZ  r  r  r   r  r5   r  r*  r  r  ra  )r   r  r  ry  r  rt  r  r  r  r  r  r!  provider_namespriteconceptr  	cancelledr.  r  r`  r  r  s                    @@@@@rD   r  r    s/    H%+,224F&**-.4"5;;=G'C/00As1c&**W"5":;<= 

7#-v.446@&EZ>;Qt 

  "%uD401#FwPU#V  FJJz28b9??A1)TBR=S\ij
 @@	C)2/OP	KS 	K$ 	K 	K(	- !1"= &e,	E"T#9::T#IJJ)*3tesCDDw z" 2  1#E*Cs3x001 # 1#E*Cs3x001  	CLL<cBB	CB  	-&T3s8,,	-  >.4C!6se<==>s   02H) A0L I 0L I8 L J+ -L  K $L 7L "L )H>=H>	I5
 I0*I5+L 0I55L 8J(= J#J(L #J((L +	K4K
L KL L L=L>L LL 	M%L?9M?Mri   c                 ^   t        |j                  d      xs d      j                         }t        |j                  d      xs d      j                         xs ||j                  dd      }t        |j                  d      xs d      j                         }|st        | dd      S |st        | dd	      S 	 t	        |      }	 dd
lm} ddl	m
} ddlm}m} t               |z  d| dz  }	|	j                         st        | dd      S t        |j                  d      xs d      j                         }
d}|
r	  |d|
      }t!               |j#                  |      }dt         dt         ddfd}	  ||	||t        |j                  d      xs d      t        |j                  d      xs |      t        |j                  d      xs d      j                         xs d||fd	      }	 t%               |j'                  |j(                        }|rt+        |t-                     ni }t/        | d|j(                  |j0                  |j2                  j                  d g       |d!      S # t
        t        f$ r d}Y w xY w# |$ r }t        | dt        |            cY d}~S d}~ww xY w# |$ r+}t        | dt        |            cY d}~t%               S d}~ww xY w# t%               w xY w# t4        $ r0}t6        j9                  d"|       t        | dd#|       cY d}~S d}~ww xY w)$u  Turn a chosen base draft into a full pet — installed but NOT yet active.

    Generation is expensive and the result varies, so hatch produces a *preview*
    the surface plays (all frames) before the user commits: the pet is written to
    the store (so it can be rendered + later activated) but the active pet is left
    untouched. Adopt with ``pet.select`` or throw it away with ``pet.remove``.

    Params: ``token`` + ``index`` (from ``pet.generate``), ``name`` (required),
    ``description`` (optional), ``prompt`` (optional concept for row prompts),
    ``style`` (optional). Returns ``{ok, slug, displayName, warnings, pet}`` where
    ``pet`` is the renderer payload. Heavy (network + raster): worker pool.
    r  r   cancelTokenr  r   rI   r4  zmissing tokenrG  r&  )	hatch_petr  r  r  u    draft expired — generate againr  NTr  r8  r  r  r   c                     | |d}| dk(  r0|j                  d      dk(  r|j                  d      \  }}}d|||d}	 t        dd|       y # t        $ r }t        j                  d|       Y d }~y d }~ww xY w)	N)r  r  rl  r  r   )r  r  rX  r  zpet.hatch.progressr   z"pet.hatch progress emit failed: %s)r.  r  r  r5   r  r*  )r  r  r  r  rX  r  r!  s          rD   _on_progressz_.<locals>._on_progress  s     ',v>G~&,,s"3q"8%+\\#%6"tU$)E4RWXH*B8 HA3GGHs   A
 
	A3A..A3descriptionr  r  r  c                      t               S r   r  )cancel_tokens   rD   r   z_.<locals>.<lambda>  s    %6|%D r   )	
base_imager  r  r  r  r  r  on_progressr  r  r  )r   r  r  r  r  zpet.hatch failed: %szpet.hatch failed: )r6   r   r7   r  r  rS  r>  r  r  r  r  r  r  r  r\  is_filer  unique_slugr  load_petr  r  r  ra  r  
validationr5   r  r*  )r   r  r  r  rI   r  r  r  r  r	  r  r  r!  r  r  r  r  r  r  s                     @rD   r  r  g  s    

7#)r*002E
 vzz-06B7==?H5LJJw"Evzz&!'R(..0DC//C~..E
A;#0Q&6%)==||~T#EFF FJJz28b9??A1)T-X 	%  &	H 	HS 	HT 	H	.!

= 9 ?R@FJJx08D9&**W-78>>@JF(D
F  -nnV[[)IL%c1B1DERT%22"--11*bA	
 		
q z" $ # 1Cs3x001>  	-T3s8,,-	-  -  ;+S1C!3C59::;s   ;I0 AK3 0K3 =
J .K3 6A:J0 1A>K3 0JJJ-J("J-#K3 (J--K3 0K 5K
K K# K3 K  K# #K00K3 3	L,<%L'!L,'L,c                    ddl m}m}m}m} d}t        | |      rd}nqt        | |      rd}nbt        | |      rd}nSt        | |      r%t        | dd      rt        | j                        nd}n"t        | dd      rt        | j                        }d	|t        |       t        | d
d      t        | dd      t        | di       xs i t        | dd      t        | dd      t        | dd      d	S )zFMap a BillingError into the result.error envelope the TUI branches on.r   )BillingRemoteSpendingRevokedBillingScopeRequiredBillingSessionRevokedBillingTransientr   remote_spending_revokedsession_revokedinsufficient_scopeNrate_limitedF
portal_urlretry_afterr  actorr  recovery)	r   r   rK  r  r  r  r  r  r  )	hermes_cli.nous_billingr  r  r  r  r  r   r6   r   )r!  r  r  r  r  rr  s         rD   _serialize_billing_errorr    s      D#34(	C.	/ 	C-	.#	C)	*!(gt!<s399~.	gt	$399~s8c<6sM483	2.4" gt,VT*CT2 r   c                    ddl m} d }d}| j                  l| j                  j                  | j                  j                  | j                  j
                  | j                  j                  | j                  j                  d}d}| j                  ^| j                  } ||j                         ||j                         ||j                         ||j                        |j                  d}d}| j                  | j                  }d}|j                  u|j                  j                  dk(  rDd|j                  j                  |j                  j                  |j                  j                  d}nd	|j                  j                  i}|j                   ||j                          ||j                          ||j"                         ||j"                        |d
}i ddd| j$                  d| j&                  d| j(                  d| j*                  d| j,                  d| j.                  d| j0                  d || j2                        d || j2                        d| j4                  d| j6                  D 	cg c]
  }	 ||	       c}	d| j6                  D 	cg c]
  }	 ||	       c}	d || j8                        d || j:                        d|d||| j<                  | j>                  tA        |       dS c c}	w c c}	w )uI   Serialize a BillingState for the wire (Decimals → strings, money-safe).r   format_moneyc                      | d S t        |       S r   r6   r  s    rD   r  z$_serialize_billing_state.<locals>._s      }t4#e*4r   N)brandlast4maskedr   resolved_via)	limit_usdlimit_displayspent_this_month_usdspent_displayis_default_ceilingdistinct)rr  payment_method_idr  r  rr  )r  threshold_usdthreshold_displayreload_to_usdreload_to_displaycardr   T	logged_inorg_nameorg_slugr)  is_admincan_change_plan
can_chargebalance_usdbalance_displaycli_billing_enabledcharge_presetscharge_presets_displaymin_usdmax_usdr  monthly_cap)auto_reloadr  r   r  )!agent.billing_viewr  r  r  r  r  r   r  r  r  r  r  r  rr  r  r  r  r  r  r  r  r)  r  r  r  r  r  r  r  r  r  r   _usage_payload)
r  r  r  r  r  mcr  arcard_outr  s
             rD   _serialize_billing_stater	    s   /5 DzzZZ%%ZZ%%jj'' zz))!JJ33
 K$BLL))",,7$&r'>'>$?)"*A*AB"$"7"7
 K$77ww||z)&)+)B)BWW]]WW]]	 #BGGLL1zz 0 01!-b.>.>!? 0 01!-b.>.>!?
dU__ 	ENN 	ENN	
 	

 	ENN 	500 	e&& 	r%++, 	<(9(9: 	u88 	%*>*>?Q2a5? 	!E<P<P"Qq<?"Q 	2emm$ 	2emm$  	!" 	{#$ #&&
  &3  @"Qs   L"L
c                 x    t        | dd      sddiS 	 ddlm} t         |             S # t        $ r ddicY S w xY w)zBest-effort shared usage model for the /topup + /subscription overlay bars.

    Only fetched when logged in; fail-open to {available:false} so the overview
    still renders if the account-info path is down.
    r  Fr  r   build_usage_model)r   agent.billing_usager	  _serialize_usage_modelr5   )r  r	  s     rD   r  r  K   sL     5+u-U##$9%&7&9:: $U##$s   ) 99ru   c                     	 ddl m}  |       }t        | t        |            S # t        $ r t        | dddd      cY S w xY w)u   GET /api/billing/state → serialized BillingState (Screen 1 + 5).

    Fail-open like the other billing RPCs: a logged-out / unreachable portal yields
    {ok:true, logged_in:false}. No scope required for this endpoint.
    r   )build_billing_stateTFzcould not load billing stater   r  r   )r  r
	  ra  r	  r5   )r   r  r
	  r  s       rD   r  r  [   sL    c:#%30788 c3t%B`abbc   !$ A A c                     | yddl m} | j                   || j                         || j                         || j
                        | j                  | j                  dS )uI   Serialize a UsageBar (dollar magnitudes → display strings + fractions).Nr   )_fmt_usd)rr  remaining_displaytotal_displayr  pct_usedfill_fraction)r	  r	  rr  remaining_usd	total_usd	spent_usdr	  r	  )barr	  s     rD   _serialize_usage_barr	  k   sV    
{, %c&7&78!#--0!#--0LL** r   c                    ddl m}m} | t        | dd      sdddS dd| j                  | j
                  | j                  t        | dd      xs  || j                        | j                  dn || j                        | j                  dn || j                        | j                  dn || j                        | j                  t        | j                        t        | j                        d	S )
u   Serialize a UsageModel for the wire — the shared two-bar dollar view.

    Dollars-only (no 'credits'); fail-open shape mirrors the other billing RPCs
    ({ok, available:false} when logged out / unreachable).
    r   )r	  format_renewsNr  FTr   r  renews_display)r   r  rN  	plan_name	renews_atr	  subscription_remaining_displaytopup_remaining_displaytotal_spendable_display	has_topupplan_bar	topup_bar)r	  r	  r	  r   rN  r	  r	  subscription_remaining_usdtopup_remaining_usdtotal_spendable_usdr!	  r	  r"	  r#	  )r   r	  r	  s      rD   r	  r	  {   s     <}GE;>// ,,____!%)94@bMRWRaRaDb44<D(5KkKkBl --5D8ED]D];^ --5D8ED]D];^__(8)%//:% r   rn   c                     	 ddl m} t        | t         |                   S # t        $ r t        | ddd      cY S w xY w)u   Shared dollar usage model (two-bar view) for /usage + /subscription.

    Fail-open: logged-out / unreachable portal → {ok:true, available:false}.
    No scope required (read-only).
    r   r	  TFr	  )r	  r	  ra  r	  r5   )r   r  r	  s      rD   r  r     sB    :93./@/BCDD :3t%899:s   " ==c                 R   ddl m} ddlm} d }d}| j                  | j                  }|j
                  |j                   ||j                         ||j                        |j                  |j                  |j                   ||j                        |j                  |j                   ||j                        d}| j                  D cg c]^  }|j
                  |j                  |j                    ||j"                         ||j                        |j$                  |j&                  d` }}d| j(                  | j*                  | j,                  | j.                  | j0                  | j2                  | j4                  ||| j6                  | j8                  t;        |       d	S c c}w )
uB   Serialize a SubscriptionState for the wire (Decimals → strings).r   )r	  r  c                      | d S t        |       S r   r  r  s    rD   r  z)_serialize_subscription_state.<locals>._s   r  r   N)tier_id	tier_namemonthly_creditscredits_remainingcycle_ends_atpending_downgrade_tier_namepending_downgrade_atpending_downgrade_displaycancel_at_period_endcancellation_effective_atcancellation_effective_display)r*	  rI   
tier_orderdollars_per_month_displayr,	  
is_current
is_enabledT)r   r  r  r  r  org_idr)  rk  r  tiersr  r   r  )r	  r	  r  r  r  r*	  r+	  r,	  r-	  r.	  r/	  r0	  r2	  r3	  r:	  rI   r5	  dollars_per_monthr7	  r8	  r  r  r  r  r9	  r)  rk  r  r   r  )r  r	  r  r  r  r  r  r:	  s           rD   _serialize_subscription_stater<	     sl   1/5 G}} MMyy!!"3"34!#A$7$7!8__+,+H+H$%$:$:)6q7M7M)N$%$:$:)*)D)D.;A<W<W.X
2   yyFF,,)5a6I6I)J!!"3"34,,,,	
E  __NN 00NN,,

==&&  &% s   A#F$r   c                     	 ddl m}  |       }t        | t        |            S # t        $ r t        | dddd      cY S w xY w)u   GET /api/billing/subscription → serialized SubscriptionState.

    Fail-open like billing.state: logged-out / unreachable portal →
    {ok:true, logged_in:false}. No scope required (read-only).
    r   )build_subscription_stateTFz!could not load subscription stater	  )agent.subscription_viewr>	  ra  r<	  r5   )r   r  r>	  r  s       rD   r  r     sL    hD(*35e<== h3t%Befgghr	  c                     d| j                   | j                  | j                  | j                  | j                  | j
                  | j                  dnt        | j                        | j                  | j                  d
S )uH   Serialize a SubscriptionChangePreview for the wire (Decimal → string).TN)
r   effectr\  current_tier_idcurrent_tier_nametarget_tier_idtarget_tier_namemonthly_credits_deltaamount_due_now_centseffective_at)
rA	  r\  rB	  rC	  rD	  rE	  rF	  r6   rG	  rH	  )r  s    rD   _serialize_subscription_previewrI	     sn     ((((,,00**..++3DQ=T=T9U ! 6 6 r   r   c           	      P   ddl m} ddlm}m} |j                  d      }|st        | dddd      S 	  | ||	            }t        | t        |            S # |$ r}t        | t        |            cY d
}~S d
}~wt        $ r#}t        | ddt        |      d      cY d
}~S d
}~ww xY w)u(  POST /api/billing/subscription/preview → serialized quote or typed error.

    params: {subscription_type_id: str}. Chargeless effect quote. Requires
    billing:manage (live Stripe calls + amounts), so a 403 → insufficient_scope
    drives the device step-up exactly like the mutations.
    r   )(subscription_change_preview_from_payload)BillingErrorpost_subscription_previewsubscription_type_idFinvalid_request subscription_type_id is requiredr   r   rK  )rN	  Nr   )r?	  rK	  r  rL	  rM	  r   ra  rI	  r  r5   r6   )r   r  rK	  rL	  rM	  r*	  r|  r!  s           rD   r  r  	!  s     QOjj/0G3u/@MopqqN:%7C
 37@AA 730566 N3uw3s8LMMNs/   #A B%A60B%6B%B B% B%r   c           	         ddl m}m} t        |j	                  d            }|j	                  d      }|s|st        | dddd      S 	  |||	      }t        | d
|j	                  d      |d      S # |$ r}t        | t        |            cY d}~S d}~wt        $ r#}t        | ddt        |      d      cY d}~S d}~ww xY w)u  PUT /api/billing/subscription/pending-change → {ok, message} or typed error.

    params: {subscription_type_id?: str, cancel?: bool}. Schedules a downgrade /
    same-price change OR a cancellation at period end (chargeless). Requires
    billing:manage.
    r   )rL	  put_subscription_pending_changecancelrN	  FrO	  z*subscription_type_id or cancel is requiredrQ	  )rN	  rT	  TrK  r   rK  r  Nr   )	r  rL	  rS	  r   r   ra  r  r5   r6   )r   r  rL	  rS	  rT	  r*	  r  r!  s           rD   r  r  "!  s     V&**X&'Fjj/0G'3u/@Myz{{N0gV\]3t

90ERXYZZ 730566 N3uw3s8LMMNs0   	(A2 2C 7BC C B;5C ;C r   c           	         ddl m}m} 	  |       }t        | d|j	                  d      |d      S # |$ r}t        | t        |            cY d}~S d}~wt        $ r#}t        | ddt        |      d	      cY d}~S d}~ww xY w)
u  DELETE /api/billing/subscription/pending-change → {ok, message} or typed error.

    Clears a scheduled downgrade or cancellation (resume / undo). Chargeless, but it
    re-enables recurring spend → requires billing:manage and honors the kill-switch.
    r   )rL	  "delete_subscription_pending_changeTrK  rU	  NFr   rQ	  )r  rL	  rW	  ra  r   r  r5   r6   )r   r  rL	  rW	  r  r!  s         rD   r  r  9!  sz     YN353t

90ERXYZZ 730566 N3uw3s8LMMNs,   %0 A>A	A>A>A93A>9A>r   c           
         ddl m} ddlm}m} |j                  d      }|st        | dddd      S |j                  d	      xs  |       }	  |||
      }t        | d|j                  d      |j                  d      |j                  d      |j                  d      |d      S # |$ r&}t        |      }	||	d	<   t        | |	      cY d}~S d}~wt        $ r$}t        | ddt        |      |d      cY d}~S d}~ww xY w)u  POST /api/billing/subscription/upgrade → {ok, status, ...} or typed error.

    params: {subscription_type_id: str, idempotency_key?: str}. The single money
    route: prorate + charge the card on the subscription + flip the plan. SCA /
    decline come back as status requires_action / payment_failed with a recovery_url
    to finish in the portal. The idempotency key is minted if absent and echoed so
    the TUI reuses it on retry of the SAME upgrade. Requires billing:manage.
    r   new_idempotency_key)rL	  post_subscription_upgraderN	  FrO	  rP	  rQ	  idempotency_key)rN	  r\	  TrN  targetTierNamerecoveryUrlr\  )r   rN  rE	  recovery_urlr\  r\	  Nr   r   r   rK  r\	  )
r  rZ	  r  rL	  r[	  r   ra  r  r5   r6   )
r   r  rZ	  rL	  r[	  r*	  rw  r  r!  r   s
             rD   r  r  K!  s    7Ojj/0G3u/@Mopqq
**&
'
@+>+@Cf*Y\] **X.$*JJ/?$@ &

= 9 **X.#&

 
	
  &s+!$3} f3uw3s8`cdeefs1   AB& &C<+CC<C<C71C<7C<zbilling.chargec           	         ddl m}m} ddlm} |j                  d      }|t        | dddd	      S |j                  d
      xs  |       }	  |||      }t        | d|j                  d      |d      S # |$ r&}t        |      }	||	d
<   t        | |	      cY d}~S d}~wt        $ r$}t        | ddt        |      |d      cY d}~S d}~ww xY w)u  POST /api/billing/charge → {ok, chargeId} or a typed error envelope.

    params: {amount_usd: str|number, idempotency_key?: str}. If no key is
    supplied, the server-side core mints a fresh one and returns it so the TUI can
    reuse it on retry of the SAME purchase.
    r   )rL	  post_chargerY	  
amount_usdNFrO	  zamount_usd is requiredrQ	  r\	  )rc	  r\	  TchargeId)r   	charge_idr\	  r   r`	  )
r  rL	  rb	  r  rZ	  r   ra  r  r5   r6   )
r   r  rL	  rb	  rZ	  amountrw  r  r!  r   s
             rD   r  r  r!  s     B6ZZ%F~3u/@Mefgg
**&
'
@+>+@CfD3t&**Z2H]`abb &s+!$3} f3uw3s8`cdeefs0   (A6 6C;BCC(CCCzbilling.charge_statusc           
         ddl m}m} |j                  d      }|st	        | dddd      S 	  ||      }t	        | d|j                  d	      |j                  d
      |j                  d      |j                  d      d      S # |$ r}t	        | t        |            cY d}~S d}~wt        $ r#}t	        | ddt        |      d      cY d}~S d}~ww xY w)u   GET /api/billing/charge/{id} → {ok, status, ...} or typed error.

    The poll. Caller drives the 2s/5-min cadence; this is a single status read.
    r   )rL	  get_charge_statusre	  Finvalid_charge_idzcharge_id is requiredrQ	  TrN  	amountUsd	settledAtr\  )r   rN  rc	  
settled_atr\  Nr   )r  rL	  rh	  r   ra  r  r5   r6   )r   r  rL	  rh	  re	  r  r!  s          rD   r  r  !  s     H

;'I3u/BOfghhN"9- **X.$jj5$jj5 **X.	
 		
  730566 N3uw3s8LMMNs0   AB CB"C"C.CCCzbilling.auto_reloadc           	         ddl m}m} 	 t        |j	                  d            }|j	                  d      }|j	                  d      }||t        | ddd	d
      S  ||||       t        | ddi      S # |$ r}t        | t        |            cY d}~S d}~wt        $ r#}t        | ddt        |      d
      cY d}~S d}~ww xY w)u   PATCH /api/billing/auto-top-up → {ok:true} or typed error (Screen 2).

    params: {enabled: bool, threshold: number, top_up_amount: number}.
    r   )rL	  patch_auto_top_upr  	thresholdtop_up_amountNFrO	  z(threshold and top_up_amount are requiredrQ	  )r  ro	  rp	  r   Tr   )	r  rL	  rn	  r   r   ra  r  r5   r6   )r   r  rL	  rn	  r  ro	  rp	  r!  s           rD   r  r  !  s     HNvzz),-JJ{+	

?3 5s53DQ{|}}'Ym\3t%% 730566 N3uw3s8LMMNs6   AA3 A3 3C8BCCB<6C<Cr   c           	      f   |j                  d      xs d	 ddlm} ddlm} dt
        dt
        dd	ffd
} |d|      }t        | dt        |      d      S # $ r&}t        |      }d|d<   t        | |      cY d	}~S d	}~wt        $ r$}t        | ddt        |      dd      cY d	}~S d	}~ww xY w)u  Run the lazy billing:manage step-up device flow → {ok, granted}.

    Triggered by the TUI after a billing call returns error=insufficient_scope.
    Returns granted:false when the server silently downscopes (non-admin / unticked).

    Runs on the thread pool (in _LONG_HANDLERS): the device flow blocks for the
    whole device-code lifetime (minutes), so it must not stall the main stdin loop.
    The verification URL/code reach the TUI via an out-of-band ``billing.step_up.
    verification`` event (a plain print would be dropped by the JSON-RPC stdout
    pipe), and the browser is opened TUI-side via openExternalUrl — never with the
    gateway's headless webbrowser.open (hence open_browser=False).
    r  r   r   )step_up_nous_billing_scope)rL	  r  r  r   Nc                 &    t        d| |d       y )Nzbilling.step_up.verification)verification_url	user_coder  )r  r  r-  s     rD   _on_verificationz_.<locals>._on_verification!  s    .%(t<r   F)open_browseron_verificationT)r   grantedry	  r   )r   r   rK  ry	  )
r   rr  rr	  r  rL	  r6   ra  r   r  r5   )	r   r  rr	  rL	  rv	  ry	  r!  r   r-  s	           @rD   r  r  !  s     **\
"
(bC`>8	# 	S 	T 	 -0@
 3tW>??  's+I3} `3uw3s8X]^__`s0   AA B0B :B0 B0B+%B0+B0session.statusc                    t        ||       \  }}|r|S ddlm} |j                  d      xs |j                  d      xs d}|j                  d      }i }t	               }|r|r	 |j                  |      xs i }d&dt        d z  dt        fd	}	 |	|j                  d
            }
|
}dD ]-  }|j                  |      s |	|j                  |      |
      } n t        |      }t        |      }t        |dd       xs |j                  d      xs d}t        |dd       xs |j                  d      xs d}t        t        |            }ddd| d |        g}|r|j                  d|d           |j                  d      xs dj                         }|r|j                  d|        |j                  d| d| dd|
j!                  d       d|j!                  d       dt#        |j                  d      xs d      dd |j                  d!      rd"nd# g       t%        | d$d%j'                  |      i      S # t        $ r i }Y w xY w)'Nr   display_hermes_homer   r  r   rN  rp  r   c                     | r	 t        j                  t        |             S |xs t        j                         S # t        $ r Y #w xY wr   )r   fromtimestampr  r5   r  )rE  rp  s     rD   _dtz_.<locals>._dt!  sF    --eEl;; )8<<>)  s   : 	AAry  )r  last_updated_atlast_activity_atr  rT  r   	(unknown)zHermes TUI StatuszSession ID: zPath: z	Project: rI   r  zTitle: Model:  ()z	Created: z%Y-%m-%d %H:%MzLast Activity: zTokens: r  r
  zAgent Running: r  YesNor   r   r   )r  r=  r}	  r   ra  rb  r5   r   r>  r  r   r  r  r  r7   r#  r4   r  ra  r*   )r   r  r#  r  r}	  rw  rN  r  rk  r	  createdupdatedr  r?  r  r  r   r  linesr  s                       rD   r  r  !  sq   ,LGS

4
++m
$
F

<(@
FBCKK ED	B	c	>>#&,"D*X_ * * $((<()GGF 88E?$((5/73G
 g&F#G,Euj$/V6::j3IVYHE7D)OVZZ-@OKE#$8$ABG

se
$&'(	E y 123XXg$"++-Ewug&'	LLeWBxj*(()9:;<g../?@ABs599W-23A67w{{9'=e4HI	
 sXtyy/011W  	D	s   $I IIzsession.historyc                 &   t        ||       \  }}|r|S t        |j                  dg             }t               }|(|j                  d      r	 |j	                  |d   d      }t        | t        |      t        |      d      S # t
        $ r Y ,w xY w)NrP  r   Tinclude_ancestors)r.  rn  )	r  r_  r   ra  rM  r5   ra  r  r  )r   r  r#  r  rP  rk  s         rD   r  r  %"  s    ,LGS

7;;y"-.G	B	~'++m4	55&$ 6 G
 \,W5	
   		s   B 	BBzsession.undoc                 
   t        ||       \  }}|r|S |j                  d      rt        | dd      S d}|d   5  |j                  dg       }|rD|d   j                  d      d	v r.|j                          |d
z  }|r|d   j                  d      d	v r.|r,|d   j                  d      dk(  r|j                          |d
z  }|r!t	        |j                  dd            d
z   |d<   d d d        t        | d|i      S # 1 sw Y   xY w)Nr  r[  9   session busy — /interrupt the current turn before /undor   rO  rP  r  r)  >   r  r?  r   r*  r1  rA  )r  r   r  r(  r  ra  )r   r  r#  r  rA  rP  s         rD   r  r  <"  s   %LGS

 {{9R
 	
 G		  	T++i,'"+//&15JJKKMqLG '"+//&15JJ wr{v.&8KKMqLG),W[[9JA-N)ORS)SG%&	T sY())	T 	Ts   AC9AC99Dr   c                    t        ||       \  }}|r|S t        |      rt        |j                  d      xs d      }t        |j                  dd      xs d      j	                         }d|rd| ndz   }	 t        |d|d      }|j                  d      dv r)t        | dt        |j                  d      xs d            S t        ||       t        | dd|d      S t        ||       \  }}|r|S |j                  d      rt        | dd      S |j                  dd      }t        |j                  dd      xs d      j	                         }	 ddlm}	 ddlm}
 |d   5  t        |j                  dg             }t!        |j                  dd            }d d d        t#              }|d   }t%        |dd      xs d}t%        |dd       xs d }|r |
|||      nd}|dk\  r"|rd| d nd}t'        |d!d"| d#|d$d%| d&       	 t)        ||||'      \  }}|d   5  t        |j                  dg             }d d d        t#              }t%        |dd      xs |}t%        |dd       xs |}|r |
|||      nd}|d   }t+        ||        |	||||t%        |d(d       )      }t-        ||      }t/        d*||       t        | |d+   rd+nd|||||||||d,
      t'        |d-       S # t        $ r}t        | d	d
|       cY d }~S d }~ww xY w# 1 sw Y   }xY w# 1 sw Y   xY w# t'        |d-       w xY w# t        $ r }t        | d.t        |            cY d }~S d }~ww xY w)/Nr  r   r  z	/compressr  r   Trc  r   r   r]  zcompute-host compress failed: r  >   r   control.errorr[  rK  zcompute-host compress failedr  rN  r  host_ackr  =   session busy — /interrupt the current turn before /compressr   summarize_manual_compressionr  rO  rP  r1  rN  r  r`   r  r  z
, focus: ""compressingu   ⠋ compressing z messages (~r
  z tok)   …r  r  r1  r  compression_staterP  aborted)
rN  rA  r  after_messagesbefore_tokensafter_tokensrp  r  rH  rn  r  i  )r  r"  r6   r   r7   rg  r5   r  rI  ra  r  !agent.manual_compression_feedbackr	  r  r  r_  r  r  r   r|  r  r  rR  r  )r   r  r#  r  r-  r  r   ackr!  r	  r  r  r1  before_count_agentr  r  r	  focus_suffixrA  r  rn  after_count_sys_prompt_after_tools_afterr	  rN  rp  rH  r  s                                 rD   r  r  X"  s   ,LGS

!'*&**\*0b1&**]B7=2>DDFk1[M!2rJ	K,-	C 776?88T3swwy'9'[=[#\]]+GS93<4UXYZZ%LGS

{{9V
 	
 **\2
&Cfjj39r:@@BKV'RF^$ 	E"7;;y"#=>O!'++.?"CDO	E ?+!f&=rBHb$/74
  *{&  	 1:EZ}A62L"<. 1"1%U<.=8	)6+ / /NGU ( <Ir :;<h-K  7<K  #67D9CVL  ."3&   G$E,S':2")%1Et"LG !0D.#t,+29+=i<&'3&1%2$0&"  (& 3(G  	KT%CC5#IJJ	K&	E 	E@< <` 3( 'Cs1v&&'s   7K, L<  7LA0L< L+  L<B#L+ L< ,	L5L
L
LLL< L($L+ +L99L< <	M%M M% M%zsession.savec                    t        ||       \  }}|r|S |d   }t               dz  dz  }	 |j                  dd       t        j                         j                  d	      }|d
| dz  }|d   5  t        |j                  dg             }	d d d        t        |dd       xs |j                  d      xs d}
t        |dd       }t        |t
              r|j                         }nL|j                  d      }t        |t        t        f      r#t        j                  |      j                         nd}	 t!        |dd      5 }t#        j$                  t        |dd      |
|t        |dd      xs d	d|dd       d d d        t'        | dt)        |      i      S # t        $ r}t	        | dd| d|       cY d }~S d }~ww xY w# 1 sw Y   9xY w# 1 sw Y   VxY w# t        $ r }t	        | dt)        |            cY d }~S d }~ww xY w)NrN  r   savedTrW  i  z failed to create save directory r%   r  hermes_conversation_.jsonrO  rP  r  r   r   session_startr  wr    r!   r   r  )r   r  r	  r  rn  r   F)rC  rD  r'   )r  r
   rZ  r5   r  r   r  r4   r_  r   r   r  	isoformatr  r  r	  r1   r   dumpra  r6   )r   r  r#  r  rN  	saved_dirr  	timestampr.   rn  r  agent_startr	  r  rB   s                  rD   r  r  "  s   %LGS

GE  !J.8ITt4 ''8I-i[>>D		  4Ir234 d3Ww{{=7QWUWJ %$7K+x(#--/[[.
 *sEl3 "":.88: 	'$g. 	!II$UGR8",%2%,U4KR%P%VTV ( "	 3T+,,K  TC!A)BqcRSST4 4$	 	  'Cs1v&&'s_   F .G1G ?:G9G 	F>!F93F>9F>GGG 	H#G>8H>Hzsession.closec                     |j                  dd      }t        5  t        |      }d d d        t        d      }t	        | d|i      S # 1 sw Y   $xY w)Nr  r   rI  rr  closed)r   r  r|  r~  ra  )r   r  r-  r#  r	  s        rD   r  r  #  sT    
**\2
&C 
 *$S)*%g+FFsXv&''* *s   AAr~   c           
      2   t        ||       \  }}|r|S t               }|t        | d      S |d   }|d   5  |j                  dg       D cg c]  }t	        |       }}d d d        st        | dd      S t               }t        j                         j                  d d }	t        |      }
t        ||	|
	      \  }}|t        | d
|      S |j                  dd      }	 |r|}n7|j                  |      xs d}t        |d      r|j                  |      n| d}|j                  ||
t!               d|i|t#        |             |D ]5  }|j%                  ||j                  dd      |j                  d             7 |j'                  ||       	 t-        |      }	 t/        |	|||
      }t1        |       t3        |	||t5        |      |j                  dd      |
       |	t6        v r|t6        |	   d<   t9        | |	||d      S c c}w # 1 sw Y   xY w# t(        $ r,}||j+                          t        | dd|       cY d }~S d }~ww xY w# t1        |       w xY w# t(        $ r,}||j+                          t        | dd|       cY d }~S d }~ww xY w)N  r  r   rO  rP  i  u*   nothing to branch — send a message firstr   r1  r  rI   r   r6  get_next_title_in_lineagez	 (branch)r  r  r)  r*  r+  r,  zbranch failed: rU  r3  r4  )r3  rB  r%  r=  zagent init failed on branch: )r  r  r  )r  ra  r  r   r   r  r  rt  ru  rv  r2  r"  rl  r`  r	  r   r  r;  r-  r  r5   r)  r  r  r  r  r_  rQ   ra  )r   r  r#  r  rk  r  r   rP  new_keynew_sidrB  r+  r4  branch_namer  r  r  r  rN  s                      rD   r  r  #  s   %LGS

	B	z$St44m$G		  D(/Ir(BC49CCDCKLL Gjjlr"GW%F5&E=  C}--**VR(K!6E**73?xG 2:; ,,W5y	* 
 	 " +G4%W% 	 	
  	C"WWVV,	*  	 	We,
D%g.	+""(	E #6*MVR(	
 i9>Ig56
 s7UgNOOO DD DV  6MMOC4556 #6*  DMMOC!>qcBCCDss   HHH B2H I! I .A	I! HH	I"!I	I	III! !	J*!JJJzsession.interruptc                 :   t        ||       \  }}|r|S t        |      rt        |j                  d      xs d      }|j                  d      r	 t	               j                  |d|         |d   5  d	|d
<   d |d<   d d d        t        |       	 ddl	m
}  ||d   dd	       t        | dd	d      S t        ||       \  }}|r|S |j                  d      }|d uxr |j                         }t        |j                  d            }	|	r"t        |d   d      r|d   j                          |d   5  d	|d
<   d |d<   d d d        |s/|d   5  |j                  d      rd|d<   t!        |       d d d        t        |j                  dd             	 ddl	m
}  ||d   dd	       t        | ddi      S # t        $ r}t        | dd|       cY d }~S d }~ww xY w# 1 sw Y   ^xY w# t        $ r Y Mw xY w# 1 sw Y   xY w# 1 sw Y   xY w# t        $ r Y tw xY w)Nr  r   r  z
interrupt-r8  r]  zcompute-host interrupt failed: rO  T_turn_cancel_requestedr  r   resolve_gateway_approvalr   rl  resolve_allrV  r_  _run_threadrN  r  FrN  )r  r"  r6   r   r/  r  r5   r  r  rv  r	  ra  r  is_aliver   r`  rQ  )
r   r  r#  r  r-  r!  r	  
run_threadrun_thread_aliveshould_interrupts
             rD   r  r  g#  sT   ,LGS

!'*&**\*0b1;;y!P,.88:VYUZI[8\ ^$ 	,04G,-'+GO$	, 	s	?$W]%;VQUV 3=DIJJ%LGS

 ]+J!-G*2E2E2GGKK	23GGG$4kB""$		  (,0()#' ( ^$ 	.{{9%%*	"$W-	. 6::lB/0; !7TR sX}-..i  PC)H'NOOP	, 	,  		$( (	. 	.$  sf   F3 2GG& 1G6"HH 3	G<GGGG#&	G32G36G?H	HHzdelegation.statusc                 d    ddl m}m}m}m} t        |  |        |        |        |       d      S )Nr   )is_spawn_pausedlist_active_subagents_get_max_concurrent_children_get_max_spawn_depth)r  pausedmax_spawn_depthmax_concurrent_children)tools.delegate_toolr	  r	  r	  r	  ra  )r   r  r	  r	  r	  r	  s         rD   r  r  #  s;      +-%'35'C'E		
 r   zdelegation.pausec                 l    ddl m} t        |j                  dd            }t	        | d ||      i      S )Nr   )set_spawn_pausedr	  T)r	  r	  r   r   ra  )r   r  r	  r	  s       rD   r  r  #  s2    4&**Xt,-FsX/7899r   zsubagent.interruptc                     ddl m} t        |j                  d      xs d      j	                         }|st        | dd      S  ||      }t        | ||d      S )Nr   )interrupt_subagentr  r     zsubagent_id required)rP  r  )r	  r	  r6   r   r7   r  ra  )r   r  r	  r  r   s        rD   r  r  #  sU    6fjj/526<<>KC566	K	(Bsb=>>r   c                  L    ddl m}   |        dz  }|j                  dd       |S )Nr   rU  zspawn-treesTrW  rY  r[  s     rD   _spawn_trees_rootr	  #  s'    0},DJJtdJ+Kr   c                 ~    dj                  d | D              xs d}t               |z  }|j                  dd       |S )Nr   c              3   L   K   | ]  }|j                         s|d v r|nd  yw)z-_r  N)isalnum)r  r  s     rD   r  z*_spawn_tree_session_dir.<locals>.<genexpr>#  s#     K1QYY[AI36Ks   "$rT  TrW  )r*   r	  rZ  )r  safer  s      rD   _spawn_tree_session_dirr	  #  sB    
K
KKXy 	 	d"AGGD4G(Hr   z_index.jsonlr  c                    	 | t         z  j                  dd      5 }|j                  t        j                  |d      dz          d d d        y # 1 sw Y   y xY w# t
        $ r }t        j                  d|       Y d }~y d }~ww xY w)Nr   r    r!   FrD  r   z"spawn_tree index append failed: %s)_SPAWN_TREE_INDEXr1   r2   r   r   OSErrorr  r*  )session_dirr  rB   r!  s       rD   _append_spawn_tree_indexr	  #  s}    @--33C'3J 	BaGGDJJu59D@A	B 	B 	B @ 	93??@s4   A *AA AA A 	B$A??Bc                 h   | t         z  }|j                         sg S g }	 |j                  dd      5 }|D ]:  }|j                         }|s	 |j	                  t        j                  |             < 	 d d d        |S # t
        j                  $ r Y ]w xY w# 1 sw Y   |S xY w# t        $ r g cY S w xY w)Nr  r    r!   )	r	  r  r1   r7   r  r   r   r   r	  )r	  
index_pathr  rB   r   s        rD   _read_spawn_tree_indexr	  #  s    00J	C__S7_3 	q zz|JJtzz$/0	 J	 ++ 	 J  	sR   B# B$A=0B3B# =BBBBB B#  B# #B10B1zspawn_tree.savec                 `   t        |j                  d      xs d      j                         }|j                  d      xs g }t        |t              r|st        | dd      S ddlm} |j                  d      }|j                  d	      xs t        j                         }t        |j                  d
      xs d      } |j                  t        |            j                  d      }| d}	t        |xs d      }
|
|	z  }	 ||rt        |      nd t        |      ||d}|j                  t        j                  |d      d       t!        |
t        |      ||d   |d	   |t#        |      d       t%        | t        |      |d      S # t        $ r}t        | dd|       cY d }~S d }~ww xY w)Nr  r   ra   r	  zsubagents list requiredr   r   ry  finished_atr9  z%Y%m%dT%H%M%Sr	  rF  )r  ry  r	  r9  ra   Fr	  r    r!   r=  zspawn_tree.save failed: )r.   r  ry  r	  r9  r.  )r.   r  )r6   r   r7   r  r_  r  r   r3   utcfromtimestampr  r4   r	  
write_textr   r   r	  r	  r  ra  )r   r  r  ra   r   ry  r	  r9  r  fnamer  r.   r  r!  s                 rD   r  r  $  s   VZZ-34::<J

;'-2Ii&iC899!L)J**]+:tyy{K

7#)r*E	"	"	"5#5	6	?	?	PBd%LE
 7i8Au9D
A$/9%
+t -"
 	

7?'R 	I$!,/"=1^	

 sSYjABB  AC!9#?@@As   AF
 
	F-F("F-(F-zspawn_tree.listc                 z   t        |j                  d      xs d      j                         }t        |j                  d      xs d      }t	        |j                  d            }|r9t               }|j                         D cg c]  }|j                         s| }}nt        |xs d      g}g }|D ]9  }	t        |	      }
|
r|j                  fd|
D               ,|	j                  d      D ]  j                  t        k(  r	 j                         }	 t        j                   j#                  d	
            }|j                  d      xs g }|j'                  t              |j                  d      xs |	j                  |j                  d      xs |j(                  |j                  d      |j                  d      xs dt+        |t,              rt/        |      ndd        < |j3                  d d       t5        | d|d | i      S c c}w # t$        $ r i }Y w xY w# t0        $ r Y Gw xY w)Nr  r   r  2   cross_sessionrF  c              3   ~   K   | ]4  }|j                  d       xst              j                         s1| 6 yw)r.   N)r   r   r  )r  r  r  s     rD   r  z_.<locals>.<genexpr>O$  s5      AEE&M'9q'9tAw~~?Os   ===z*.jsonr    r!   ra   r	  ry  r9  r   )r.   r  r	  ry  r9  r.  c                 ,    | j                  d      xs dS )Nr	  r   r  )r  s    rD   r   z_.<locals>.<lambda>m$  s    quu]38q r   Trw  reverseentries)r6   r   r7   r  r   r	  ra  rb  r	  r	  r#  globrI   r	  rQ  r   r   	read_textr5   r  rR  r  r_  r  r	  r  ra  )r   r  r  r  r	  r  r  rootsr	  r  indexedrQ  r  ra   s         `       rD   r  r  >$  s   VZZ-34::<J

7#)r*EO45M " LLN9qahhj99()@yABG  (+NN "   ! 	Avv**vvx**Q[['[%BCC  GGK06B	 #A&)ggl&;&Eqvv'*ww}'='N&)ggl&;!$!1!7R3=i3NYTU		 D LL8$LGsY011Q :. ! C  sC   HH
H-%H B-H-H*'H-)H**H--	H:9H:zspawn_tree.loadc                 ,   ddl m} t        |j                  d      xs d      j	                         }|st        | dd      S t               j                         }	  ||      j                         }|j                  |       	 t        j                  |j                  d	
            }t        | |      S # t        t        f$ r}t        | dd|       cY d }~S d }~ww xY w# t        t        j                  f$ r}t        | dd|       cY d }~S d }~ww xY w)Nr   r   r.   r   r	  path requiredr  zpath outside spawn-trees root: r    r!   r=  zspawn_tree.load failed: )pathlibr   r6   r   r7   r  r	  r  relative_tor>  r	  r   r   r	  r   ra  )r   r  r   raw_pathr  r  r!  r  s           rD   r  r  q$  s   6::f%+,224HC// &&(DH>))+T"A**X///AB sG   HC!@FGGH
 T))* AC!9#?@@As<   'B4 %C  4CCCC D9DDDzsession.steerc                 z   |j                  d      xs dj                         }|st        | dd      S t        ||       \  }}|r|S |j                  d      }|t	        |d      st        | dd	      S 	 |j                  |      }t        | |rdnd|d      S # t        $ r}t        | d
d|       cY d}~S d}~ww xY w)uG  Inject a user message into the next tool result without interrupting.

    Mirrors AIAgent.steer(). Safe to call while a turn is running — the text
    lands on the last tool result of the next tool batch and the model sees
    it on its next iteration. No interrupt, no new user turn, no role
    alternation violation.
    r   r     ztext is requiredrN  Nr   i  zagent does not support steerr=  zsteer failed: r  rejected)rN  r   )r   r7   r  r  r`  r   r5   ra  )r   r  r   r#  r  rN  acceptedr!  s           rD   r  r  $  s     JJv$"++-DC122,LGS

KK E}GE73C=>>7;;t$ s8xTRSS  7Cu5667s   3B 	B: B5/B:5B:zterminal.resizec                     t        ||       \  }}|r|S t        |j                  dd            |d<   t        | d|d   i      S )Nr3  r4  )r  r  r   ra  )r   r  r#  r  s       rD   r  r  $  sI    ,LGS

&**VR01GFOsVWV_-..r   zprompt.submitc                     ddl m} |j                  dd      |j                  dd      }t        |t              r ||      n||j                  d      }t        |       \  }|r|S t               }t        |      }t               x}|d<   	 d }	d	   5  j                  d
      r|xs j                  d      }	n
	 d d d        n	 d d d        t         |	      }
|
|
S Vd	   5  j                  d      r=t        t	        j                  d      xs d            rt         dd      cd d d        S |	 t        |      }j                  dg       }t        |      D cg c]  \  }}|j                  d      dk(  s| }}}|dk  s|t!        |      k\  rt         dd      cd d d        S |d ||    }|d<   t        j                  dd            dz   d<   t#               x}	 |j%                  d   |       dd
<   dd<   t/        j.                         d<   t1               d d d        |rKt3               }|j                  d      s|S t4        j7                  d|d   j                  dd              t9               t;               t=               d& fd!}t?        j@                  |d"      }|d#<   |jC                          tE         d$d%i      S # 1 sw Y   $xY w# t        t        f$ r t         dd      cY cd d d        S w xY wc c}}w # t&        $ r)}t)        d| t*        j,                         Y d }~Rd }~ww xY w# 1 sw Y   /xY w)'Nr   )sanitize_user_prompt_textr  r   r   truncate_before_user_ordinalr  TrO  r  r  r   r[  u0   subagent still running — wait for it to finishr4  z/truncate_before_user_ordinal must be an integerrP  r)  r*    z3target user message is no longer in session historyr1  r   z6[tui_gateway] prompt.submit: replace_messages failed: r
  Fr	  r  r   zDcompute-host dispatch failed for session %s; falling back inline: %srK  zunknown errorc            	         t              } | rNt        dd| j                  di       j                  dd      i       d   5  dd<   t               d d d        y d   5  j                  d      sj                  d      sdd<   t               	 d d d        y 	 d d d        t	               y # 1 sw Y   y xY w# 1 sw Y   $xY w)Nr   rK  agent initialization failedrO  Fr  r	  )r  r  r   rQ  r  )r  r   r#  r-  r   s    rD   run_after_agent_readyz _.<locals>.run_after_agent_ready%  s    '3'swww377!#@  ( .%*	"$W-. ^$ 	{{34GKK	<R%*	"$W-		 	<R	
 	3Wd3. 	 	s   B8#4C8CCr   r	  rN  r^  r   )#hermes_cli.input_sanitizer
  r   r  r6   r  r  r"  r   r  r  r  r  rS  r>  r  r  ra  replace_messagesr5   r:   r;   r<   r3   r  rb  r  r   r&  r/  r  r   r   r   ra  )r   r  r
  raw_texttruncate_user_ordinalr  r  r  r  busy_transportbusy_responseordinalrP  r"  r  user_indices	truncatedrk  r!  isolated_responser	
  r	  r#  r-  r   s   `                     @@@rD   r  r  $  s   C
**\2
&Czz&"%H2<Xs2K$X.QYD"JJ'EF,LGS

<>M/GN   - 
^$ 	{{9%
 "#!>gkk+&>	 	 	 ,Cgt^T$   $ 
	  !, ;;v#4S]9S9YWY5Z#[T#UV!, !, !,Z34 kk)R0G*3G*<X$!QfQW@WAXLX {g\)::C'\]+!, !,,   7,w"78I!*GI),W[[9JA-N)ORS)SG%&i,k''(>	J "	,1()!%Wd+C!,F :3WdS $$W-$$Rg&**9oF	
 7# !sG$4 4. !!)>tLJ (GMsX{+,,A	 	6 z* ZC'XYY!, !,Z Y ! kRSVRWX_b_i_ijjk9!, !,s   )K10AM$?M$K> M$-L)
L)"M$::M$5L/
-M$1K;>L&M$%L&&	M$/	M!8MM$M!!M$$M.evtc                   	
 t        |j                  d      xs d      }|rZ|t        | xs d      k(  rj                  d      sy	 t        5  |t        v xr t        |   j                  d       }ddd       ryt        |j                  d      xs d      		syt        j                  d      xs d      t        |       h}	
	 t               }||j                  	      xs 	

	k7  r>
|v ry	 t        5  t        
fd	t        j                         D              }ddd       ry	|v ry	 t        5  t        t        j                               }ddd       t        	
fd
D              S # 1 sw Y   xY w# t        $ r d}Y w xY w# t        $ r 	
Y w xY w# 1 sw Y   xY w# t        $ r d}Y w xY w# 1 sw Y   lxY w# t        $ r Y yw xY w)a  True if ``evt`` is owned by a *different* live session.

    Background completions carry the ``session_key`` of the session that started
    the work. Async delegation completions from the desktop also carry
    ``origin_ui_session_id``: the live TUI tab/window that commissioned them.
    Since all desktop sessions share one process-wide completion queue, each
    poller must skip events it doesn't own so a detached result surfaces in the
    launching session, not whichever poller happened to dequeue first.
    r[  r   rL  FNTr   ro  c              3      K   | ]K  }|j                  d        xr3 t        |j                  d      xs d      k(  xs t        |d      k(   M ywrL  r   r   ro  Nr   r6   rq  )r  r  resolved_keys     rD   r  z8_notification_event_belongs_elsewhere.<locals>.<genexpr>[%  sa      (  l++ AEE-06B7<G O.q2>,N(s   AAc              3      K   | ]S  }|uxrI |j                  d        xr5 t        |j                  d      xs d      hv xs t        |d      hv  U ywr
  r
  )r  r  evt_keyr
  r#  s     rD   r  z8_notification_event_belongs_elsewhere.<locals>.<genexpr>s%  sz        	
 	
l##	
 m$*+/FF N"1r2w6MM		
s   AA)r6   r   re  rQ   r5   rq  ra  rK  r  ra  r_  )r-  r#  r
  
evt_ui_sid
owner_livecurrent_keysrk  continuation_liveri  r
  r
  s    `       @@rD   %_notification_event_belongs_elsewherer 
  %%  s	    SWW34:;JSYB'L0I	 e'94dYz=R=V=VWc=d9d
e 
 #''-(.B/G 	GKK&,"-Gc2L LY>77@KGL w<'	& $' ( '--/( %! , 	0I,,./H	0     e e 	J	4     	& %	&	0 	0  s   	F $E93F !F 9F5 ?'F)&F5 7G =GG 9F>F FFF&%F&)F2.F5 5GGGG 	GGc                    |j                  d      ryt        |j                  d      xs d      t        | xs d      k(  ryt        |j                  d      xs d      }|syt        |j                  d      xs d      t        ||       h}||v ry	 t               }||j	                  |      n|xs |}||v S # t
        $ r |}Y ||v S w xY w)u  True iff *this* session PROVABLY owns ``evt``.

    Positive ownership — the mirror of ``_notification_event_belongs_elsewhere``
    minus its orphan-adoption fallback. An event owns-matches when its
    ``origin_ui_session_id`` is this live session, or its ``session_key``
    (raw or resolved through the compression chain) matches this session's
    key/lineage. Used as the fail-closed gate for every addressed notification:
    "not provably elsewhere" is NOT good enough to inject a payload into this
    chat (#55578).
    rL  Fr[  r   Tr   ro  )r   r6   rq  ra  rK  r5   )r-  r#  r
  r
  r
  rk  r
  s          rD    _session_owns_notification_eventr"
  ~%  s     {{< 
377)*0b1S^C#''-(.B/GGKK&,"-Gc2L ,Y57^B((1 	
 <''  <''s   #B; ;CCc                     | j                  d      dk(  xsG t        t        | j                  d      xs d      xs t        | j                  d      xs d            S )z?Whether ``evt`` must be positively claimed before TUI delivery.r  async_delegationr[  r   r   )r   r   r6   )r
  s    rD   "_notification_event_requires_ownerr%
  %  sV    776?00 DCGG*+1r2 	-sww}%+,5 r   c           
         | j                  dd      }| j                  dd      }|dk(  rY||| j                  dd      | j                  dd      | j                  dd      | j                  d	d
      | j                  dd      fS |j                  d      s|dk(  r7||| j                  dd      | j                  dd      | j                  d	d
      fS |dk(  r| j                  dd      |fS ||fS )a  Return the UI-emission identity for a process notification event.

    Completion events are terminal notifications for a background process, so
    they remain one-shot per process session. Watch-match events are not
    terminal: a single background process can legitimately match the same or
    different patterns many times, so include event-specific content to avoid
    suppressing later distinct matches from the same process.
    r  r  r  r   watch_matchr   patternr   
suppressedr   
message_idwatch_overflow_watch_disabledrK  r$
  delegation_id)r   r  )r
  evt_typeevt_sids      rD   _notification_event_dedup_keyr0
  %  s    wwv|,HgglB'G= GGIr"GGIr"GGHb!GGL!$GGL"%
 	
 ,-=M1MGGIr"GGIr"GGL!$
 	
 %% ,h77Xr   rg  c           
         ddl m}m} t               }| j	                         sd|j                  d      sR	 |j                  j                  d      }t        |||      r1|j                  j                  |       t        j                  d       ~t        |      }|rt        |||      s|j                  d      dk(  rt        j                  nt        j                   } |d	|j                  dd
      t#        |j                  d      xs d      t#        |j                  d      xs d      |       "|j                  dd      }	|j                  d      d
k(  r|j%                  |	      r[ ||      }
|
sgt'        |      }||vr!t)        d|d|
d       |j+                  |       d}|d   5  |j                  d      r|j                  j                  |       d}nd|d<   ddd       |rt        j                  d       dt-        t        j                         dz         }ddlm}m}m}  ||d      }|.	 t)        d|       t7        ||||
        |||       | j	                         s|j                  d      sRg }|j                  jC                         s	 |j                  jE                         }t        |||      r|jG                  |       Ut        |      }|rt        |||      s|j                  d      dk(  r|jG                  |       n`t        j!                  d |j                  dd
      t#        |j                  d      xs d      t#        |j                  d      xs d             |j                  dd      }	|j                  d      d
k(  r|j%                  |	      r/ ||      }
|
s;t'        |      }||vr!t)        d|d|
d       |j+                  |       |d   5  |j                  d      r%|j                  j                  |       	 ddd       nd|d<   ddd       dt-        t        j                         dz         }ddlm}m}m}  ||d      }|	 t)        d|       t7        ||||
        |||       |j                  jC                         s|D ]  }|j                  j                  |        y# t        $ r Y w xY w# 1 sw Y   xY w# t        $ rh} |||       t9        dt;        |      j<                   d| t>        j@                         |d   5  d|d<   ddd       n# 1 sw Y   nxY wY d}~d}~ww xY w# t        $ r Y w xY w# 1 sw Y   GxY w# t        $ rh} |||       t9        dt;        |      j<                   d| t>        j@                         |d   5  d|d<   ddd       n# 1 sw Y   nxY wY d}~Xd}~ww xY w)!a  Poll completion_queue and dispatch notifications autonomously.

    Runs in a daemon thread started by _init_session(). Emits a
    status.update (kind=process) for user visibility, then chains an
    agent turn via _run_prompt_submit if the session is idle.

    The completion_queue is process-global. In multi-session Desktop each
    poller requeues events owned by another live session and drops addressed
    events whose owner is gone; ownerless legacy notifications remain global.
    r   )process_registryformat_process_notificationrL  r  r   r  r  r$
  zWDropping unowned %s notification (origin=%r key=%r) instead of delivering to session %sr  r[  r   r   r  rw  processrx  FrO  r  TNg      ?	__notif__r*  claim_event_deliverycomplete_event_deliveryrelease_event_deliveryz
tui-pollerr  z3[tui_gateway] notification poller dispatch failed: r%   r
  zIDropping unowned %s notification during shutdown drain (origin=%r key=%r))$tools.process_registryr2
  r3
  r^  r  r   completion_queuer5   r 
  r   r3   r  r%
  r"
  r  r   r*  r6   is_completion_consumedr0
  r  r%  r  rd  r7
  r8
  r9
  r  r:   r  r9   r;   r<   empty
get_nowaitr  )rg  r-  r#  r2
  r3
  _emittedr
  requires_ownerlog_evt_sidr   
_dedup_key	_requeuedr   r7
  r8
  r9
  _claimr!  deferreds                       rD   _notification_poller_looprG
  %  s    UuH!'++l*C	"33777DC 1gsC--11#6JJsO <C@"B3QT"U 776?&88 \\ 
 .-CGG239r:CGGM*0b1 77<,776?l*/?/V/VW_/`*3/ 337
X%/3D(IJLL$	^$ 	*{{9% 1155c: 	%)	"	*  JJt#diikD0123	
 	
 &c<8>	+/3'sC$7#C0_ !'++l*C| H//557	"33>>@C 1gsCOOC  <C@"B3QT"Uwwv"44$)GGFL1 67=2>.4"5 77<,776?l*/?/V/VW_/`*3/237
X%/3D(IJLL$^$ 	&{{9% 1155c:	& 	& "&GI		& #diikD0123	
 	
 &c<8>	+/3'sC$7#C0i //557@  3))--c23y  		j	* 	*0  	+"3/E9%%&b/ZZ
 ( +%*	"+ + +	+$  		B	& 	&"  	+"3/E9%%&b/ZZ
 ( +%*	"+ + +	+s   S 15S+#S8 &U, :.U;1U;9#V 	S('S(+S58	U)AU$U		U$U	U$$U),	U87U8;V	W9AW4W"	W4"W+	'W44W9c                      ddl m}  t        | dd      du}t        | dd      du}|r|rydt        fdfd}fd	}|s|| _        |s|| _        yy)
a(  Idempotently route background-process output (and tab-close requests) to
    the desktop, keyed by process id. Read-only agent terminal tabs stream
    `agent.terminal.output` chunks live instead of polling the output tail, and
    `process_registry.request_close_terminal` emits `terminal.close` so the agent
    can drop a tab without killing the process. Events are routed to the window
    that owns the process (its gateway session); `_emit`/`write_json` is
    `_stdout_lock`-guarded, so calling it from the registry's reader threads is
    safe.r   r2
  	on_outputNon_closer   c                 
   t        t        | dd      xs d      }|syt        5  t        j	                         D ]3  \  }}t        |j                  d      xs d      |k(  s(|c cd d d        S  	 d d d        y# 1 sw Y   yxY w)Nr   r   )r6   r   re  rQ   rf  r   )r#  r   r-  tui_sessions       rD   _owner_sid_for_processz;_wire_agent_terminal_output.<locals>._owner_sid_for_process&  s    ''="=CD 	$-OO$5  [{}5;<KJ	 		 		 s   <A9!A9.A99Bc                 F    t        d |       | j                  |d       y )Nzagent.terminal.output)
process_idchunk)r  r   )r#  rQ
  rN
  s     rD   _emit_agent_terminal_outputz@_wire_agent_terminal_output.<locals>._emit_agent_terminal_output&  s"    #"7+"::6	
r   c                 <    |  |       nd}t        d|d|i       y )Nr   zterminal.closerP
  r  )r#  rP
  r-  rN
  s      rD   _emit_agent_terminal_closez?_wire_agent_terminal_output.<locals>._emit_agent_terminal_close&  s)     291D$W-"lJ%?@r   )r:
  r2
  r   r6   rJ
  rK
  )r2
  has_output_sinkhas_close_sinkrR
  rT
  rN
  s        @rD   _wire_agent_terminal_outputrW
  &  sn     8.TB$NO-z4@LN>3 
A %@"$>! r   c                     t                t        j                         }t        j                  t        || |fd      }|j                          |S )z;Start the background notification poller for a TUI session.Tr   rJ   r   )rW
  r   rw  r   rG
  r   )r-  r#  stopr  s       rD   r  r  &  sD    !??D(C!	A
 GGIKr   c                    	 d   5  t        d         t        j                  dd            t        j                  dg             	g d<   t        j                  d      t              st               d d d        d   t        d      r	 j                          t        d	       	 fd
}t        j                  |d      }|d<   |j                          y # 1 sw Y   pxY w# t        $ r Y \w xY w)NrO  rP  r1  r   r2  r  rN  clear_interruptr  c                  r   QRS d } g }d }d }Yj                  dd       }	 ddlm}m}  |Yd         } t	        Yd   Z      }Yj                  d      }|rt        |      }t        Z       |st        ZY       t        Y      }t        Y       Yj                  dd      }	t        |	      S[}
t        |
t              rfd	|
v radd
lm} ddlm}  |t%        Tdd      xs
 t'               t%        Tdd      xs dt%        Tdd      xs dt%        Tdd      xs dt%        Tdd             } ||
|||      }|j(                  rt+        dZddj-                  |j.                        xs di       	 |r/	 t1        T|       t3        ZY       t5        Y       t7        Y       	 |  ||        |t?        |       tA        |       d T_!        Yd   5  dYd<   tE        jD                         Yd<   tG        Y       d d d        t+        dZtI        TY             y |jJ                  }
|
}Wr	 dd l&m'}m(} dd!l)m*}  |       }tW        T      \  }} ||||      }t%        Td"d      d#k(  rd$}|d'k(  rY	  |
W      \  }}|r(tY        d(t_        |       d)tZ        j\                  &       ta        d* |D              r|}ntc        |
W      }ntc        |
W      }YZSfd,}te               rdd-d$t        d.tf        d/d fZfd0}|T_!        nd T_!        ti        U      |d1}	 d2tk        jl                  Tjn                        jp                  v rYd   |d2<    Tjn                  |fi |}d3Yv rYj                  d3d       }t        |tv              rv|j                  d4      }|j                  d      } |j                  d      }!|Yj                  d5d        n|Yd5<   | rA|!r|  d6|! n| }"	 ty        ZY|"dtg        |      d7       n|Yj                  d5d        n|Yd5<   d }$d }%t        |tv              rVt        |j                  d9      th              rcYd   5  t}        Yj                  d:d            }&|&Vk(  r|d9   Yd;<   Vd<z   Yd:<   n$tY        d=V d>|& d?tZ        j\                  &       d@}%d d d        t        ZYddA       |j                  dBd      }'|j                  dC      rdCn|j                  d      rdndD}(|'sG|j                  d      r6|j                  dE      s|j                  dF      rdG|j                  d       }'|j                  dH      })t        |)t              r.|)j                         r|)j                         }$nt        |      }'dD}(|'t        T      |(dI}*|$r|$|*dJ<   |%r|%|*dK<   |j                  dL      rd|*dL<   t        |'|	      }+|+r|+|*dM<   Yd   5  tG        Y       d d d        t+        dNZ|*       |(dDk(  rt        |'t              r|'j                         r	 ddOlCmD}, Yj                  d      xs d}-|-r	 t               j                  dP      xs i }.t}        |.j                  dQdR      xs dR      }/ |,|-|/S      }0|0j                         rs	 ddTlCmG}1  |1       }2|0j                  |'d|2U      }3|3j                  d      xs d}4|4rt+        dVZdW|4dX       |3j                  dY      r|3j                  dZ      xs d}5|5r|5}Yj                  d]      }7|7r>|(dDk(  r9t               }8|8r-Yj                  d      xs Z}9	 |8j                  |9|7      rd Yd]<   |(dDk(  rt        |'t              r|'j                         rt        [t              r[j                         r	 dd_lNmO}; Yj                  d      xs Z}<t%        Tdd       Qt%        Tdd       R |;t               |<[|'Yj                  d;g       t%        Tdd       t%        Tdd       t%        Tdd       t%        Tdd       t%        Td"d       d`QRTfda|<fZfdb	c       |(dDk(  rZt        |'t              rJ|'j                         r:t               r0	 dddlQmR}= |'}>t        j                  |=|>fde      j                          |r/	 t1        T|       t3        ZY       t5        Y       t7        Y       	 |  |        |t?        |       tA        |       d T_!        Yd   5  dYd<   tE        jD                         Yd<   tG        Y       d d d        t+        dZtI        TY             t        XZY      ry |rIYd   5  Yj                  d      r
	 d d d        y dYd<   d d d        	 t+        drZ       t        XZY|       	 ddtlcmd}D |Dj                  Yj                  dd      YZfdudv      }Et        |E      D ]  \  }F\  }G}HYd   5  Yj                  d      r3EFd  D ]   \  }I}JDj                  j                  |I       " 	 d d d         y dYd<   d d d        ddwlimj}Kmk}Lml}M  |KGdx      }N|Nv	 t+        drZ       t        XZYH        LGN        y # t8        $ r t:        j=                  dd       Y w xY w# t8        $ r Y w xY w# 1 sw Y   xY w# t8        $ r+}tY        d%| tZ        j\                  &       d$}Y d }~d }~ww xY w# t8        $ r5}tY        d+| tZ        j\                  &       tc        |
W      }Y d }~Yd }~ww xY w# tr        tt        f$ r Y w xY w# t8        $ r!}#t:        j{                  d8|#       Y d }#~#Zd }#~#ww xY w# 1 sw Y   xY w# 1 sw Y   xY w# t8        $ r dR}/Y %w xY w# t8        $ r d }2Y w xY w# t8        $ r?}6tY        d[t        |6      j                   d\|6 tZ        j\                  &       Y d }6~6d }6~6ww xY w# tt        $ r'}:d Yd]<   t:        j                  d^|9|:       Y d }:~:d }:~:wt8        $ r Y w xY w# t8        $ r Y w xY w# t        $ r t:        j{                  df       Y t8        $ r!}?t:        j{                  dg|?       Y d }?~?d }?~?ww xY w# t8        $ r}?dd lW}@|@j                         }A	 t        j                  t        j                  j                  t              dh       t        t        didjk      5 }B|Bj                  dltE        j                  dm       dnZ do       |Bj                  A       d d d        n# 1 sw Y   nxY wn# t8        $ r Y nw xY wtY        dpt        |?      j                   d\|? tZ        j\                  dq       t+        dZdt        |?      i       Y d }?~?d }?~?ww xY w# t8        $ r t:        j=                  dd       Y w xY w# t8        $ r Y w xY w# 1 sw Y   xY w# |rV	 t1        T|       t3        ZY       t5        Y       t7        Y       n&# t8        $ r t:        j=                  dd       Y nw xY w	 |  |        n# t8        $ r Y nw xY w|t?        |       tA        |       d T_!        Yd   5  dYd<   tE        jD                         Yd<   tG        Y       d d d        n# 1 sw Y   nxY wt+        dZtI        TY             w xY w# 1 sw Y   yxY w# t8        $ r_}CtY        dst        C      j                   d\|C tZ        j\                  &       Yd   5  dYd<   d d d        n# 1 sw Y   nxY wY d }C~Cd }C~Cww xY w# 1 sw Y   <xY w# t8        $ rh}O MGN       tY        dyt        O      j                   d\|O tZ        j\                  &       Yd   5  dYd<   d d d        n# 1 sw Y   nxY wY d }O~Od }O~Oww xY w# t8        $ r>}PtY        dzt        P      j                   d\|P tZ        j\                  &       Y d }P~Py d }P~Pww xY w){Nrv  r   )reset_current_session_keyset_current_session_keyr   rd  r   r3  r4  @)preprocess_context_references)get_model_context_lengthr   r   r  rG  r  _config_context_length)r  rG  r  ro  )r   allowed_rootrm  r   rK  r   zContext injection refused.z!TUI one-turn model restore failedTr&  rO  Fr  r  rP  )decide_image_input_modebuild_native_content_partsr  r  codex_app_serverr   zA[tui_gateway] image_routing decision failed, defaulting to text: r
  nativez.[tui_gateway] native image attachment skipped z unreadable path(s)c              3   D   K   | ]  }|j                  d       dk(    yw)r  r  Nr  r  s     rD   r  z2_run_prompt_submit.<locals>.run.<locals>.<genexpr><'  s     LquuV};Ls    z:[tui_gateway] native attach failed, falling back to text: c                     d   5  t        |        d d d        d| i}rj                  |       x}||d<   t        d|       y # 1 sw Y   5xY w)NrO  r   rz  r  )r  feedr  )r  r  r  r#  r-  streamers      rD   _streamz0_run_prompt_submit.<locals>.run.<locals>._streamI'  s_    ^, ;*7E:;!5/hmmE&:!: G*+GJ'osG4; ;s   AAr  r  r   c                &    t        d| |d       y r  r  r  s     rD   _interim_assistant_cbz>_run_prompt_submit.<locals>.run.<locals>._interim_assistant_cbW'  s    +S $,<3 r   )conversation_historystream_callbackr  moa_one_shot_restorer  r5  r  r  z%MoA one-shot model restore failed: %srn  r1  rP  r   z@[tui_gateway] prompt.submit: history_version mismatch (expected=z	 current=u1   ) — agent output NOT written to session historyuh   History changed during this turn — the response above is visible but was not saved to session history.r  final_responserV  completer  partialrM  last_reasoning)r   r  rN  r  r   response_previewedrz  rL  GoalManagergoalsr     r  default_max_turns)gather_background_processes)user_initiatedbackground_processesrw  r  rx  should_continuecontinuation_promptz-[tui_gateway] goal continuation hook failed: r%   r  z)Dropping pending title for session %s: %s)maybe_auto_titlerw  c                  H    t        dd        k(  xr t        dd       k(  S )Nr   r  r  )_title_model_title_providerrN  s   rD   r   z1_run_prompt_submit.<locals>.run.<locals>.<lambda>M(  s0    #E7D9\I T 'z4 @O S r   c                 $    t        d|| d      S )Nr  )r  r  r  )r  _kr-  s     rD   r   z1_run_prompt_submit.<locals>.run.<locals>.<lambda>T(  s    +Sa2PA r   )r  runtime_validatortitle_callback
speak_textrY
  z/voice TTS skipped: hermes_cli.voice unavailablezvoice TTS dispatch failed: %sr   r   r    r!   u"   
=== turn-dispatcher exception · r#   u    · sid=r$   z[gateway-turn] r&   r  z1[tui_gateway] goal continuation dispatch failed: rI
  c                     t        |       S r   )r"
  )r  r#  r-  s    rD   r   z1_run_prompt_submit.<locals>.run.<locals>.<lambda>(  s    %Ec7TU%V r   )r   
owns_eventskip_poll_observedr6
  ztui-post-turnz7[tui_gateway] completion notification dispatch failed: z-[tui_gateway] completion queue drain failed: )mr(  rv  r^
  r_
  r  r   r   r  r  r;  r  rN   r  r6   agent.context_referencesra
  r  rb
  r   r  blockedr  r*   r  rT  r?  r  r  r5   r  r*  r   r  r  r3   rQ  rR  rK  agent.image_routingre
  rf
  r^  r  r  r:   r;   r<   r  r  r  r  r   r_  inspect	signaturerun_conversation
parametersrS  r>  r   r  r   r  r  r7   r  rP   hermes_cli.goalsry
  r  	is_activer~
  evaluate_after_turnr  r9   ra  r  rH  agent.title_generatorr
  _voice_tts_enabledhermes_cli.voicer
  r   r   r   ImportErrorr)   
format_excr,   r-   r.   r/   r0   r1   r2   r4   rT  r  r:
  r2
  drain_notificationsr  r;
  r   rd  r7
  r8
  r9
  )\approval_tokensession_tokensr  goal_followupone_turn_restorer^
  r_
  _profile_home_strr   r3  r  ra
  rb
  ctx_lenr  run_messagere
  rf
  _tui_load_config_cfg	_provider_model_mode_img_exc_parts_skippedrm
  ro
  
run_kwargsr  _restore_prev_override_prev_model_prev_provider_raw_moa_restore_excrv
  status_notecurrent_versionr  rN  lrr  rz  ry
  sid_key	goals_cfggoal_max_turnsgoal_mgr
_gather_bg	_bg_procsdecisionverdict_msgcont_prompt	_goal_excrS   _pdb_session_keyr!  r
  
_title_keyr
  spokenr  r)   rA   rB   	_cont_excr2
  drainedr  _evtsynthpending_evt_pending_synthr7
  r8
  r9
  rE
  _n_exc
_drain_excr
  r
  rl
  rN  rP  r1  imagesr   r#  r-  r   s\                                                                                    @@@rD   r   z_run_prompt_submit.<locals>.run&  s   
";;'?FJ	F
 5W]5KLN1&!N !(N ; 56GH
 C  $-c7;w'C!'*;;vr*D+D1HF&#&3&=RI2E7B/C>3C$UJ;Ar#E9b9?R$UJ;Ar*17+ 4!$#*	 ;;%tyy'> (<; f  U08HI)#w71':7@!--n= %*:6">2 04E,( .%*	")-&$W-. .#}UG'DES   &K# R+-D(Fu(M%Iv3!E
 uj"59KK & H$S+E"",( $!"PQTU]Q^P__r s%(ZZ LVLL*0K*Fvv*VK #?vv"NK5 01QV  $ [_  4I0370 )-W#*J 1 1%2H2H I T TT,3M,BJy) ,U++KF:FF%0";;'=tD h-%-\\*%=N"*,,w"7K%-\\*%=N%-$4d;4B 01"  .  +m<7GH!, 
/ # ' $8=59.5I 27	 %KK 0$708G,-!NK&$'fjj4d; 0 *-gkk:KQ.O*P*o=17
1CGI.9H19LG$56 "#--<,=YFW XN!O &)ZZ	!H ()> 1eRV jj!126 zz-0 "$*JJw$7Z  G!4JJx(FJJy,A#FJJw$7#89CZZ 01b#&288:%'XXZN&k#"Z->&QG'5$%0	"zz./04,-%c40H&.
#( .$W-.$c73 #
3(<)<%kk-8>BG0(1(@(FBI-0{B1O1USU-VN $/'..<$ $--/1 f,6L	 (0'C'C #/35> (D (H
 +3,,y*A*GRK* %$3$'-3[$I!"
  (||,=>.6ll;P.Q.WUW#.4?M {{?3HFj0y#*;;}#=#DL11,I7;GO4 *$sC(IIKtS)JJL&F!(]!;!BsJ $+5'4#@L&-eZ&FO$	"Ir2 &-UGT%B(/z4(H(/z4(H'.ui'F(/z4(H&+ 5? (1H *$sC(IIK&(
G; F$$)	$eg0  U08HI)#w71':7@!--n= %*:6">2 04E,( .%*	")-&$W-. .#}UG'DE
  S'2 ( *;;y) 	* *
 &*	"*
/os+"3WmD$,	? '::#KKr:V#( ; G
 )2'(: 3$}e^, .{{9-;B56? O7K,==AA+NO	. .
 *.GI&.  .dOD>3/3/&sC%@+D&9!3O ! ULL!DtLTU
  . .Y ! #[\d[ef ZZ #E#, % SXYaXbc!$ 'C66&RSP z* F  ) "NN G 0  L. .*  ) 0-/N0 $- 1,0	1$ ! G	?334BykC ZZ   &  480G(#  % ` ! ( # VNN#TU  GNN#BAFFG 	5((*E	BGGOOJ7$G*cG< #GG===)<=>hse6S GGEN# # #  !$q'"2"2!32aS9

RV '3CF 344#	52 ! ULL!DtLTU
  . .'  U08HI)#w71':7@  ULL!DtLTU!--n= %*:6">2 04E,( .%*	")-&$W-. . . .#}UG'DE* *  /GI//09+?
 ^, /).GI&/ / //>. .  ! 3*48Q<001F8= ZZ
 !0 3-2	*3 3 33  	?
#,,-R
|=ZZ 	s  Er 5.i9 $
j  (j0r +?j= *r 0Ak4 Ar 3l5 Br !m ;Ar Am8%D4r n%;r !n6 ?<n ;n6 n$ #A%n6 9r p Ar B$p? /r 3/q %.w 
w) (w9{6:{6| #A/ *;}.%	/ /}.4/ #};6/ 9 jj 	j-,j-0j:=	k1 k,&r ,k11r 4	l2=*l-'r -l22r 5mr mr 	m5m0*r 0m55r 8n=r n
r n!n6  n!!n6 $n3/n6 2n33n6 6	o>?4o93r 9o>>r 	p<
p,&r ,p<8r ;p<<r ?	qr qr r-r 0r8rr rr 
v?&v:;A
u=u	uu	uv:	u$!v:#u$$Av:4x :v??x  w&%w&)	w65w69x{3
.x98{39 y{3y{3 
y+*{3+	y74{36y77'{3({	{3{{36| 	}+9}&}	}&}	}&&}+.}8	3/ ;	,A'	''!/ ',,/ /	A@684A@1@1A@6Tr   r	  )r_  r  r   r  r   r  r`  r\
  r5   r  r   r   r   )
r   r-  r#  r   r   r	  rN  rP  r1  r
  s
   ````  @@@@rD   r  r  &  s   		  0wy)*gkk*;Q?@gkk"3R89%'!"'++o6= $/0 GEu'(	!!# 
/3e eN !!T:J'GMq0 0  		s   A5C2C> 2C;>	D
	D
zclipboard.pastec           	      p   t        ||       \  }}|r|S 	 ddlm}m} |j                  dd      dz   |d<   t        dz  }|j                  dd	       |d
t        j                         j                  d       d|d    dz  } ||      s/t        d|d   dz
        |d<    |       rdnd}	t        | d|	d      S |j                  dg       j                  t!        |             t        | dt!        |      t#        |d         dt%        |            S # t        $ r}t        | dd|       cY d }~S d }~ww xY w)Nr   )has_clipboard_imagesave_clipboard_image  zclipboard unavailable: rV  r   r
  TrW  clip_r  r  r  z)Clipboard has image but extraction failedzNo image found in clipboardF)attachedrK  r2  )r
  r.   r.  )r  hermes_cli.clipboardr
  r
  r5   r  r   r  rZ  r   r  r4   rF  ra  rf  r  r6   r  r  )
r   r  r#  r  r
  r
  r  img_dirimg_pathr   s
             rD   r  r  (  sd   %LGS

>R  '{{?A>BGOX%GMM$M.(,,.))/:;1W_=U<VVZ
[	\   )#&q'/*BQ*F#G  #$ 8. 	
 3Us;<<("-44S]CM!234	
 (#		
 -  >C!8<==>s   D 	D5D0*D50D5zimage.attachc           
         t        ||       \  }}|r|S t        |j                  dd      xs d      j                         }|st	        | dd      S 	 ddlm}m}m}m	}  ||      }	|	r|	d   }
|	d   }n% ||      \  }} ||      }
|
t	        | dd	|       S |
j                  j                         |vrt	        | dd
|
j                         S |j                  dg       j                  t        |
             t        | dt        |
      t!        |d         ||xs d|
j                   ddt#        |
            S # t$        $ r }t	        | dt        |            cY d }~S d }~ww xY w)Nr.   r     r	  r   )_IMAGE_EXTENSIONS_detect_file_drop_resolve_attachment_path_split_path_input	remainderr\  zimage not found: zunsupported image: r2  T[User attached image: r  )r
  r.   r.  r
  r   r
  )r  r6   r   r7   r  r8  r
  r
  r
  r
  rb  r  rI   rf  r  ra  r  r  r5   )r   r  r#  r  r  r
  r
  r
  r
  dropped
image_pathr
  
path_tokenr  s                 rD   r  r  )  s   %LGS


fjj$*
+
1
1
3CC// '	
 	
 $C( J,I$5c$:!J	1*=J!C)::,'GHH""$,==T%88I#JKK,b188ZI JW%678&!P'=joo=Na%P j)

 
	
  'Cs1v&&'s,   AD; 5D; A-D; ;	E$EE$E$i  i   r+  ))s   PNG

r  )s   .jpg)s   GIF87a.gif)s   GIF89ar
  )s   BM.bmp_IMAGE_MAGICr  mime_prefixc                $   ddl }ddl}| j                         }|j                  d|j	                  |       d||j
                        }|r|j                  d      }|j                  dd|      }	 |j                  |d	      S # t        $ r Y yw xY w)
zDecode a base64 (optionally data-URL-wrapped) payload.

    Accepts ``data:<mime_prefix>...;base64,<b64>`` plus embedded whitespace.
    Returns the decoded bytes, or ``None`` when the input isn't valid base64.
    r   Nz^data:z[a-zA-Z0-9.+-]*;base64,(.*)$r   \s+r   Tr{  )
r  r~  r7   r  escaper  r  subr  r5   )r  r
  _base64r  cleanedr  s         rD   _decode_attach_base64r
  Y)  s     iikG		#**[)**FG

	A
 	''!*ggfb'*G  4 88 s   0B 	BB	img_bytesrC  c                     |r't        |      j                  j                         }|r|S | dd }|j                  d      r	|dd dk(  ryt        D ]  \  }}|j                  |      s|c S  y)	zResolve an image extension from a filename hint, else magic bytes.

    Falls back to ``.png``. WebP needs the RIFF/WEBP container check, handled
    before the generic table.
    Nr+  s   RIFFr   r  s   WEBP.webpr  )r   rb  r  r  r
  )r
  rC  rb  headsigr  s         rD   _sniff_image_extr
  q)  sw     h&&,,.MSb>DwD2J'$9  S??3J r   c                  ^    	 ddl m}  t        |       S # t        $ r t        h d      cY S w xY w)Nr   r
  >   .jpegr
  r
  r
  r  r
  )r8  r
  r!  r5   r
  s    rD   _allowed_image_extensionsr
  )  s4    M)*++ MKLLMs    ,,r  r  c                   | j                  dd      dz   | d<   t        dz  }|j                  dd       t        j                         j                  d      }|| d| d| d    | z  }	 |j                  |       | j                  d	g       j                  t        |             |S # t        $ r t        d| d   dz
        | d<    w xY w)
a#  Write image bytes into the gateway's images dir and queue them.

    Mirrors what ``image.attach`` does for a local path: appends to
    ``session["attached_images"]`` so the next ``prompt.submit`` picks it up via
    the existing native-image-attach pipeline. Returns the written path.
    rV  r   r   r
  TrW  r  r  r2  )r   r  rZ  r   r  r4   r  r5   rF  rf  r  r6   )r#  r
  r  r  r
  r  r
  s          rD   _queue_attached_imager
  )  s      '{{?A>BGOX%GMM$M.		 	 	1BF81RD'/*B)CC5IIHY' ("-44S]CO	  #&q'/*BQ*F#G s   +B( ( Czimage.attach_bytesc                    t        ||       \  }}|r|S t        |j                  d      xs |j                  d      xs d      j                         }|st	        | dd      S t        |d      }|t	        | d	d
      S |st	        | d	d      S t        |      t        kD  r&t        dz  }t	        | ddt        |       d| d      S t        |j                  dd      xs d      }t        |j                  dd      xs d      j                         j                         }|r|j                  d      sd|z   }t        ||xs	 |rd| nd      }	|	t               vrt	        | dd|	       S 	 t        |||	d      }
t        | dt        |
      t        |d         dd|
j                   dt        |      dt!        |
            S # t        $ r}t	        | dd|       cY d}~S d}~ww xY w) u  Attach an image to the session from base64 bytes (remote-client path).

    A desktop app or web dashboard running on a DIFFERENT machine than the
    gateway can't hand us a local path — that file only exists on the client's
    disk. So it uploads the raw image bytes (base64) and we write them into the
    gateway's own images dir. The response shape mirrors ``image.attach`` so the
    client treats both identically.

    Params:
      content_base64 / data (str, required): base64 image bytes. Accepts a
        ``data:image/...;base64,`` prefix and embedded whitespace. ``data`` is
        an accepted alias for older desktop builds.
      filename / ext (str, optional): extension hint. Without it, magic bytes
        identify PNG/JPEG/GIF/WebP/BMP, falling back to ``.png``.
    content_base64r  r   r
  zcontent_base64 requiredzimage/r
  Nr^  data is not valid base64zimage is empty   r
  zimage too large ( bytes; cap is  MB)rC  r  r  xr\  zunsupported image extension: uploadr  r
  zwrite failed: Tr2  r
  r  )r
  r.   r.  r
  r   bytes)r  r6   r   r7   r  r
  r  _ATTACH_BYTES_MAX_BYTESr  r  r
  r
  r
  r5   ra  rI   r  )r   r  r#  r  raw_b64r
  mbrC  ext_hintr  r
  r  s               rD   r  r  )  s   " %LGS

&**-.J&**V2DJKQQSGC899%g8DIC9::C/00
9~//$5C!23y>2B/RTQUUYZ[[6::j"-34H6::eR(.B/557==?H++C0>
9h&VXQxj>SU
WC
+--C!>seDEE5()SR M!234,X]]O1=^	
 (#	
   5Cs3445s   +G 	G'G"G'"G'z
pdf.attachc                 \   ddl }ddl}ddl}t        ||       \  }}|r|S |j	                  d      t        | dd      S t        |j                  dd      xs d      j                         }t        |j                  d      xs |j                  d	      xs d      j                         }|s|st        | d
d      S |j                  d      5 }	t        |	      }
|rt        |d      }|t        | dd      cddd       S |st        | dd      cddd       S t        |      t        kD  r/t        dz  }t        | ddt        |       d| d      cddd       S |dd dk7  rt        | dd      cddd       S |
dz  }|j                  |       t        |j                  dd      xs d      }n	 ddlm}  ||      }|t        |      j%                         st        | dd |       cddd       S t        |      j&                  j)                         d!k7  r,t        | dd"t        |      j*                         cddd       S t        |      j-                         j.                  t        kD  r#t        dz  }t        | dd#| d$      cddd       S t        |      }|j*                  }	 t1        |j                  d%      xs d&      }|j                  d'      }|t1        |      nd}|d&k  rt        | d
d)      cddd       S ||t6        z   d&z
  }||k  rt        | d
d*      cddd       S ||z
  d&z   t6        kD  rt        | d+d,t6         d-      cddd       S |
d.z  }dd/d0d1d2t        |      d3t        |      t        |      t        |      g
}dd4lm} 	  |j<                  |d5d5d6|j>                   |       7      }|jB                  dk7  re|jD                  xs |jF                  xs dj                         jI                         d9d }t        | dd:d;jK                  |      z         cddd       S tM        |
jO                  d<            }|st        | dd=      cddd       S g }|D ]u  }|jP                  jS                  d>d&      d?   }	 t1        |      }tU        ||jW                         d@dA|       }|jY                  t        |      |dBt[        |             w t]        | d5|t        |      |t        |dC         dD| dEt        |       dFdG      cddd       S # t"        $ r d}Y nw xY w# t2        t4        f$ r t        | d
d(      cY cddd       S w xY w# |j@                  $ r t        | dd8      cY cddd       S w xY w# t4        $ r |t        |      z   }Y w xY w# 1 sw Y   yxY w)Ha  Attach a PDF by rendering each page to PNG and queuing the pages.

    Anthropic's vision pipeline accepts images, not PDFs, so this runs
    ``pdftoppm`` (poppler-utils) at 150 DPI per page and queues each rendered
    page as an attached image. Accepts either a host ``path`` (local mode) or
    base64 ``content_base64`` (remote upload). Caps at 50 MB / 25 pages per call.

    Requires ``pdftoppm`` on $PATH (``apt install poppler-utils``); returns 5028
    if missing.
    r   Npdftoppm  z7pdftoppm not installed (poppler-utils package required)r.   r   r
  r  r
  zpath or content_base64 requiredpdf_attach_r  zapplication/pdfr
  r^  r
  zdecoded PDF is emptyr   r
  zPDF too large (r  r     s   %PDF-z0payload is not a PDF (missing %PDF- magic bytes)z	input.pdfrC  zuploaded.pdf)r
  r\  zPDF not found: z.pdfznot a PDF: zPDF too large; cap is z MB
first_pager   	last_pagez%first_page/last_page must be integerszfirst_page must be >= 1zlast_page must be >= first_page  zpage range exceeds cap of z pages per attach callr^  z-pngz-r150z-fz-lr   Tr  )capture_outputr   r   r   r   zpdftoppm timed out (>120s)zpdftoppm failed: z | z
page-*.pngz)pdftoppm produced no pages (corrupt PDF?)-r  r  pdf_p)r.   r^  r2  z[User attached PDF: r	  z
 page(s))])r
  rC  pages_attachedr_  r.  r   )/r`  r   tempfiler  whichr  r6   r   r7   TemporaryDirectoryr   r
  r  _PDF_ATTACH_MAX_BYTESr  r8  r
  r5   r  rb  r  rI   rQ  r  r  rS  r>  _PDF_ATTACH_MAX_PAGESr   r   r   DEVNULLTimeoutExpired
returncoder<   r   r8   r*   r!  r	  stemr  r
  r  r  r  ra  )r   r  r`  r   r  r#  r  r	  r  tdtd_path	pdf_bytesr	  pdf_pathr  r
  r  r  last_page_paramr  
out_prefixr   r   resr6  rz  attached_pagesrG  page_numpage_intdsts                                  rD   r  r  )  s    %LGS

||J'CXYY6::fb)/R0668H&**-.J&**V2DJKQQSGGC@AA		$	$M	$	: \
br(-gCTUI C'AB\
 \
 C'=>\
 \
 9~ 55*{;CY8HXZW[[_'`a\
 \
 !}(C'YZ\
 \
 ,H  +vzz*b9K^LL 83H= tH~'='='?C
'CD1\
 \
2 H~$$**,6CT(^5H5H4I'JK5\
 \
6 H~""$,,/DD*{;C)?t3'GH;\
 \
< H~H#==L	LVZZ5:;J$jj5O0?0KO,QUI >T#<=S\
 \
T "%::Q>Iz!T#DE[\
 \
\ z!A%(==T%?@U?VVl#mn_\
 \
b v%
e#j/4YM3z?

 	E	A *..TcI[I[02C >>QJJ2#**299;FFHMDT#6D9I#IJE\
 \
H ',,|45T#NOM\
 \
P  	\Cxx~~c1-b1H<x= (1A6TYZbYcRdeC!!3s8X"ZUXIY"Z[	\  ("%n"5'W%678.|nBs>?R>SS]^

e\
 \
*      :& 	LT#JKKM\
 \
J	L2 (( 	AT#?@@\
 \
|	A  <%N(;;<[\
 \
s   )V" V"7V"V"76V".T<*V"0AV"AV"V"'>T.%V" V")#V";V"'U9A*V"-(V"&V"VBV"T+'V"*T++V".U
V"UV"V5V" VV"VV"VV""V+c                     ddl }t        |j                  d      a| rt        j                  |       s| S d| vrd|  dS d| vrd|  dS d| vrd|  dS | S )zQuote a context-ref value when it contains whitespace or bracket chars.

    Mirrors the desktop ``formatRefValue`` so the staged ``@file:`` ref round-trips
    through ``agent.context_references`` cleanly.
    r   Nz[\s()\[\]{}<>"'`]r  r	  r  )r~   _ATTACHMENT_REF_NEEDS_QUOTING_REcompilerZ  )rE  r  s     rD   _format_ref_valuer0  ]*  s|      (/+.;;7O+P(8??F
%5'|
%5'|
%5'|Lr   r   c                 (   t        t        |             j                         }	 |j                         j                  |      }t	        |      j                  t        j                  d      S # t        $ r t	        |j                               cY S w xY w)zKWorkspace-relative path for an attachment, or the absolute path if outside.r  )	r   r;  r  r	  r6   r  r,   sepr>  )r#  r   	workspacerels       rD   _attachment_ref_pathr5  s*  sr    \'*+335I%nn**953x,, %6>>#$$%s   AA, ,"BBc                 |    t        t        |             j                         dz  dz  }|j                  dd       |S )Nz.hermeszdesktop-attachmentsTrW  )r   r;  r  rZ  )r#  r  s     rD   _desktop_attachment_dirr7  }*  s:    W%&..09<?TTDJJtdJ+Kr   c                     dd l }t        t        | xs d      j                               j                  }|j                  dd|      }|j                         j                  d      }|xs dS )Nr   r   z[\x00-\x1f]+r  r  
attachment)r~  r   r6   r7   rI   r
  )rI   r  r  s      rD   _sanitize_attachment_namer:  *  sZ    S_**,-22Ii8I!'',I$$r   r  c                     | |z  }|j                         s|S t        |      j                  xs d}t        |      j                  }d}	 | | d| | z  }|j                         s|S |dz  }$)Nr9  r   r  r   )r  r   r!  rb  )r  rC  r  r!  rb  counternext_candidates          rD   _unique_attachment_pathr>  *  s    xI>.,D(^""FG
4&'6( ;;$$&!!1	 r   c                     | sy	 ddl m}m}m}  ||       }|rt        |d         j                         S  ||       \  }} ||      }|t        |      j                         S dS # t        $ r Y yw xY w)z<Resolve a raw path token to a gateway-visible file, or None.Nr   )r
  r
  r
  r.   )r8  r
  r
  r
  r5   r   r  )r  r
  r
  r
  r
  r
  
_remainderr  s           rD    _resolve_gateway_attachment_pathrA  *  s    VV  $GGFO$,,...s3J
'
3H'/';4>!!#EE  s   
A% %	A10A1data_urlc                 \   ddl }ddl}ddl}| xs dj                         }|j	                  d||j
                  |j                  z        }|r|j                  d      }|j                  dd|      }	 |j                  |d      S # t        |j                  f$ r}t        d	      |d}~ww xY w)
u,  Decode a ``data:<any-mime>;base64,<b64>`` payload to bytes.

    Unlike ``_decode_attach_base64`` (image-mime-specific), this accepts any
    media type — text/csv, application/pdf, etc. — so non-image file uploads
    round-trip. Also tolerates a bare base64 string with no data-URL prefix.
    r   Nr   z-^data:[^;,]*(?:;[^;,=]+=[^;,]+)*;base64,(.*)$r   r
  Tr{  zinvalid data_url payload)r  r}  r~  r7   r  r  Ir  r
  r  r>  r  )rB  r
  	_binasciir  r
  r  r!  s          rD   _decode_attachment_data_urlrF  *  s      ~2$$&G		BGSZZZ]Z_Z_M_`A''!*ggfb'*G>  4 88	( >34#=>s   2B B+B&&B+r	  c                   t        t        |             j                         }t        |      }|	 |j	                  |       |dfS |st        d      t        |      }t        |xs" t        t        |xs d            j                        }t        |       }t        |t        |            }	|	j                  |       |	j                         dfS # t
        $ r |j                         }|j                  }Y jw xY w)u  Make a desktop file attachment available to the remote gateway agent.

    Three cases:
      1. The path resolves to a file already INSIDE the session workspace — use
         it as-is (no copy, ``uploaded=False``).
      2. The path resolves to a gateway-visible file OUTSIDE the workspace — copy
         it into ``.hermes/desktop-attachments/`` so the ``@file:`` ref resolves.
      3. The path doesn't exist on the gateway (the common remote case: it's a
         path on the CLIENT's disk) — decode the uploaded ``data_url`` bytes and
         write them into ``.hermes/desktop-attachments/``.

    Returns ``(stored_path, uploaded)``.
    Fz2file not found on gateway and no data_url providedr   T)r   r;  r  rA  r	  r>  r  rI   rF  r:  r6   r7  r>  r  )
r#  r	  rB  rI   r3  r  r  rC  
upload_dirr   s
             rD   _stage_session_file_attachmentrI  *  s    ( \'*+335I/9H	%  +U?"
 QRR-h7,T-ST#hn":M5N5S5ST(1J$Z1J81TUF
w>>T!!  	%))+G}}H	%s   C %C87C8zfile.attachc                 R   t        ||       \  }}|r|S t        |j                  dd      xs d      j                         }t        |j                  dd      xs d      j                         }t        |j                  dd      xs d      j                         }|s|st	        | dd      S 	 t        ||||      \  }}t        ||      }	t        | d|j                  t        |      |	d	t        |	       |d
      S # t        $ r }
t	        | dt        |
            cY d}
~
S d}
~
ww xY w)aB  Stage a non-image file attachment into the session workspace.

    The image/PDF path renders to vision tiles; this one keeps the file as a
    readable artifact and returns a workspace-relative ``@file:`` ref so the
    agent's file tools (and ``agent.context_references``) can read it. Solves the
    remote-gateway case where the desktop passes a path that only exists on the
    CLIENT's disk: the client uploads ``data_url`` bytes and we materialize the
    file on the gateway.

    Params:
      session_id (str, required)
      path (str): client/host path of the file (used for naming + local-mode
        gateway-visible resolution).
      data_url (str): ``data:<mime>;base64,<b64>`` upload of the file bytes,
        required when the path isn't visible to the gateway.
      name (str, optional): preferred filename.
    r.   r   rB  rI   r
  zpath or data_url required)r	  rB  rI   T@file:)r
  rI   r.   r  ref_textuploadedr  N)r  r6   r   r7   r  rI  r5  ra  rI   r0  r5   )r   r  r#  r  r  rB  rI   stored_pathrM  r  r  s              rD   r  r  *  s*   & %LGS


fjj$*
+
1
1
3C6::j"-34::<Hvzz&"%+,224DxC:;;' >cH4!
X (= #((K($$%6x%@$AB$

 
	
  'Cs1v&&'s   -AC= =	D&D!D&!D&zimage.detachc                 j   t        ||       \  }}|r|S t        |j                  dd      xs d      j                         }|st	        | dd      S |j                  dg       }t        |      }|D cg c]
  }||k7  s	| c}|d<   t        | t        |d         |k7  t        |d         d      S c c}w )Nr.   r   r
  r	  r2  )r  r.  )r  r6   r   r7   r  rf  r  ra  )r   r  r#  r  r  r
  beforer.   s           rD   r  r  +  s    %LGS


fjj$*
+
1
1
3CC// 126F[F39!I4TS[$!IGG$5676A!234	
  "Js   1
B0<B0zinput.detect_dropc           
      d   t        ||       \  }}|r|S 	 ddlm} t        |j	                  dd      xs d      } ||      }|st        | ddi      S |d   }|d   }|d	   rp|j                  d
g       j                  t        |             |xs d|j                   d}	t        | ddt        |      t        |d
         |	dt        |            S d| d|rd| ndz   }	t        | ddt        |      |j                  |	d      S # t        $ r }
t        | dt        |
            cY d }
~
S d }
~
ww xY w)Nr   )r
  r   r   matchedFr.   r
  is_imager2  r
  r  T)rR  rS  r.   r.  r   z[User attached file: r   )rR  rS  r.   rI   r   r
  )r  r8  r
  r6   r   ra  rf  r  rI   r  r  r5   r  )r   r  r#  r  r
  r  r
  	drop_pathr
  r   r  s              rD   r  r  -+  sg   ,LGS

'')&**VR(.B/#C(sY.//FO	K(	:0"5<<S^LJ"88H JD# $	N ):!;<  "),
 
 'yk3 )br
 !I!	
 		
  'Cs1v&&'s*   <D A>D 4D 	D/D*$D/*D/zprompt.backgroundc                 V   t        ||       \  }|r|S |j                  dd      |j                  dd      cst        | dd      S dt        j                         j
                  d d  fd}t        j                  |d	
      j                          t        | di      S )Nr   r   r    text requiredbg_r  c                     t        t                    } 	 ddlm}  |d
i t	        d         j                        }t        dt        |t              r|j                  dt        |            n
t        |      d       t        |        y # t        $ r}t        dd	| d       Y d }~-d }~ww xY w# t        |        w xY w)Nr   r   r~  rN  )user_messager  zbackground.completers
  r  r   error: r   )r  r;  r  r  r8  r
  r  r  r   r   r6   r5   r  )r
  r  r  r  r  r#  r  r   s       rD   r   z_.<locals>.runf+  s    -g<;PQ	3) *77+;WE!    %& &fd3 

#3S[A [& #>2  	%#wqc]; 	 #>2s*   A0B 	B;B61B> 6B;;B> >CTr   r  )
r  r   r  rt  ru  rv  r   r   r   ra  )r   r  r  r   r  r#  r  r   s       @@@@rD   r  r  \+  s    %LGS

::fb)6::lB+GLD&C//DJJL$$Ra()*G3@ C-335sY())r   zpreview.restartc                   	
 t        ||       \  }|r|S t        |j                  d      xs d      j                         }t        |j                  d      xs d      j                         }t        |j                  d      xs d      j                         }|st	        | dd      S dt        j                         j                  d d  |j                  d	d      t              	t        	      }d
j                  d ddd| d|xs d d|rd| nd|rdnd|rdnd ddddddddddddddfD              	 |r<t        j                  j                  t        j                  j                  |            nd

r!t        j                  j                  
      sd
	
fd }t#        j$                  |d!"      j'                          t)        | d#i      S # t         $ r d
Y Jw xY w)$Nr  r   r   rk  rV  zurl requiredpreview_r  r  r   c              3   $   K   | ]  }|r| 
 y wr   r   )r  r   s     rD   r  z_.<locals>.<genexpr>+  s      8 ; 	r  z8The desktop preview pane cannot load a local server URL.zPreview URL: zCurrent working directory: r	  zPreview console:
uC  The conversation history above is from the user's main session — including the commands you (the assistant) previously ran to start servers, edit files, or check ports. Use it to figure out exactly which server should be running at this Preview URL. The user did not start a brand new task; recover what they had working.zPRestart exactly the app intended for the Preview URL, not Hermes Desktop itself.zcThe Preview URL and port are the target. Preserve that target unless you conclude it is impossible.zIf the prior conversation shows a specific command that bound this URL/port, prefer re-running THAT exact command (in the same cwd) over guessing a new one.zFirst inspect what process, if any, owns the Preview URL port. If a stale server exists, inspect its cwd and prefer that cwd over the Hermes/Desktop process cwd.zThe Current working directory is only a hint. Do not assume it is the preview app root when the port owner or files indicate another root.zIf the console shows a module-script MIME error for src/main.tsx or similar, a static server is serving source files. Do not restart python -m http.server or any dumb static server for that app.zFor module-script MIME failures, inspect package.json/vite config in the candidate app root and start the real dev server/bundler (for example npm/pnpm/yarn dev) so module transforms happen.zBefore declaring success, verify the Preview URL responds with the intended app, not Hermes Desktop. If it serves Hermes/Desktop UI or another unrelated app, stop that process and report failure.z8Do not modify files. Do not ask the user unless blocked.z@Prefer existing project scripts or commands when they are clear.z:If a stale process owns the needed port, handle it safely.zOStart long-running servers detached/in the background, then return immediately.zLDo not run a foreground dev server command that blocks this background task.zaKeep the final response short: what command/server was started, or why it could not be restarted.c                     t        
xs t                    } 	 ddlm} ddlm} 
r |d
i       	rdt        	       dnd}t        d	d
| d        |di t        d         t              j                  	xs d       }t        |t              r|j                  dt        |            n
t        |      }t        d|d       	 ddlm}  |       t#        |        y # t        $ r}t        dd| d       Y d }~<d }~ww xY w# t        $ r Y @w xY w# 	 ddlm}  |       n# t        $ r Y nw xY wt#        |        w xY w)NrZ  r   r~  r  r   z (with z$ parent-session messages of context)r   rJ  zStarting hidden restart agentr\  rN  )r[  r  rp
  rs
  zpreview.restart.completer]  )clear_task_env_overridesr   )r  r;  r  r  r  r  r  r  r;  rS  r
  r  r   r   r6   r5   rb  r  )r
  r  r  history_noter  r   r  rb  r  parent_historypreview_cwdr  r#  r  s           rD   r   z_.<locals>.run+  s    .gK<`<X_K`b,	3)G+Ge[5IJ " #n-..RS 
 *#/L\N-[\
  1''2BGL,VW= #%3%;t    fd+ 

+S[9[ 
 ,f'SW6XYH(1 #>2  	*#wqc]; 	  	H(1 ">2s`   B<C4 D 4	D=DD, DD, 	D)(D),E.D=<E=	E	EE		ETr   r  )r  r6   r   r7   r  rt  ru  rv  rC  r   r*   r,   r.   r  r  r  r5   r   r   r   ra  )r   r  r  r  r   rk  has_historyr   r  rd  re  r  r#  r  s           @@@@@@rD   r  r  +  s   %LGS


fjj%2
&
,
,
.C
fjj%2
&
,
,
.C&**Y'-2.446GC~..))"1-./GZZb)F-g6N~&KYY  GC5!)#*<)=>.5 	*2Br  V^q k p Y Q M RFNH]Zo5
 FFBEbggoobgg&8&8&=>2rww}}[9K03 03d C-335sY())m  s   A#G! !G/.G/allow_expiredc                l   |j                  dd      }t        5  t        j                  |      }|s5|r|rt        | ddi      cd d d        S t	        | dd| d      cd d d        S |\  }}|j                  |d      t
        |<   |j                          d d d        t        | ddi      S # 1 sw Y   xY w)	Nr8  r   rN  expiredr[  zno pending z requestr   )r   rx  rS   ra  r  rU   r^  )r   r  rw  rh  r  r  r  rz  s           rD   _respondrk  +  s    

<$A	 Q39 56	 
 T[X#>?  2jjb)
 sXt$%% s   )B*B*&.B**B3zclarify.respondc                     t        | |d      S )Nr|  rk  r   r  s     rD   r  r  ,  s    C**r   zterminal.read.respondc                     t        | |d      S )Nr   rm  rn  s     rD   r  r  ,  s     C((r   zsudo.respondc                      t        | |dd      S )NpasswordTrg  rm  rn  s     rD   r  r  ,  s    C4@@r   zsecret.respondc                      t        | |dd      S )NrE  Trg  rm  rn  s     rD   r  r  ,  s    C==r   zapproval.respondc                    t        ||       \  }}|r|S 	 ddlm} t        | d ||d   |j	                  dd      |j	                  dd      	      i      S # t
        $ r }t        | d
t        |            cY d }~S d }~ww xY w)Nr   r	  r  r   choicerl  r  Fr	  i  )r  rv  r	  ra  r   r5   r  r6   )r   r  r#  r  r	  r  s         rD   r  r  !,  s    %LGS

';4M*JJx0 &

5% 8	
 		
  'Cs1v&&'s   ?A 	A>A93A>9A>z
config.setc                  (  7 |j                  dd      |j                  dd      }}t        j                  |j                  dd            }|dk(  rd	 |st        | dd      S |r|j                  d      rt        | d	d
      S ddlm}  ||      }|j
                  }|j                  d      \|j                         sL|j                  dd      }t        ||       t        ||       }	|	r|	S |j                  d      t        | dd      S t        |j                  dd      ||t        |j                  dd            |      }
n*t        ddd i|t        |j                  dd                  }
t        | ||
d   |
d   |
j                  dd      |
j                  dd      |
j                  dd      d      S |dk(  rt        |xs d      j                         j                         7|r|j                  d      nd }|t        |dd       dk(  }n)||j                  d      	|d   dk(  }nt!               dk(  }7dv rt        | ||rdd!      S d d!      S 7d"v r|rd nd}n7d#v rd}n7d$v rd }nt        | dd%|       S d }|dk(  rdd&lm} |t        |dd       }nH|xs i j                  d'      xs i }t'        |t(              r|j                  d      nd xs
 t+               }|st        | dd(      S  ||      }|t        | dd)      S ||dk(  rdnd|d<   nt-        d*|       ||dk(  rdnd |_        t)        t        |d+i       xs i       }|j1                  dd        |j1                  d,d        |dk(  r|j3                  |       ||_        t7        |       t9        d-|j                  dd      t;        ||             t        | ||d!      S |d.k(  rut        |xs d      j                         j                         77d/v rt        | |t=               d!      S 7d0vrt        | dd1|       S t-        d27       t        | |7d!      S |d3k(  rg d4}|r|j                  d5t?                     n	t?               }|r@|d6k7  r;t        |      j                         j                         }||vr6t        | dd7|       S 	 |jA                  |      }||d9z   tE        |      z     }t-        d:|       |r"||d5<   |j                  d      }|
|d3k(  |_#        t        | ||d!      S |d;v rt        |xs d      j                         j                         77tH        vrt        | dd<| d=      S t-        d>7       tK        t        jM                               D ]0  \  }}|j                  d      }|t9        d-|t;        ||             2 t        | d>7d!      S |d?k(  rLt        |j                  d      xs d      j                         j                         }	 dd@l'm(}m)}m*} t        |xs d      j                         j                         7dAt        dBt        f7fdC}|dDk(  rddEl'm+} tY               }t'        |t(              r|j                  dF      nd } t'        | t(              si }  || j                  dGdH            dIk(  }! ||!      }"t-        d>|"rdIndH       |"rdJndK}tK        t        jM                               D ]0  \  }}|j                  d      }|t9        d-|t;        ||             2 t        | ||dDdL      S |rk ||dM         }! ||!      }"|"r ||dM          dJ}n ||dM          dK}|j                  d      }|t9        d-|j                  dd      t;        ||             njt[        t\        j^                  j                  dN            }! ||!      }"|"rdJt\        j^                  dN<   dJ}n"t\        j^                  j1                  dNd        dK}t        | ||ddL      S |dOk(  r	 ddPl0m1}# t        |xs d      j                         j                         }$t        |j                  d      xs d      j                         j                         }|dDk(  }%|$dQv rtY               }t'        |j                  dR      t(              r|j                  dR      ni }&t'        |&j                  dS      t(              r|&j                  dS      ni }'dT|&dU<   dV|'dW<   |'|&dS<   |&|dR<   te        |       |rdT|dU<   t        | |dXd!      S |$dYv rtY               }t'        |j                  dR      t(              r|j                  dR      ni }&t'        |&j                  dS      t(              r|&j                  dS      ni }'d|&dU<   dZ|'dW<   |'|&dS<   |&|dR<   te        |       |rd|dU<   t        | |d[d!      S |$d\v rtY               }t'        |j                  dR      t(              r|j                  dR      ni }&t'        |&j                  dS      t(              r|&j                  dS      ni }'dT|&d]<   dV|'dW<   |'|&dS<   |&|dR<   te        |       t        | |d^d!      S |$d_v rtY               }t'        |j                  dR      t(              r|j                  dR      ni }&t'        |&j                  dS      t(              r|&j                  dS      ni }'d|&d]<   d`|'dW<   |'|&dS<   |&|dR<   te        |       t        | |dad!      S  |#|$      }(|(t        | ddb|       S |%s|!t-        dc|$       ||j1                  ddd        n|(|dd<   |rP|j                  d      ?|(|d   _3        t7        |       t9        d-|j                  dd      t;        |d   |             t        | ||$d!      S |dek(  rt        |xs d      j                         j                         }|th        vrt        | ddf|       S tY               }t'        |j                  dR      t(              r|j                  dR      ni }&t'        |&j                  dS      t(              r|&j                  dS      ni }'||&de<   tj        D ]  })||'|)<   	 |'|&dS<   |&|dR<   te        |       t        | ||d!      S |jm                  dg      r?|jo                  dhd9      d9   })|)tj        vrt        | ddi|)       S tY               }t'        |j                  dR      t(              r|j                  dR      ni }&t'        |&j                  dS      t(              r|&j                  dS      ni }*t        |xs d      j                         j                         }|s6|*j1                  |)d        |*|&dS<   |&|dR<   te        |       t        | |dd!      S |th        vrt        | ddf|       S ||*|)<   |*|&dS<   |&|dR<   te        |       t        | ||d!      S |djk(  rzt        |xs d      j                         j                         }tq        h dk      }+||+vrt        | ddl|       S t-        dm|       t-        dn|d^k(  rdVnd`       t        | ||d!      S |dok(  rt        |xs d      j                         j                         7tY               },t'        |,j                  dR      t(              r|,j                  dR      ni }-t        |-j                  dpd            }.7d"v r|. }/n 7dqk(  rdT}/n7dIk(  rd}/nt        | ddr|       S t-        ds|/       t        | ||/rdqd!      S dId!      S |dtk(  rt        |xs d      j                         j                         7tY               j                  dR      }&t'        |&t(              r|&ni }-ts        |-j                  dudv            }!7d"v r
|!dIk(  rdvndI}n#7dqk(  rdv}n7tt        v r7}nt        | ddw|       S t-        dx|       t        | ||d!      S |dyk(  r|dn
t        |      j                         j                         7tY               }t'        |j                  dR      t(              r|j                  dR      ni }&tw        |&      }!7d"v r
|!dIk(  rdzndI}n"7tx        v r
tx        7   }nt        | dd{|       S t-        d||       t        | ||d!      S |d}k(  rt|dn
t        |      j                         j                         77tz        vr&t        | dd~7ddj}                  tz                     S t-        d7       t        | |7d!      S |dv rt        |xs d      j                         77st        | dd      S t\        j~                  j                  t\        j~                  j                  7            }0t\        j~                  j                  |0      st        | dd7       S t-        d|0       |0t\        j^                  d<   t        | d|0|0t        |0      d      S |dv r	 tY               }|dk(  r-|dk(  r|j1                  dd        d}n||d<   |}te        |       n|dk(  rg|j                  dd      }1t        t        |xs d      |      \  }2}3t-        d|2       t-        d|3       t        |xs d      }t        |1||3|2      \  }4}5n+t-        d| |       |}|dk(  rt9        ddt                      ||d!}6|dk(  r4|6d<   5|5|6d<   t        | |6      S t        | dd|       S # t        $ r }t        | dt        |            cY d }~S d }~ww xY w# tB        $ r d8}Y w xY w# t        $ r }t        | dt        |            cY d }~S d }~ww xY w# t        $ r }t        | dt        |            cY d }~S d }~ww xY w# t        $ r }t        | dt        |            cY d }~S d }~ww xY w)Nrw  r   rE  r  r   r	  ra  r  r[  uD   session busy — /interrupt the current turn before switching modelsr   )r[  rN  r  r
  rU  F)rU  rW  )rU  r   rs  rt  ry  r#  )rw  rE  r   rs  rt  ry    r  r  r  r7  >   rN  r  )rw  rE  >   r   toggle>   r  r  >   r  r  zunknown fast mode: )resolve_fast_mode_overridesr5  z3fast mode is not available without a selected modelz)fast mode is not available for this modelzagent.service_tierr6  speedrP  busy>   r   rN  >   r   r   r  zunknown busy mode: zdisplay.busy_input_moder  )r  r  r  r  r5  cyclezunknown verbose mode: r   r   zdisplay.tool_progress>   r  approvals.modezunknown approval mode: z; pick one of manual|smart|offr|  r  )r  r  r  r  r   c                     dv rydv ry|  S )N>   r  r  r  r  T>   r  r  r  r  Fr   )r  r  s    rD   _resolve_togglez_.<locals>._resolve_toggle-  s#    4455 "{"r   rx  r  r  r  r  r  r  r  )rw  rE  ry  r   HERMES_YOLO_MODEr  r  >   r  showr   sectionsTr  rd   r_   r  >   r  hiderc   r  >   r  r  reasoning_fullr  >   clampshortcollapsere   r  zunknown reasoning value: zagent.reasoning_effortr6  details_modezunknown details_mode: zdetails_mode.r  zunknown section: thinking_mode>   r  re   r
  zunknown thinking_mode: zdisplay.thinking_modezdisplay.details_modecompacttui_compactr  zunknown compact value: zdisplay.tui_compact	statusbartui_statusbarr  zunknown statusbar value: zdisplay.tui_statusbarmouser  zunknown mouse value: zdisplay.mouse_tracking	indicatorzunknown indicator: z; pick one of |zdisplay.tui_status_indicator>   r   workdirterminal.cwdr]  r;  r  r  )rw  rE  r   r6  >   r  r  r  r  clearcustom_promptr  zdisplay.personalityzagent.system_promptr  zdisplay.r  zskin.changedhistory_resetrH  unknown config key: )Gr   rQ   r  rz  r[  r  r7   r  r  r  r   ra  r5   r6   r  r   r  r  rx  r  r   r  r  r  r(  rG  r6  r  r  rR  r  r  r  r>  r  r.  r  r_  rf  rv  r  r  r  r  r  r   r,   r  r=  r  r_  r  _DETAIL_MODES_DETAIL_SECTION_NAMESr  r  r!  r  r  r  r  rD  r*   r.   r  r  r  r5  r
  r  r  )8r   r  rw  rE  r#  r[  rW  r  r  init_errr  r  rN  current_fastnvr  rx  ro  session_overridecurrent_overridesr{  rS  r3  r-  rb  ry  r  r  r  r~  r  r  apprr  enabler  argglobal_scoper   r  r  sectionsections_cfg
allowed_tmcfg0d0cur_bnv_br   r
  pnamer  r  rH  r  r  s8                                                          @rD   r  r  :,  s   E2&

7B(?CmmFJJ|R89G
g~<	+C'=>> ;;y)^ 
 O9%@$0$B$B!;;w'/8I8O8O8Q!'L"!=J&z7;*7C8H'{{7+3#C/LMM,JJ|R0,0

#<eD- ". -dO,0

#<eD-	 #G_%i0(.

3Eu(M'-zz2CR'H#ZZ;
 
 f}%+2$$&,,.(/G$T"5.$?:ML W[[1O%P%\ ##ABjPL-/:=L*fK BJK 
 . )vBN"B%%BT%8#@AA	<E &ugt<
 %,Mr#6#67G#H#NB  ""2D9 %((1 & $%	 
  I 
 4LAI ?   !Fl
 23 2B7/1V|E $WU4G%L%RPR S!!.$7!!'40V|!((3&7E#)'2

<,eW-
 3b122
f}%+2$$&,,.. sC2G2IJKK55T%8#@AA3S93c233
i0  KK,.F.HI)+ 	
 Ug%U!!#))+BC)?w'GHHkk#& a3u:-.B126,.G()KK(E (*i%3b122
11%+2$$&,,.o%)%0NO  	*C0ioo/0 	GICHHW%E nc=+EF	G 3 03?@@
f} FJJw'495;;=CCEA	+  ekr"((*002C# #$ #  Ck/9#t/Dsww{+$!$-D2488FH3MNRWW(1
 ""2VER"S!%ioo&7!8 OIC HHW-E(nc=3MNO 3b8 LMM1'-2HI(1'(>?B()?@BG,$&

<4%eW5 *"**..9K*LM(158BJJ12BJJNN#5t<BsC"yIJJ kj	+?ekr"((*002C

7+1r288:@@BE H,Ln$k*4SWWY5G*NCGGI&TV 
 "'++j"94@ KK
+ 
 -1()'1$&.
#!(I#04G,-3f =>>o%k*4SWWY5G*NCGGI&TV 
 "'++j"94@ KK
+ 
 -2()'/$&.
#!(I#05G,-3f =>> o%k*4SWWY5G*NCGGI&TV 
 "'++j"94@ KK
+ 
 -1()'1$&.
#!(I#3f =>>44k*4SWWY5G*NCGGI&TV 
 "'++j"94@ KK
+ 
 -2()'2$&.
#!(I#3g >??+C0F~C)B5''JKKw!":C@&KK ;TB 8>347;;w/;4: 1-g6"JJ|R0!''"2G<
 sC#677 n"##%++-]"T%;E7#CDDk(237793Et(L#'')$RT'1'++j2I4'PGKK
#VX 	 #%, 	#G "HW	#&
 I#3b122
~~o&
 ))C#A&//T%6wi#@AAk(237793Et(L#'')$RT'1'++j2I4'PGKK
#VX 	 "##%++-Wd+".GJ$C	NcNsC"566]"T%;E7#CDD "W*
 I#3b122
o"##%++-AB
ZT%<UG#DEE126"",JK	
 3b122
i%+2$$&,,.{$.txx	/BD$ITXXi rRVVM512. 9DD[DE\DT%<UG#DEE/63ddFGGFGG
k%+2$$&,,.+//),"7D1Wr#BFF?E$BC. !U*BD[B$$BT%>ug#FGG1263b122
g~ ]rE
99;AACk(237793Et(L#'')$RT)'2. !U*B++(-BT%:5'#BCC2B73b122
k ]rE
99;AAC''%cWN388DU;V:WX 
 	8#>3c233
00%+2$$&T>22ggoobgg0056ww}}S!T%Gu#MNN.#.%(

>""SH[\_H`a
 	

 //	++ChG#GGOT2B+0C(B#% **\26$9#ekr:JC$P!z!"7?!"7D&)&CWj%'#t "HSE"2E:&=."ln=,Dm#(5_%##'DLsD>! T1#788s  	+T3q6**	+d  J  	+T3q6**	+Z  	+T3q6**	+d  	+T3q6**	+s  AL> !AL> A(AL> *AL> B,AL> ;AM* D AM< (AM< =C&AM< +DAN( B&AN( )BAN( 	BAN( )AN( B
AN( H9C4AO L>	AM'MAM"MAM'M"AM'M*AM9M8AM9M<	AN%NAN NAN%N AN%N(	AON1AOOAOOAOO	AO=OAO8O2AO=O8AO=  i    c                       e Zd ZdZy)
_NoProjectzHRaised inside a projects handler when ``params['id']`` resolves to None.N)r9   r   r   r   r   r   rD   r  r  .  s    Rr   r  c                     ddl m} |j                  | d      D cg c]  }|j                          c}|j	                  |       dS c c}w )Nr   r  T)include_archived)projects	active_id)r  r  list_projectsto_dictget_active_id)r  r  r  s      rD   _projects_payloadr  .  sG    - +.*;*;DSW*;*XYQQYY[Y&&t, Ys   Ac                       fd}|S )a4  Register a projects RPC, injecting (pdb, conn) and unifying error mapping.

    Every project CRUD handler opened the per-profile DB, mapped a missing id to
    5062, bad args to 5063, and everything else to 5061. This collapses that
    boilerplate so each handler is just its one meaningful operation.
    c                 J     t              dt        dt        f fd       }|S )Nr  r   c                 `   	 ddl m} |j                         5 } | |||      cd d d        S # 1 sw Y   y xY w# t        $ r t	        | t
        d      cY S t        $ r$}t	        | t        t        |            cY d }~S d }~wt        $ r$}t	        | t        t        |            cY d }~S d }~ww xY w)Nr   r  zno such project)r  r  r  r  r  _E_NO_PROJECTr>  _E_PROJECT_ARGr6   r5   _E_PROJECTS)r   r  r  r  r  r  s        rD   r  z4_projects_method.<locals>.decorator.<locals>.handler.  s    
69((* 6dc6356 6 6 CC0ABB 9CQ88 6Cc!f556sG   : .	: 7: : B-B-A=7B-=B-	B("B-(B-)r  r   )r  r  rI   s   ` rD   	decoratorz#_projects_method.<locals>.decorator.  s.    		6 	6$ 	6 
	6 r   r   )rI   r  s   ` rD   _projects_methodr  .  s    " r   c                 r    | j                  |t        |j                  d      xs d            }|t        |S )z@The project named by ``params['id']`` (or raise ``_NoProject``).r   r   )get_projectr6   r   r  )r  r  r  projs       rD   _require_projectr  .  s5    ??4VZZ%5%;!<=D|Kr   zprojects.listc                 ,    t        | t        |            S r   )ra  r  r   r  r  r  s       rD   r  r  .  s    s%d+,,r   zprojects.getc           	      P    t        | dt        |||      j                         i      S )Nr  )ra  r  r  r  s       rD   r  r  .  s'    sY 0dF C K K MNOOr   zprojects.createc                    |j                  |t        |j                  d      xs d      |j                  d      |j                  d      xs g |j                  d      |j                  d      |j                  d      |j                  d      |j                  d	      
	      }|j                  d      r|j                  ||       |j	                  ||      }t        | d|r|j                         i      S d i      S )NrI   r   r  foldersr  r  iconr  
board_slug)rI   r  r  r  r  r  r  r  user  )create_projectr6   r   
set_activer  ra  r  )r   r  r  r  pidr  s         rD   r  r  .  s    


F#)r*ZZ

9%+ZZ/JJ}-ZZjj!::l+  
C zz%tS!??4%DsY$ABBDABBr   zprojects.updatec                 b   t        |||      }|j                  ||j                  |j                  d      |j                  d      |j                  d      |j                  d      |j                  d             t	        | d|j                  ||j                        j                         i      S )NrI   r  r  r  r  )rI   r  r  r  r  r  )r  update_projectr   r   ra  r  r  r   r  r  r  r  s        rD   r  r  .  s    Cv.DZZJJ}-ZZjj!::l+   sYdgg > F F HIJJr   zprojects.add_folderc                 N   t        |||      }|j                  ||j                  t        |j	                  d      xs d      |j	                  d      t        |j	                  d                   t        | d|j                  ||j                        j                         i      S )Nr.   r   r9  
is_primary)r9  r  r  )	r  
add_folderr   r6   r   r   ra  r  r  r  s        rD   r  r  .  s    Cv.DNNFJJv$"%jj!

<01   sYdgg > F F HIJJr   zprojects.remove_folderc           	          t        |||      }|j                  ||j                  t        |j	                  d      xs d             t        | d|j                  ||j                        j                         i      S Nr.   r   r  )r  remove_folderr   r6   r   ra  r  r  r  s        rD   r  r  .  sc    Cv.DdDGGSF);)Ar%BCsYdgg > F F HIJJr   zprojects.set_primaryc           	          t        |||      }|j                  ||j                  t        |j	                  d      xs d             t        | d|j                  ||j                        j                         i      S r  )r  set_primaryr   r6   r   ra  r  r  r  s        rD   r  r  .  sa    Cv.DOOD$''3vzz&'9'?R#@AsYdgg > F F HIJJr   zprojects.archivec                     t        |||      } |j                  d      r|j                  n|j                  ||j                         t        | t        |            S )Nrestore)r  r   restore_projectarchive_projectr   ra  r  r  s        rD   r  r  .  sO    Cv.DJFJJy1Ss7J7JDRVRYRYZs%d+,,r   zprojects.deletec                 ~    t        |||      }|j                  ||j                         t        | t	        |            S r   )r  delete_projectr   ra  r  r  s        rD   r  r  /  s7    Cv.DtTWW%s%d+,,r   zprojects.set_activec                     |j                  ||j                  d      rt        |||      j                  nd        t	        | d|j                  |      i      S )Nr   r  )r  r   r  r   ra  r  r  s       rD   r  r  /  sK    NN46::dCS)#tV<??Y]^s[#"3"3D"9:;;r   r   c                    t        |j                  d      r.dt        |j                  d      xs d      j                         ini       }|j	                  ||      }t        | |r|j                         nd |t        |      d      S )Nr   r   )r  r   r6  )r  r   r6   r7   r  ra  r  r5  )r   r  r  r  r   r  s         rD   r  r  /  ss    
6::V[K\5#fjj&7&=2">"D"D"FGbd
eCc*Ds$DXkloXpqrrr   c                    | syddl m} t        j                  j	                  |       }t        j                  j	                  t        j                  j                  d            }t        j                  j	                  t         |                   }||k(  xs) ||k(  xs" |j                  |t        j                  z         S )u   A git root we never auto-surface as a project: the bare home dir or
    anything under HERMES_HOME (~/.hermes by default) — config/sessions/skills,
    not a workspace. User-created projects pointing there are still honored.Tr   rU  ~)	r=  r
   r,   r.   realpathr  r6   r  r2  )r  r
   realr  r   s        rD   _is_repo_junkr  /  s     077D!D77BGG..s34D''""3'8#9:K4<W4;.W$//+PRPVPVBV2WWr   c                    | syddl m} t        j                  j	                  t        j                  j                  |             }t        j                  j	                  t        j                  j                  t        j                  j                  d                  }t        j                  j	                  t        j                  j                  t         |                         }||k(  xs ||k(  S )aU  A non-git cwd that should stay in flat Recents rather than auto-group.

    Unlike discovered git roots, an explicitly selected descendant of
    HERMES_HOME may be an intentional prose/data workspace. The pre-Projects
    desktop surfaced every such cwd, so exclude only the two broad defaults
    that would create catch-all projects.
    Tr   rU  r  )r=  r
   r,   r.   normcaser  r  r6   )r   r
   r  r  r   s        rD   _is_session_cwd_junkr  %/  s     077BGG,,S12D77BGG,,RWW-?-?-DEFD''""277#3#3C8I4J#KLK4<.4;..r   r  backfillr  c          	      
   t         i dt        dt        ffdt        | j	                               }t        j                  d |D               i }|D ]  }t        |j                  d      xs d      }t        |      }|s/|||<    |      r= |      }|dxx   t        |j                  d      xs d      z  cc<   t        |d	   t        |j                  d	      xs d            |d	<    |r	 | j                  |       	 ddlm dfd}	|	 |	|       n!j%                         5 }
 |	|
       ddd       t'        j)                         d d      }|D ]D  }|d   xs8 t*        j,                  j/                  |d   j1                  d            xs |d   |d<   F |S # t        $ r t        j                  d
d       Y w xY w# 1 sw Y   xY w# t        $ r t        j                  dd       Y w xY w)u  Merge filesystem-scanned repos (cached) with session-derived repo roots.

    Repo-first: the disk scan (persisted by `projects.record_repos`) surfaces
    repos even with zero hermes sessions. Session-derived roots cover repos
    outside the scan roots. Both are junk-filtered (hermes home subtree + bare
    home) and carry their session totals for the overview.

    ``conn`` reuses an already-open projects.db connection (the tree path holds
    one); ``backfill`` persists resolved roots back onto session rows — kept off
    the per-turn tree path (grouping uses the live git resolver regardless) and
    done only on the explicit discover/record refresh.
    r  r   c                 2    j                  | | dddd      S )Nr   r   r]   )r  r9  r   r  )rf  )r  reposs    rD   _aggz%_discover_repos_payload.<locals>._aggH/  s     tba`c&deer   c              3   X   K   | ]"  }t        |j                  d       xs d       $ yw)r   r   N)r6   r   r  r  s     rD   r  z*_discover_repos_payload.<locals>.<genexpr>P/  s"     CQQUU5\/R0Cs   (*r   r   r   r   r  zfailed to backfill repo rootsTr&  r  Nc           	      "   j                  |       D ]z  }t        |j                  d      xs d      }|r |      r, |      }|j                  d      r|d   |d<   t        |d   t	        |j                  d      xs d            |d<   | y )Nr  r   r9  r  	last_seenr   )list_discovered_reposr6   r   rF  r  )r  r  r  aggr  _is_junkr  s       rD   _readz&_discover_repos_payload.<locals>._readi/  s    2215 a599V,23x~4j99W%#(>CL%(]);U599[CYC^]^=_%`M"ar   z$failed to read discovered repo cachec                     | d   S )Nr  r   r  s    rD   r   z)_discover_repos_payload.<locals>.<lambda>{/  s    q/? r   r	  r9  z/\r   )r  r6   r   r_  distinct_session_cwdsr   
warm_rootsr   r  r  rF  r  backfill_repo_rootsr5   r  r*  r  r  r  r!  ra  r,   r.   basenamer   )rk  r  r  cwd_rowscwd_to_rootrl  r   r  r  r  ownr  r  r  r  r  r  s                @@@@rD   _discover_repos_payloadr  8/  s    HEf3 f4 f
 B,,./H C(CC"$K 
Y#''%.&B',S1CD>4jJ3swwz27a88 ]!3U377=;Q;VUV5WXM
Y 	I"";/L1	a $K$$& #c

 %?
NC ZwZY277#3#3AfI4D4DU4K#LYPQRXPY'
ZJ;  	ILL84LH	I*  L;dKLs<   9F- )G 4	G=G - GGGG  HHr   c                     	 t               }|t        | dg i      S t        | dt        |      i      S # t        $ r }t	        | dt        |            cY d}~S d}~ww xY w)uO   Repos for the desktop overview: scanned-from-disk (cached) ∪ session-derived.Nr  r  )ra  ra  r  r5   r  r6   )r   r  rk  r  s       rD   r  r  /  s_    'Y:sWbM**3"9""=>?? 'Cs1v&&'s   3 3 	AAAAr   c                 P   	 ddl m} g }|j                  d      xs g D ]w  }t        |t              r|j                  |df       't        |t              s8|j                  d      sJ|j                  t	        |d         |j                  d      f       y |j                         5 }|j                  ||d       ddd       t               }t        | d|t        |      i      S g i      S # 1 sw Y   3xY w# t        $ r }t        | d	t	        |            cY d}~S d}~ww xY w)
zPersist git repo roots found by the client's filesystem scan, then return
    the merged repo list. The native crawl runs on the desktop (local fs); this
    caches the result so later reads are instant instead of re-walking disk.r   r  r  Nr  r9  T)r  r  )r  r  r   r  r6   r  r   r  record_discovered_reposra  ra  r  r5   r  )r   r  r  pairsr&  r  rk  r  s           rD   r  r  /  s   
'1.0JJw'-2 	ED$$dD\*D$'DHHV,<c$v,/'1BCD		E   " 	Cd''eT'B	C Y3"9""=XYYUWXYY		C 	C
  'Cs1v&&'sI   AC< C< )A C< )C0>*C< )C< 0C95C< <	D%D D% D%r9  r  c                    i d| j                  d      d| j                  d      d| j                  d      d| j                  d      d| j                  d      d| j                  d      xs dd| j                  d      d	| j                  d	      xs | j                  d      xs dd
| j                  d
      dt        | j                  d            d| j                  d      xs dd| j                  d      xs dd| j                  d      xs dd| j                  d      xs dd| j                  d      ddd| j                  d      | j                  d      | j                  d      dS )a&  Project a SessionDB row to the minimal shape the sidebar renders.

    Keeps the fields the grouping needs (cwd / git_branch / git_repo_root) plus
    everything ``SidebarSessionRow`` reads, and drops the heavy columns
    (system_prompt, model_config, ...) so the tree payload stays lean.
    r   _lineage_root_idr  r  r|  ry  r   ended_atr  rB  archivedrB  tool_call_countr  r  r   r
  Fr   
git_branchgit_repo_root)r  r	  )r   r   r  s    rD   _project_tree_rowr
  /  s   aeeDkAEE"45 	QUU#67 	w 	155# 	aeeL).Q 	AEE*% 	quu]+Gquu\/BGa 	!%%/ 	Dz*+ 	/41 	155!238q  	n-2!" 	/41#$ 	w%& 	U'( 	quuU|)* eeL)/- r   session_limitinclude_discoveredc          	         | j                  |ddddt        d      }|D cg c]  }t        |       }}t        j                  d |D               ddlm} |j                         5 }|j                  |      D cg c]  }|j                          }	}|j                  |      }
|rt        | |d      ng }d	d	d	       |	
fS c c}w c c}w # 1 sw Y   xY w)
u  Gather (sessions, projects, discovered_repos, active_id) for build_tree.

    ``include_discovered`` is the zero-session-repo overview tier; the entered
    view (drill-in) skips it entirely — it only needs the project it's showing,
    which already has sessions — avoiding the distinct-cwd scan + git probes on
    that per-turn path. One projects.db connection serves both reads.
    r   Tr   F)r  offsetr  min_message_countinclude_childrenexclude_sourcesr  c              3   J   K   | ]  }|j                  d       s|d      yw)r   Nr  r  r  s     rD   r  z'_project_tree_inputs.<locals>.<genexpr>/  s     DaquuU|5Ds   #
#r  r  N)r"  _PROJECT_TREE_EXCLUDED_SOURCESr
  r   r  r  r  r  r  r  r  r  )rk  r  r  r$  r  r   r  r  r  r  r  
discovereds               rD   _project_tree_inputsr  /  s       !6 ! D /33!!$3H3 D8DD-				 j$),):):4)@AAAIIKAA%%d+	Oa,RdUKgi
	j Xz944 4 Bj js#   C'C;C
%C
CCpreview_limithydratec          
          ddl m} t        | ||      \  }}}}	|j                  |||t        ||t
        t              }
|
|	fS )zOGather inputs and run the one authoritative builder. Returns (tree, active_id).r   )project_tree)r  )r  r  is_junk_rootis_junk_cwd)tui_gatewayr  r  
build_tree_resolve_cwd_gitr  r  )rk  r  r  r  r  r  r   r  r  r  trees              rD   _build_project_treer!  /  s]     )0D
M.@1-Hh
I ""#"( # 	D ?r   rx   c           
      V   	 t               }|t        | g dg d      S t        |t        |j	                  d      xs d      dt        |j	                  d      xs d      d	      \  }}t        | |d
   ||d   d      S # t
        $ r }t        | dt        |            cY d}~S d}~ww xY w)a=  Authoritative project overview: project -> repo -> lane structure with
    counts + a few preview sessions per project, plus the flat set of session
    ids claimed by any project (so the desktop excludes them from flat Recents).
    Lanes carry no session rows here; drill-in uses ``projects.project_sessions``.
    N)r  r  scoped_session_idsr  r(  Fr  i  Tr  r  r  r  r  r#  r  )ra  ra  r!  r  r   r5   r  r6   )r   r  rk  r   r  r  s         rD   r  r  0  s    'Y:s$VXYZZ-fjj9>Q?fjj9ATB#
i j)	Y]^rYst
 	
  'Cs1v&&'s#   A? A A? ?	B(B#B(#B(r   c           
         	 t        |j                  d      xs d      st        | dd      S t               }|t	        | ddi      S t        |ddt        |j                  d	      xs d
      d      \  }}t        fd|d   D        d      }t	        | d|i      S # t        $ r }t        | dt        |            cY d}~S d}~ww xY w)zFully hydrated lanes (repo -> lane -> session rows) for one project,
    built from the same authoritative grouping as ``projects.tree`` so ids and
    membership match exactly. Used when the user enters a project.
project_idr   r  zproject_id requiredNr  r   Tr  r=  Fr$  c              3   4   K   | ]  }|d    k(  s|  yw)r   Nr   )r  r  r&  s     rD   r  z_.<locals>.<genexpr>50  s     J1AdGz4IQJ   r  r  )	r6   r   r  ra  ra  r!  r  r  r5   )r   r  rk  r   _activer  r  r&  s          @rD   r  r  !0  s    
'L17R8
T#899Y:sY-.. ,aSOA\Ad`d=e$
g JZ 0JDQ3D)** 'Cs1v&&'s)   ,B B 
AB 	C(C=CCz
config.getc                    |j                  dd      }|dk(  rS	 ddlm}m} t	               }|j                  dd      }t        | |t        |      dkD  r ||d         nd |       d	      S |dk(  r'ddlm} t        | t        t               |       d      S |dk(  rt               j                  d      xs i }	t        |j                  dd      xs |	j                  dd      xs d      j                         }
t!        |
rd|
ini       }t        | |t#        |      d      S |dk(  rt        | dt               i      S |dk(  r&t        | dt               j                  dd      i      S |dk(  r9t        | dt               j                  d      xs i j                  dd      i      S |dk(  rut               j                  d      xs i j                  dd      }
t        |
      j                         j%                         }t        | d|t&        v r|i      S t(        i      S |dk(  r<t        | dt               j                  d      xs i j                  d      xs di      S |dk(  rUt               }t*        j                  |j                  dd            }d }|at-        |j                  d       t.              r|j                  d       }n0|j                  d!      }t1        |d"d       }t-        |t.              r|}t-        |t.              r5|j                  d#      d$u rd}nZt        |j                  d%      xs d&      }n;|j                  d!      xs i j                  d'd      }|d$u rd}nt        |xs d&      }t3        |j                  d      xs i j                  d(d)            rd*nd+}t        | ||d,      S |d-k(  rt*        j                  |j                  dd            }d }|7|j                  d!      }|t1        |d.d       }n|j                  d/      |d/   }|
t5               }t        | d|d0k(  rd-i      S d1i      S |d2k(  rt        | dt7               i      S |d3v r	 t        | dt9               i      S |d5k(  ryt;        h d6      }t        t               j                  d      xs i j                  d5d7      xs d7      j                         j%                         }
|
|v r|
nd7}t        | d|i      S |d8k(  rt;        h d9      }t               }t        |j                  d      xs i j                  d8d      xs d      j                         j%                         }
|
|v r|
}nWt        |j                  d      xs i j                  d5d7      xs d7      j                         j%                         }|d:k(  rdnd7}t        | d|i      S |d;k(  rMt3        t               j                  d      xs i j                  d<d$            }t        | d|rd=i      S d>i      S |d?k(  rTt               j                  d      }t-        |t.              r|j                  d@dA      ndA}
t        | dt=        |
      i      S |dBk(  r0t               j                  d      }t        | dt?        |      i      S |dCk(  rGt        dDz  }	 t        | dC|jA                         r|jC                         jD                  i      S di      S t        | dEdF|       S # t        $ r }t        | d
t        |            cY d }~S d }~ww xY w# t        $ r }t        | d4t        |            cY d }~S d }~ww xY w# t        $ r t        | dCdi      cY S w xY w)GNrw  r   r  r   )list_available_providersnormalize_providerr  r   rT  )r   r  re  i  r  r|	  )r  r   r  r  r   )r   r6  r  r  r  r  r  rE  r   rF  r  tui_status_indicatorr  r  r  r  r6  rN  r  r  Fr  mediumr  r  Tr  r  )rE  r   r  r  r7  r  r  rz  >   r  r|  rv  r  >   rc   rd   re   re   r  >   r  re   r
  rd   r  r  r  r  r  r  r  r  rX  r  r	  r  )#r   r  r+  r,  r  r  ra  r  r5   r  r6   r=  r}	  r  r  r7   r  r5  r  rD  _INDICATOR_DEFAULTrQ   r  r   r   r   r  r  r  r!  r  r  r  rQ  rR  )r   r  rw  r+  r,  r   r  r  r}	  cfg_terminalr  r   normr  r#  r  rN  agent_reasoningr  
raw_effortr   r  
allowed_dmr  r  dmr  cfg_paths                               rD   r  r  ;0  s]   
**UB
C
j	+V"$EKKQ'E"8;E
Q*584I!9!;	 	 i83\!2?R?TUVV
i {z28b&**UB'L<+;+;E2+FL"MSSUcuclr:3/B3/GHII
f}39;/00
h39;???B#GHII
f}'IKOOI6<"AA&)TU
 	
 k {y)/R445KRP3x~~%%'d&77dP
 	
=OP
 	
 my{y17R<<]KUvV
 	
 kk--

< <='++&ABDI#*;;/J#K G,")%1CT"Jot4'6$&-##I.%7-11(;GxH'''*0b556H"MJU"  Z384 SWWY'-2223CTJK  	
 3&W=>>
f} --

< <=KK(E und;;<H=><%'D3DJ,>&MNNHMNN
f}3"7"9:;;
11	+sW&9&;<== nBC
+1r66~{S  UWUW 	 :%S;3"&&
oAB
k#)r..CIrJUWUW 	
 *B WWY'-222>;O #"   +B3"&&
i9;??9-388NO3"$899%899
k+//),3=gt3LGKK/RW 	 3"3C"89::
g~+//),3"9'"BCDD
g~-/	*g8??;Lx}}77T RST 
 T1#788_  	+T3q6**	+p  	+T3q6**	+j  	*sWaL))	*sT   A\ (\: 5]& 7]& 	\7\2,\72\7:	]#]]#]#&^ ?^ rt   c                     	 ddl m} t        | dt         |             i      S # t        $ r }t        | dt        |            cY d }~S d }~ww xY w)Nr   _has_any_provider_configuredprovider_configured  )hermes_cli.mainr9  ra  r   r5   r  r6   )r   r  r9  r  s       rD   r  r  0  sI    '@3.5Q5S0TUVV 'Cs1v&&'   !$ 	AAAAr   c           
         	 ddl m} ddlm} ddlm} t        |j                  d      xs d      j                         xs d} ||      }t         |             }|j                  d      xs d}t        |j                  d	      xs d      }	|s*|d
k(  r%|	dv r!t        | d||j                  d      |	dd      S |j                  d      }
t        |
      rdnt        |
xs d      j                         }t        |
      xs* |dv xs$  ||      xs t        |j                  d            }|s4t        | d||j                  d      |j                  d	      d| dd      S t        | d|j                  d      |j                  d      |j                  d	      d      S # t        $ r"}t        | dt        |      d      cY d}~S d}~ww xY w)a  Strict provider check: does the configured/default model actually resolve to a usable runtime?

    Unlike setup.status (which returns True if ANY provider auth state is
    discoverable, including indirect fallbacks like ``gh auth token`` for
    Copilot), this runs the same resolve_runtime_provider() call the agent
    uses on session creation. It returns ok=False with the auth error message
    when the user's configured model cannot actually be served, so UIs can
    surface onboarding before the user submits a doomed prompt.
    r   r]  )has_usable_secretr8  r  r   Nrb  rB  bedrock>   iam-roleaws-sdk-default-chainFr   z!No Hermes provider is configured.)r   r  r   rB  r   rG  >   aws-sdkr  r   z No usable credentials found for r  T)r   r  r   rB  )r   r   )r  r^  rr  r?  r<  r9  r6   r   r7   r   ra  r|  r5   )r   r  r^  r?  r9  rc  r  r:  r  rB  rG  api_key_textcredential_okr  s                 rD   r  r  0  s   88H5@

:.4"5;;=E	*Y?"#?#AB;;z*8jW[[*0b1"x9'< L
 B
  ($[[1$@	 	 ++i(%g.rC24F4L4L4NW ,==, ., GKK	*+	 	  ($[[1%kk(3?zK	 	 #KK
3 W-!++h/	
 	
  83us1v6778s+   B9F" <B'F" $=F" "	G+GGGzprocess.stopc                     	 ddl m} t        | d|j                         i      S # t        $ r }t        | dt        |            cY d }~S d }~ww xY w)Nr   rI
  killed  )r:
  r2
  ra  kill_allr5   r  r6   )r   r  r2
  r  s       rD   r  r  31  sI    ';3#3#<#<#>?@@ 'Cs1v&&'r=  c                 2   ddl m} t        | j                  d      xs d      }g }|j	                         D ]]  }|j                  |d         }|t        t        |dd      xs d      |k7  r7|j                  xs ddd |d<   |j                  |       _ |S )	zHBackground processes owned by this session (registry session_key match).r   rI
  r   r   r  N`r  )r:
  r2
  r6   r   list_sessionsr   output_bufferr  )r#  r2
  rw  r  r  r   s         rD   _session_processesrN  =1  s    7
gkk-(.B
/CE!//1 ##E,$78<3wt]B?E2F#M !% 2 2 8b%&AmU Lr   rr   c                     t        ||       \  }}|r|S 	 t        | dt        |      i      S # t        $ r }t	        | dt        |            cY d}~S d}~ww xY w)zNSession-scoped view of the background process registry (desktop status stack).	processesrH  N)r  ra  rN  r5   r  r6   )r   r  r#  r  r  s        rD   r  r  N1  s\     %LGS

'3&8&ABCC 'Cs1v&&'s   , 	AA
AAzprocess.killc                    t        ||       \  }}|r|S t        |j                  d      xs d      }|st        | dd      S 	 ddlm} |j                  |      }|9t        t        |dd      xs d      t        |j                  d      xs d      k7  rt        | d	d
|       S t        | |j                  |            S # t        $ r }t        | dt        |            cY d}~S d}~ww xY w)u   Kill ONE background process — scoped to the caller's session so one
    window can't reap another session's work (unlike process.stop's kill_all).rP
  r   rV  zprocess_id requiredr   rI
  Nr   i  zno such process: rH  )
r  r6   r   r  r:
  r2
  r   ra  kill_processr5   )r   r  r#  r  proc_idr2
  r   r  s           rD   r  r  Z1  s     %LGS

&**\*0b1GC455
';##G,<3wt]B?E2F#KK&,"K
 
 T%6wi#@AA3(55g>?? 'Cs1v&&'s%   A!B? $B? ?	C(C#C(#C(z
reload.mcpc                    t         j                  |j                  dd            }	 t        |j                  dd            }|so	 ddlm}  |       }t        |t              r|j                  d      nd }d}t        |t              rt        |j                  d	d            }|rt        | d
dd      S |rVt        |      rK	 t               j                  t        |j                  d      xs d      d|        }t        | dd|d      S ddlm}
m}  |
         |        |rF|d   }	 ddlm}  ||t%               d       t+        d|j                  dd      t-        ||             t        |j                  dd            r	 ddlm}  |dd       t        | ddi      S # t        $ r d}Y w xY w# t        $ r}	t        | dd|	       cY d }	~	S d }	~	ww xY w# t        $ r }t&        j)                  d|       Y d }~d }~ww xY w# t        $ r }t&        j)                  d|       Y d }~d }~ww xY w# t        $ r }t        | dt        |            cY d }~S d }~ww xY w)Nr  r   confirmFr   r  r  Tmcp_reload_confirmrs  u   ⚠️  /reload-mcp invalidates the prompt cache (next message re-sends full input tokens). Reply `/reload-mcp now` to proceed, or `/reload-mcp always` to proceed and silence this prompt permanently.)rN  rK  zreload-mcp-r	  r]  z compute-host reload_mcp failed: reloadedr	  )shutdown_mcp_serversdiscover_mcp_toolsrN  r`  )enabled_overrider-  z:Failed to refresh cached agent tools after /reload-mcp: %srP  rn  rA  zapprovals.mcp_reload_confirmz.Failed to persist mcp_reload_confirm=false: %srN    )rQ   r   r   r^  r  r  r   r5   ra  r"  r/  
reload_mcpr6   r  r  rX  rY  ra  r3  r  r   r  rR  r8  rB  )r   r  r#  user_confirm_load_configr
  
_approvals_confirm_requiredr	  r!  rX  rY  rN  ra  _excr_  r  s                    rD   r  r  q1  sc   mmFJJ|R89G]' FJJy%89	)I#~6@t6LTXXk2RV
$(!j$/(,Z^^<PRV-W(X% ! "4?  1':Q24??

<06B7!,SE2 @  szTWZ[\\KG$EB (%;%=# 

<,eW- 

8U+,W>8%@ 3:.//S  )$(!)6  QC)I#'OPPQ4  P "  WOQUVVW  'Cs1v&&'s   H2 AF" "H2 3H2 :F4 ;H2 H2 )G AH2 H H2 "F1-H2 0F11H2 4	G=GGH2 GH2 	H#G>9H2 >HH2 	H/H*%H2 *H//H2 2	I;IIIz
reload.envc                     	 ddl m}  |       }t        | dt        |      i      S # t        $ r }t        | dt        |            cY d}~S d}~ww xY w)u  Re-read ``~/.hermes/.env`` into the gateway process via
    ``hermes_cli.config.reload_env``, matching classic CLI's ``/reload``
    handler.  Newly added API keys take effect on the next agent call
    without restarting the TUI.

    The credential pool / provider routing for any *already-constructed*
    agent does not auto-rebuild — that's the same behaviour as classic
    CLI's ``/reload``.  Users who want a brand-new credential resolution
    should follow with ``/new``.
    r   )
reload_envr	  r[  N)r^  rc  ra  r  r5   r  r6   )r   r  rc  r.  r  s        rD   r  r  1  sJ    '03CJ/00 'Cs1v&&'s   #& 	AA
A
A>   set-homerl  approvesethomecommands_TUI_HIDDEN))/compactToggle compact display modeTUI)/logsShow recent gateway log linesrk  )/mouse;Set mouse tracking preset [on|off|toggle|wheel|buttons|all]rk  )z	/sessionsz Switch between live TUI sessionsrk  
_TUI_EXTRA>   r  moar  planundolearnr   retryr   r  compress_PENDING_INPUT_COMMANDSsnap_WORKER_BLOCKED_COMMANDSzcommands.catalogc           
      `   	 ddl m}m}m} g }i }g }i }g }	|D ]  }
|
j                  t
        v s|
j                  r"d|
j                   }|||j                         <   |
j                  D ]  }||d| j                         <     ||
      }|j                  ||g       |
j                  }||vrg ||<   |	j                  |       ||   j                  ||g        t        D ]I  \  }}}|j                  ||g       ||vrg ||<   |	j                  |       ||   j                  ||g       K d}	 t               j                  di       xs i }t        |t              r|rd}||vrg ||<   |	j                  |       t!        |j#                               D ]  \  }}t        |t              sd| }|||j                         <   |j                  dd      }|dk(  rd	|j                  d
d       }n!|dk(  rd|j                  dd       }n|xs d}t%        |j                  d      xs |      }|dd t'        |      dkD  rdndz   }|j                  ||g       ||   j                  ||g        d}	 ddlm} t!         |       j#                               D ]N  \  }}t%        |j                  dd            }|j                  ||dd t'        |      dkD  rdndz   g       |dz  }P 	 |	D ]  }|j                  |||   d        |j#                         D ci c]  \  }}||dd  } }}t/        | || ||||d      S # t(        $ r}|sd| }Y d}~d}~ww xY w# t(        $ r}d| }Y d}~d}~ww xY wc c}}w # t(        $ r }t1        | dt%        |            cY d}~S d}~ww xY w)uG   Registry-backed slash metadata for the TUI — categorized, no aliases.r   )COMMAND_REGISTRYSUBCOMMANDS_build_descriptionr  r   quick_commandszUser commandsr  execzexec: r   aliasu
   alias → r   zquick commandr  Nr  r	  z&quick_commands discovery unavailable: )scan_skill_commandsSkillr   zskill discovery unavailable: )rI   r  )r  r
  canonr  skill_countr     )hermes_cli.commandsr{  r|  r}  rI   rh  gateway_onlyr  aliasesr  categoryrp  r  r   r  r   r!  rf  r6   r  r5   r  r  ra  r  )!r   r  r{  r|  r}  	all_pairsr  r  cat_map	cat_ordercmdr  r   r  catrI   r   qcmdsbucketqnameqcrw  qtypedefault_descqdescr  r  r  r  rH  r  r  r
  s!                                    rD   r  r  2  s   ]'	
 	
 &(	 "!#
.0!	# 	+Cxx;&#*:*:CHH:A E!'')[[ +)*!gmmo&+ &c*DaY',,C'!!  %CLD	*!	+$  * 	.OD$dD\*'!!  %CLt-	. 	GKOO$4b9?RE%&5((&(GFO$$V,!'!6 9IE2%b$/ eW+C),E#))+&FF62.E)/y"0E/F'G'))3BFF8R4H3I'J','?} 5 EFE!$3KCJ4D5"ME$$c5\2FO**C<89( 	:@!"5"7"="="?@ !489  !QtWQ#2%N!OPq !  	DCsWS\BC	D $/#4#4#6741aq!A$w77"(*"

 
	
'  	GB1#F	G  	:5aS9G	: 8  'Cs1v&&'s   D.N 1EM 6N 9A5M# .2N  M>0N 	M MN M  N #	M;,M61N 6M;;	N 	N-N("N-(N-r   c                     | sy| d   j                         }|dk(  ry|dk(  ry|dk(  r%t        |       dkD  r| d   j                         d	k(  ry
|dk(  r%t        |       dkD  r| d   j                         dk(  ryy)zKReturn user hint if this argv must not run headless in the gateway process.u^   bare `hermes` is interactive — use `/hermes chat -q …` or run `hermes` in another terminalr   setupu?   `hermes setup` needs a full terminal — run it outside the TUIr  u?   `hermes gateway` is long-running — run it in another terminalr   r   browseu_   `hermes sessions browse` is interactive — use /resume here, or run browse in another terminalr  editz5`hermes config edit` needs $EDITOR in a real terminalN)r  r  )r   a0s     rD   _cli_exec_blockedr  y2  sy    o	aB	W}P	YP	ZCIMd1gmmo.Ip	X~#d)a-DGMMOv,EFr   rf   c                 "   |j                  dg       }t        |t              rt        d |D              st	        | dd      S t        |      }|rt        | d|ddd      S 	 t        j                  t        j                  d	d
g|ddt        t        |j                  dd            d      t        j                         t        d      t        j                         }|j"                  xs d|j$                  xs dg}dj'                  d |D              j)                         xs d}t        | d|j*                  |dd d      S # t        j,                  $ r t	        | dd      cY S t.        $ r }t	        | dt1        |            cY d}~S d}~ww xY w)zXRun `python -m hermes_cli.main` with argv; capture stdout/stderr (non-interactive only).r   c              3   <   K   | ]  }t        |t                y wr   )r  r6   )r  r  s     rD   r  z_.<locals>.<genexpr>2  s     ,NAZ3-?,Ns     zargv must be list[str]Tr  r   )r
  r  r  r   r   zhermes_cli.mainr      iX  r   )r  r   r   r   r   r   r   c              3   &   K   | ]	  }|s|  y wr   r   r  s     rD   r  z_.<locals>.<genexpr>2  s     .aA.r  (no output)FNi  )r
  r  r   r;  zcli.exec: timeout  )r   r  r_  r  r  r  ra  r   r   r;   r   r  r  r,   r   r   r  r   r<   r*   r7   r   r  r5   r6   )r   r  r   r  r  r  r  r  s           rD   r  r  2  se    ::fb!DdD!,N,N)NC788T"D3D$bQRR'NN^^T#4<t<FJJy#67=		 &$?$$

 RR0ii.5..446G-UALLCLQ
 	
 $$ 4C233 'Cs1v&&'s%   !C"E  F&F.F	F	Fzcommand.resolvec                 6   	 ddl m}  ||j                  dd            }|r.t        | |j                  |j
                  |j                  d      S t        | dd|j                  d             S # t        $ r }t        | dt        |            cY d }~S d }~ww xY w)	Nr   resolve_commandrI   r   )	canonicalr  r  i  zunknown command: i  )
r  r  r   ra  rI   r  r  r  r5   r6   )r   r  r  r  r  s        rD   r  r  2  s    '7FJJvr23!"#$== !

  C!26::f3E2FGHH 'Cs1v&&'s$   AA/ A/ /	B8BBBc                 b    	 ddl m}  ||       }|r|j                  S | S # t        $ r | cY S w xY w)Nr   r  )r  r  rI   r5   )rI   r  r  s      rD   _resolve_namer  2  s9    7D!qvv$$ s       ..command.dispatchc                     |j                  dd      j                  d      |j                  dd      }}t        |      }||k7  r|}t        j                  |j                  dd            }t	               j                  di       }||v rK||   }|j                  d      dk(  rd	d
lm}  |t        j                  j                               }	t        j                  |j                  dd      ddddt        j                  |	      }
|
j                  xs d|
j                  r|
j                  rdndz   |
j                  xs dz   j                         d d }|rd	dlm}  ||      }|
j$                  d	k7  rt'        | d|xs d|
j$                         S t)        | d|d      S |j                  d      dk(  rt)        | d|j                  dd      d      S 	 d	dlm}m}  ||      }|r* | ||            }t)        | dt1        |xs d      d      S 	 	 d	dlm}m}m} d	dlm}  ||       ||      nd }|	  |||r|j                  dd      ndtA                     }|st'        | dd|       S |\  }}}        j                  |i       }|j                  d|j                  d            }d | d!tC        |       d"}|r|d#d$jE                  |       z  }t)        | d%||d&      S 	 d	d'l#m$}m%}  |       } d| }!|!| v rD ||!||r|j                  dd      nd(      }|r#t)        | d)|| |!   j                  d|      d*      S |d+v r|st'        | d,d-      S t)        | d%|d.      S |d/k(  rd	d0l&m'}" t)        | d% |"|      d.      S |d1k(  r	 d	d2l(m)}#m*}$ |st'        | d, |#             S |st'        | d3d4      S |j                  dd      }% |$t	               j                  d1      xs i       }&|&d5   }'|j                  d6      }(|j                  d7      |(rtW        |(d8d       nd |(rtW        |(d9d       nd d:|d;<   |(	 tY        |%||' d<d=dd=>       nd1|'dAdBdCdD|d7<   t)        | d%dE|' dF|dG      S |dHk(  r*|st'        | d3dI      S |j                  dJ      rt'        | dKdL      S |j                  dMg       })|)st'        | ddN      S d }*t]        tC        |)      dOz
  dPdP      D ]  }+|)|+   j                  dQ      dRk(  s|+}* n |*t'        | ddN      S |)|*   j                  dSd      },t_        |,t`              rdTjE                  dU |,D              },|,st'        | ddV      S |dW   5  |)d |* |dM<   tc        |j                  dXd	            dOz   |dX<   d d d        t)        | d%|,d.      S |dYk(  r}|st'        | d,dZ      S |r|j                  d6      nd }(|(rHte        |(dY      r<	 |(jg                  |      }-|-r't)        | dd[|d d\  tC        |      d\kD  rd]nd d      S 	 t)        | d%|d.      S |d^k(  r|st'        | d3d4      S 	 d	d_l4m5}. |j                  d      xs d}/|/st'        | d3da      S 	 t	               j                  db      xs i }0tc        |0j                  dcdd      xs dd      }1 |.|/|1e      }2|j                         jm                         }3|j                         r|3dfk(  rt)        | d|2jo                         d      S |3dgk(  r4|2jq                  dhi      }4|4djndk|4jr                   }5t)        | d|5d      S |3dlk(  r>|2ju                         }4|4t)        | ddmd      S t)        | ddn|4jr                   dod      S |3dpv r9|2jw                         }6|2jy                          t)        | d|6rdqd      S drd      S 	 |2j{                  |      }4dt|4j~                   du|4jr                   dv}t)        | d%||4jr                  dG      S |dwk(  r|st'        | d3dx      S |j                  dJ      rt'        | dKdy      S t               }7|7t        | dz{      S |j                  dd      }8|8st'        | d3d|      S dO}9|xs dj                         }:|:r	 tc        |:j                         d	         }9|9dOk  rdO}9	 |7j                  |8t        |9d            };|;st'        | dd      S t        |9dOz
  tC        |;      dOz
        }=|;|=   d   }>	 |7j                  |8|>      }	 |7j                  |8d      }?|dW   5  ta        |?      |dM<   tc        |j                  dXd	            dOz   |dX<   d d d        |j                  d6      }(|(_tW        |(dd       }@|@	 @j                  |8dd=d       te        |(d      r	 |(j                          te        |(d      r	 tC        |?      |(_K        |j                  d      xs i }A|Aj                  dS      xs d}Bt_        |Bt`              r[BD Ccg c]8  }Ct_        |Ct              r&Cj                  d      dk(  rCj                  dd      : }D}CdjE                  d |DD              }Bt_        Bt0              sd}B|j                  dd	      }E|=dOz   }F|FdOk(  rdnd}GdF dT|G d!E d}t)        | dB|d&      S |dv r:|r#|j                  dO      d	   jm                         nd}H|Hdv rt)        | ddd      S |dv r|st'        | d3d      S |j                  dJ      rt'        | dKd      S |j                  dd      }%t        |      rd| |rdT| ndz   }I	 t        |%dId      }JJj                  d      dv r)t'        | dKt1        Jj                  d      xs d            S t        |J       t)        | dt1        |Jj                  d      xs d      d      S 	 d	dlPmQ}K d	dlRmS}L |dW   5  ta        |j                  dMg             }Mtc        |j                  dXd	            }Nd d d        tC        M      }O|d6   }PtW        |Pdd      xs d}QtW        Pdd       xs d }ROr LMQR      nd	}St        ||j                         xs d SMN      \  }T}U|dW   5  ta        |j                  dMg             }Vd d d        tC        V      }WtW        Pdd      xs Q}XtW        Pdd       xs R}YWr LVXY      nd	}Zt        |%|        KMVS|ZtW        Pdd             }[t        d|%t        |j                  d6      |             t)        | ddjE                  t        d |[d   |[d   |[j                  d      g            d      S t'        | dd|       S # t2        $ r Y w xY w# t2        $ r d }Y nw xY w# t2        $ r}t'        | dd|       cY d }~S d }~ww xY w# t2        $ r Y 
w xY w# t2        $ r,}|j[                  d;d        t'        | d?d@|       cY d }~S d }~ww xY w# t2        $ r}t'        | d?d@|       cY d }~S d }~ww xY w# 1 sw Y   xY w# t2        $ r Y >w xY w# t2        $ r}t'        | d?d`|       cY d }~S d }~ww xY w# t2        $ r dd}1Y w xY w# t|        $ r}t'        | d,ds|       cY d }~S d }~ww xY w# t|        t        f$ r t'        | d,d}|:d~      cY S w xY w# t2        $ r}<t'        | dzd|<       cY d }<~<S d }<~<ww xY w# t|        $ r}<t'        | d,d|<       cY d }<~<S d }<~<wt2        $ r}<t'        | dzd|<       cY d }<~<S d }<~<ww xY w# t2        $ r g }?Y 9w xY w# 1 sw Y   
xY w# t2        $ r Y w xY w# t2        $ r Y w xY w# t2        $ r Y w xY wc c}Cw # t2        $ r}t'        | dd|       cY d }~S d }~ww xY w# 1 sw Y   xY w# 1 sw Y   +xY w# t2        $ r}t'        | dd|       cY d }~S d }~ww xY w)NrI   r   r  r  r  r~  r  r  r   )_sanitize_subprocess_envr   Tr  )shellr  r   r   r   r   r   r	  r<  r
  z$quick command failed with exit code )r  r   r  r   )r  r   get_plugin_command_handlerresolve_plugin_command_resultplugin)build_bundle_invocation_messageget_skill_bundlesresolve_bundle_command_keyr  r   )r  r  zbundle dispatch failed: zfailed to load bundle: u   ⚡ Loading bundle: r	  z skills)z
Skipped missing skills: r  send)r  rK  notice)r  build_skill_invocation_messager  skill)r  rK  rI   >   r  r   r4  zusage: /queue <prompt>)r  rK  rt  )build_learn_promptrq  )	moa_usagenormalize_moa_configr  zno active sessiondefault_presetrN  r5  r   r  )r  r   r  rr
  z --provider moaFr  r  zmoa unavailable: zmoa://localzmoa-virtual-providerchat_completions)r  r   r  rG  r  z MoA one-shot queued with preset z2; previous model will be restored after this turn.)r  r  rK  ru  zno active session to retryr  r[  u:   session busy — /interrupt the current turn before /retryrP  z!no previous user message to retryr   r  r)  r*  r+  r  c              3      K   | ]:  }t        |t              r(|j                  d       dk(  r|j                  dd       < yw)r  r   r   N)r  r   r   r  s     rD   r  z_.<locals>.<genexpr>3  s<      a&155=F+B fb!s   A Azlast user message is emptyrO  r1  r   zusage: /steer <prompt>u7   ⏩ Steer queued — arrives after the next tool call: r4  ...r  rx
  zgoals unavailable: zno session keyrz
  r  r{
  r|
  rN  pausezuser-paused)r\  zNo goal set.u   ⏸ Goal paused: resumezNo goal to resume.u   ▶ Goal resumed: uT   
Send any message to continue, or wait — I'll take the next step on the next turn.>   rX  rZ
  r  u   ✓ Goal cleared.zNo active goal.zinvalid goal: u   ⊙ Goal set (z-turn budget): u   
I'll keep working until the goal is done, you pause/clear it, or the budget is exhausted.
Controls: /goal status · /goal pause · /goal resume · /goal clearrs  zno active session to undor	  r	  r  zno session key for undozundo: invalid count u    — use /undo or /undo Nr   )r  zundo: failed to load history: zno user messages to undor   zundo: rE  _memory_manager)r  resetrewound_invalidate_system_prompt_last_flushed_db_idxtarget_messager   c              3   &   K   | ]	  }|s|  y wr   r   )r  r  s     rD   r  z_.<locals>.<genexpr>m4  s     #:!A#:r  rewound_countr  turnsu
   ↶ Undid z7 message(s)). Edit and resubmit, or send a new message.prefill>   rx  ri  maxsplit>   rewindr  z/snapshot restore is blocked in the TUI because it changes config/state on disk while the live agent has cached settings. Run it in the classic CLI, then restart the TUI.>   r  rv  zno active session to compressr	  zslash.compressr	  r]  z$compute-host slash.compress failed: >   r   r	  rK  z"compute-host slash.compress failedr   r	  r  r  r`   r  r	  r  r	  rP  headline
token_linenotei  zcompress failed: z)not a quick/plugin/bundle/skill command: )Yr   r2  r  rQ   r  tools.environments.localr  r,   r  rV  r   r   r  r   r<   r7   r?  r=  r   r  ra  r  r  r  r6   r5   agent.skill_bundlesr  r  r  r  r  r	  r  r*   r  r  r  agent.learn_promptr  hermes_cli.moa_configr  r  r   r  r(  r  r  r_  r  r`  r   r
  ry
  r  status_liner  r  r  has_goalr  r^  r>  r  ra  r  r  
IndexErrorlist_recent_user_messagesrF  r  rewind_to_messagerM  on_session_switchr  r  r   r"  rg  rI  r	  r	  r  r  r  r  r  rR  filter)\r   r  rI   r  r  r#  r  r  r  sanitized_envr  r   r=  r  r  r  r  r  r  r  r  
bundle_keybundle_resultr!  r   loaded_namesmissingbundle_infobundle_namer  r  r  cmdsrw  r  r  r  r-  moa_cfgpresetrN  rP  rA  r"  r+  r
  ry
  r
  r
  r  r  r  r  r  hadrk  r   rc  arg_strrecentsr  
target_idx	target_idr  mm
target_msgtarget_textr  r  r  turns_undone	turn_word
subcommandr   r	  r	  r  r  r1  r	  r	  r  r  r	  rA  r  r	  r	  r	  r	  r	  rp  s\                                                                                               rD   r  r  2  s   

62&--c2FJJub4I#DT"H4mmFJJ|R89GKOO,b1Eu}4[66&>V# J4RZZ__5FGMy"%# ((!A R884b:88>r# eget	F
 >.v6||q S DQ\\NS 
 sVv>??66&>W$sWx8LMNN	

 -T2273<@FsXV\r9JKLL 	
 	
 	8 t$, 't, 	 	E;:AM26r24	M T%<ZL#IJJ%2"\7')--j"=!oofj.?.?.DE'}Bs<7H6IR2499W3E2FGGF 
 	
	

 #$$j$;0SG'++mR"@QSC  '#& $S	fd ;  ~T#;<<3C899w
 	:34Fs4KLMMu}
8	>MCy{33C':;;**\2.C*9;??5+A+GRHG-.F
 KK(E#KK(89:?6T@EGE:t<4/G*+
  F'!(/205-1 */	$ !&# -5 2-() " @Hz{"  wT#?@@;;y!TW  ++i,T#FGGs7|a'R0 	Aqz~~f%/ !	  T#FGG-(,,Y;gt$hh   G
 T#?@@ ^$ 	T!(-!8GI),W[[9JA-N)ORS)SG%&	T 3G<==wT#;<<(/G$TWUG, ;;s+$*(_`cdgeg`h_isvwzs{  A  tAjo  GI  jJ  'K   3C899v~T#677	@4 ++m,2T#344	!06BIIMM+r:@bAI W	J		!!#yy{ex/sVs7HIJJGII]I3E$)M.9J5::,7WCsVs;<<HJJLE}3;O PQQ",UZZL 9n n	 	 --,,.CIIK"581  ?P 	;GGCLE
 U__-_UZZL IS S 	 v%**E
 	

 v~ T#>??;;y!TV  Y:(488kk-4T#<==9"##%d*+ q5A	I22;c!Rj2QG T#=>> QGq 01
J'-		1))+yAF	44[UY4ZF ^$ 	T!%fGI),W[[9JA-N)ORS)SG%&	T G$ 148B~((#*,# $	 )  u9:335 u4514VE. ZZ 017R
 nnY/52k4(+6&'a&155=F+B fb!E  ))#:u#::K+s+K

?A6!A~*a/FW	a	{"]O D8 8 	 ;&I
 	

 ##9<SYYY*1-335"
.."K
 
 &&T#BCC;;y!TZ  jjr*%g.$jauI"=GU0/#	 wwv"<<	*R.RS 
 0=3swwx/@/FB+GH <	>VJ( I"&w{{9b'A"B"%gkk2CQ&G"HI /LW%F!&*A2FL"KVWd3;tF
   .#;f   7		#t+ / /NGU ( B!%gkk)R&@!ABn-K 7<K  #67D9CVL  .""3&   -S':2")&2F"MG .#}W[[5I7'ST""iitgj&97<;PRYR]R]^dRe%fg  TFtfMNNU  "  
  	ET%=cU#CDD	ET  t ! FKK 6=T->se+DEEF,  	>T%6se#<==	>@	T 	T(    	@T%8#>??	@  	I	N  	;T^C5#9::	;R 
+ dC)=g[Ha'bccd  	IT%CA3#GHH	I  	1TVA3<00 	1TVA3<00	1  	F		T 	T" ! 
 ! 
 ! 
f  UC)McU'STTU"I I*B BD  	>T%6se#<==	>sG  ;v "v 9(v( -Aw x -x <Bx  w x #*x<9y	 <y '<y? 7z z7 ){ 9| }
 $0}?}) !}9 >~	 =~~  "7A3 (C 	vvv%$v%(	w1w ww	ww	x'!xx	x xx 	x9x4.x94x9<y		yy	y<"y71y<7y<?zz	z4z/)z4/z47 {{	| &{;5| ;| 	}|!}!}-}<}}
}}}&)	}65}69	~~		~~	'~<6<	  	A@'<6A@<A@zpaste.collapsec                    |j                  dd      }|st        | dd      S t        dz  a|j                  d      dz   }t        dz  }|j                  dd	       d
dlm} |dt         d |j                         j                  d       dz  }|j                  |d       dt         d| d| d}t        | |t        |      |d      S )Nr   r   r4  zempty paster   r   pastesTrW  r   r   paste_r  z%H%M%Sz.txtr    r!   z[Pasted text #r%   u    lines → r  )r  r.   r	  )r   r  _paste_counterr.  r  rZ  r   r  r4   r	  ra  r6   )r   r  r   
line_count	paste_dirr   
paste_filer  s           rD   r  r  4  s     ::fb!DC}--aND!A%Jx'IOOD4O0! 	f^,Alhlln.E.Eh.O-PPTUU  $1 (:,nZLPQR  [#j/JW r   i N  >   .hg.git.svn.next.venv.cache.mypy_cache.ruff_cache.pytest_cachedistvenvbuildr   __pycache__node_modules_fuzzy_cachec           
      6   t        j                         }t        5  t        j	                  |       }|r||d   z
  t
        k  r|d   cddd       S ddd       g }ddlm}  |       }	 t        j                  dd| ddgd	d
dt        j                  |      }|j                  dk(  r0|j                  j                  dd      j                         }t        j                  dd|dddddgd	d
dt        j                  |      }|j                  dk(  r|j                  j                  dd      j                  d      D ]  }	|	st         j"                  j%                  t         j"                  j'                  ||	      |       j)                  t         j*                  d      }
|
j-                  d      rt|j/                  |
       t1        |      t2        k\  s n |s	 t!        j8                  | d      D ]  \  }}}|D cg c]  }|t:        vr|j-                  d      s| c}|dd t         j"                  j%                  ||       }|D ]S  }|dk(  r|n| d| }
|j/                  |
j)                  t         j*                  d             t1        |      t2        k\  sS n t1        |      t2        k\  s n t        5  ||ft        | <   ddd       |S # 1 sw Y   xY w# t4        t        j6                  f$ r Y  w xY wc c}w # t4        $ r Y Yw xY w# 1 sw Y   |S xY w)an  Return file paths relative to ``root``.

    Uses ``git ls-files`` from the repo top (resolved via
    ``rev-parse --show-toplevel``) so the listing covers tracked + untracked
    files anywhere in the repo, then converts each path back to be relative
    to ``root``. Files outside ``root`` (parent directories of cwd, sibling
    subtrees) are excluded so the picker stays scoped to what's reachable
    from the gateway's cwd. Falls back to a bounded ``os.walk(root)`` when
    ``root`` isn't inside a git repo. Result cached per-root for
    ``_FUZZY_CACHE_TTL_S`` so rapid keystrokes don't respawn git processes.
    r   r   Nr   gitz-Cz	rev-parsez--show-toplevelT       @F)r  r   checkr   r   r    r  zls-filesz-zz--cachedz--othersz--exclude-standard r  z../)followlinksr  )r3   	monotonic_fuzzy_cache_lockr  r   _FUZZY_CACHE_TTL_Sr   r   r   r   r  r   r   r  r7   r  r,   r.   relpathr*   r  r2  r  r  r  _FUZZY_CACHE_MAX_FILESr	  r  walk_FUZZY_FALLBACK_EXCLUDES)r  r  r  filesr   _creationflags
top_resultr  list_resultr  r4  dirpathdirnames	filenamesr  rel_dirrB   s                    rD   _list_repo_filesr  %5  s    ..
C	 !!$'cF1Io(::!9  
 E@')N+^^D$->?$$(

   A%##**7I>DDFC$..(	  $ ((,K" %%*$++227IFLLTR A ''//"'',,sA*>EMMC
 ~~e, LL%5z%;;  	02%0P ,9 & 88cAR 
 ''//'48" A&#~!gYas3CCLLRVVS!9:5z%;;	
 u:!77" 
 *!5\T* L_ f Z../   		* Lsa   +K(E*K K "K? ;"K:A:K? K? .K? 7LKK76K7:K? ?	L
LLqueryc                    |sdt        |       fS | j                         }|j                         }||k(  rdt        |       fS |j                  |      rdt        |       fS g }d}| D ]L  }|dv s%|j                         r1|r/|d   j                         s|r|j	                  |       |dvr|nd}H||z  }N |r|j	                  |       |D ]0  }|j                         j                  |      s#dt        |       fc S  ||v rdt        |       fS d}|D ]-  }|||   k(  s|dz  }|t        |      k(  s dt        |       fc S  y	)
u  Rank ``name`` against ``query``; lower is better. Returns None to reject.

    Tiers (kind):
      0 — exact basename
      1 — basename prefix (e.g. `app` → `appChrome.tsx`)
      2 — word-boundary / camelCase hit (e.g. `chrome` → `appChrome.tsx`)
      3 — substring anywhere in basename
      4 — subsequence match (every query char appears in order)

    Secondary key is `len(name)` so shorter names win ties.
    r(  r   r   r   z-_.r  r   r  N)r  r  r  isupperr  )	rI   r  nlqlr  rp  chr  r"  s	            rD   _fuzzy_basename_rankr#  5  sW    3t9~	B	B	Rx3t9~	}}R3t9~
 E
C ;2::<CB8IS!%"RC2IC S "779#s4y>!" 
Rx3t9~	A &A;FACG|3t9~%	& r   rv   c           	      `	   |j                  dd      }|st        | dg i      S g }	 t        |      }|j                  d      }|r|dd  n|}|r0|s.ddddd	d	d
dddddddddddddddddg}t        | d|i      S |r	|dv r|d}}n3|r)|j                  d      r|j	                  d      \  }}	}
|
}nd}|r|n|}|r|r	t        |j                               dk\  rd|vr|dk7  rg }t        |      D ]g  }t        j                  j                  |      }|j                  d      r|j                  d      sEt        ||      }|T|j                  |||f       i |j                  d        |xs d}|d d D ]>  \  }	}}|j                  d| d| |t        j                  j                  |      d       @ t        | d|i      S |rt        |      nd}|dk(  s|sd\  }}nX|j!                  d      r|d}}nBt        j                  j                  |      xs d}t        j                  j                  |      }t        j                  j#                  |      r|nt        j                  j%                  ||      }t        j                  j'                  |      st        | dg i      S |dk(  }|j)                         }t+        t        j,                  |            D ]  }|r |j)                         j                  |      s&|r	|t.        v r1|r|s|j                  d      rGt        j                  j%                  ||      }t        j                  j'                  |      }|r||k7  rt        j                  j1                  ||      j3                  t        j4                  d      }|rdnd}|r|rd| d| | }n|r|rdnd}d| d| | }nt|j                  d      rDd t        j                  j1                  |t        j                  j7                  d            z   |z   }n|j                  d!      r	d!|z   |z   }n||z   }|j                  |||z   |rd"ndd       t        |      dk\  s n t        | d|i      S # t8        $ r }t;        | d#t=        |            cY d }~S d }~ww xY w)$Nwordr   rf  r`
  r   z@diffzgit diffr   r   r  z@stagedzstaged diffrK  zattach filez@folder:zattach folderz@url:z	fetch urlz@git:zgit log>   r'   folder)zfile:zfolder:r  r   r  r'  r  c                 0    | d   t        | d         | d   fS )Nr   r   )r  r  s    rD   r   z_.<locals>.<lambda>5  s    qtS1Y!&= r   r  r'   r  )r  r   r  z~/z./dirr  )r   ra  r  r  	partitionr  r7   r  r,   r.   r  r#  r  r  r/   r  endswithisabsr*   r  r  r!  listdirr  r  r  r2  r  r5   r  r6   )r   r  r%  rf  r  
is_contextr  
prefix_tagr  r  r6  rankedr4  r  ranktagrd   
search_dirr  want_dirmatch_lowerr  r  rb  rb  r   rr  r  s                               rD   r  r  5  s   ::fb!D3"&&Ex'v&__S)
&QRDe WjI"y-P!hN#
OT WkJ WiHE sWe,--
 %#55$)2	JE,,-AB"'//#"6J4IJ!+I IOO%&!+9$h&=?F'- 577++C0&&s+I4H4H4M+Hi@<tS(345 KK=K>&C$*3BK  3"#C5##+ " 4 sWe,--<E-i83s?( 'Js# ("J29cJGG$$X.E ''--
3JdJ9W 	 ww}}Z(sWbM**)kkmBJJz23 %	EU[[]55kBe'??*1A1A#1F77<<
E2DWW]]4(F h&0''//$-55bffcBC"SFj:,auVH5#)xv4&#vh/%bggoodBGG4F4Fs4KLLvU&czF*V|LL $v~%+E 5zRK%	R sWe$%%  'Cs1v&&'s9   AR =ER 
C!R ,GR 3R 	R-R("R-(R-r  c                     | | |dS )Nr&  r   )rE  r  s     rD   _details_completion_itemr7  ?6  s    eT::r   needs_leading_spacec                 2    t        |r
d|  |      S | |      S )Nr  )r7  )rE  r  r8  s      rD   _details_root_completion_itemr:  C6  s/     $*!E7 05 r   c           
      :   | j                         j                  d      sy | j                         }|r1dj                  |j                         j                         d         sy | t	        d      d  }|j                  d      r|dd  }|j                         }| j                  d      }d}d}|rt	        |      dk(  rJ|rHg |D cg c]  }t        |d|        c}t        dd	|       |D cg c]  }t        |d
|        c}S t	        |      dk(  rZ|sX|d   j                         }	g |d|}
|
D cg c]1  }|j                  |	      r||	k7  rt        |||v rd
n|dk(  rd	nd      3 c}S t	        |      dk(  rh|rf|d   j                         |v rQg |D cg c]"  }t        |d|d   j                                $ c}t        dd|d   j                          d      S t	        |      dk(  r|s|d   j                         |v rx|d   j                         }	g |dD cg c]T  }|j                  |	      rA||	k7  r<t        ||dk(  rd|d   j                          dnd|d   j                                V c}S g S c c}w c c}w c c}w c c}w c c}w )N/detailsr   r  r   r^   )rc   re   rd   zglobal moder{  zcycle global modezsection overridezset r  zclear z	 overrider   )r  r  r7   r  r  r+  r:  r7  )r   strippedrz  r  has_trailing_spacer  modesr  r  r  
candidatesr  s               rD   _details_completionsrA  L6  s   ::<"":.zz|H
--hnn.>.D.D.Fq.IJJ!"DsABxJJLEs+=H/ECJ!O(:

 "	  .--?)?
 *,2D.D
  (	  ./5G1G
 	
$ 5zQ1q!1u1g11
 (
 ##F+	V0C % !H, '09W0D,-
 	
 5zQ-%(..2Bh2N
 " )eAhnn6F5G/HI

 %WuQx~~7G6H	.RS
 	
 5zQ1eAhnn6F(6Rq! /u.g.
 ##F+	V0C % !G+ U1X^^-.i8a 012
 	
 Is

s   J.J	66J'J&AJr|   c                    |j                  dd      }|j                  d      st        | dg i      S 	 ddlm} ddlm} ddlm} dd	l	m
 dd
lm  |fdfd      } ||t        |            }|j                  |d       D cg c]X  }|j                  |j                   r ||j                         n|j                  |j"                  r ||j"                        nddZ c}d d }	|j%                         }
ddddddddddddddddg}|D ]=  d   j                  |
      st'        fd|	D              r-|	j)                         ? t+        |      }|0t        | |d|v r|j-                  d      dz   n
t        |      d      S t        | |	d|v r|j-                  d      dz   ndd      S c c}w # t.        $ r }t1        | dt3        |            cY d }~S d }~ww xY w)Nr   r   r  rf  r   )SlashCommandCompleter)Document)to_plain_textget_skill_commandsr  c                               S r   r   rF  s   rD   r   z_.<locals>.<lambda>6  s    ,>,@ r   c                               S r   r   rH  s   rD   r   z_.<locals>.<lambda>6  s    +<+> r   )skill_commands_providerskill_bundles_providerr&  r  ri  rj  r<  zControl agent detail visibilityrl  rm  rn  ro  c              3   4   K   | ]  }|d    d    k(    yw)r   Nr   )r  r&  extras     rD   r  z_.<locals>.<genexpr>6  s%      @26Vf-@s   r  r   )rf  replace_fromr  )r   r  ra  r  rC  prompt_toolkit.documentrD  prompt_toolkit.formatted_textrE  r  rG  r  r  r  get_completionsr   r   display_metar  r  r  rA  r0  r5   r  r6   )r   r  r   rC  rD  rE  	completerdocr  rf  
text_lowerextrasdetails_itemsr  rN  r  rG  s                 @@@rD   r  r  6  s   ::fb!D??33"&&F'=4?;9)$@#>
	 tSY' ..sD9
   89yy=3aff9:ann5R	
 2 ZZ\
 #%5 #%9  "7 !#U!
,  	$EV}''
3C @:?@ = U#		$ -T2$*;>$;DJJsOa$7CPTI  C4KTZZ_q-@UVW
 	
i
p  'Cs1v&&'sE   AF> 
AF9'AF> -F> AF> &F> 9F> >	G'G"G'"G'rw   c                    	 ddl m}m} t        j	                  |j	                  dd            }|r|j	                  d      nd } |       j                  |rt        |dd      nd|rt        |dd      ndxs
 t               |rt        |dd      nd	      } ||t        |j	                  d
            t        |j	                  d            ddddt        |j	                  d            t        |j	                  d            t        |j	                  d             
      }t        | |      S # t        $ r }t        | dt        |            cY d }~S d }~ww xY w)Nr   build_models_payloadload_picker_contextr  r   rN  r  r   r  r  rf  rg  explicit_onlyinclude_unconfiguredTrefresh)	r^  r_  picker_hintscanonical_orderpricingcapabilitiesr`  probe_custom_providersprobe_current_custom_provider  )hermes_cli.inventoryr[  r\  rQ   r   with_overridesr   r  r   ra  r5   r  r6   )	r   r  r[  r\  r#  rN  r  r  r  s	            rD   r  r  6  s-   &'R--

< <=(/G$T
 "#22?DWUJ;"05,2R.BR?DWUJ;" 3 
 'vzz/:;!%fjj1G&H!I I./#'

9(=#>.26::i3H.I*I
 3   'Cs1v&&'s   D*D- -	E6EEEzmodel.save_keyc           	      j   	 ddl m} ddlm} ddlm}m} |j                  d      xs dj                         |j                  d      xs dj                         }r|st        | dd	      S  |       rt        | d
d      S |j                        }|st        | dd       S |j                  dk7  r't        | d|j                   d|j                   d      S |j                  st        | dd|j                         S |j                  d   }ddlm}	  |	||       ddl}
||
j                   |<   t"        j                  |j                  dd            }|r|j                  d      nd} |       j%                  |rt'        |dd      nd|rt'        |dd      ndxs
 t)               |rt'        |dd      nd      } ||dd      }t+        fd|d   D        d      }||j                  d g ddd!}d|d"<   t-        | d|i      S # t.        $ r }t        | d#t1        |            cY d}~S d}~ww xY w)$a  Save an API key for a provider, then return its refreshed model list.

    Params:
        slug: provider slug (e.g. "deepseek", "xai")
        api_key: the key value to save

    Returns the provider dict with models populated (same shape as
    model.options entries) on success.
    r   )PROVIDER_REGISTRY)
is_managedrZ  r  r   rG  r  zslug and api_key are requiredr;  u-   managed install — credentials are read-onlyr	  zunknown provider: r  z uses u)    auth — run `hermes model` to configurer4  zno env var defined for )save_provider_env_credentialNr  rN  r  r   r  r]  Tr	  )ra  
max_modelsc              3   4   K   | ]  }|d    k(  s|  yw)r  Nr   )r  r  r  s     rD   r  z_.<locals>.<genexpr>V7  s     B1&	T0AQBr(  re  F)r  rI   r7	  modelstotal_modelsauthenticatedrr    )rr  rk  r^  rl  rh  r[  r\  r   r7   r  	auth_typerI   api_key_env_varshermes_cli.credential_lifecyclerm  r,   r  rQ   ri  r   r  r  ra  r5   r6   )r   r  rk  rl  r[  r\  rG  pconfigr  rm  r,   r#  rN  r  r  provider_datar  r  s                    @rD   r  r  7  sH   H'50R

6"(b//1::i(.B5577T#BCC<T#RSS#''-T%7v#>??	)<<.w'8'8&9 :2 3  ''T%<W\\N#KLL
 **1-P$Wg6%

7 --

< <=(/G$T!#22?DWUJ;"05,2R.BR?DWUJ;" 3 
 'dr
 B,BD
   # !!%M *.o&3]344 'Cs1v&&'s=   A*H	 .H	 "H	 %5H	 %H	 DH	 		H2H-'H2-H2zmodel.disconnectc                    	 ddl m}m} ddlm} |j                  d      xs dj                         }|st        | dd      S |j                  |      }d}d}|r7|j                  r+|j                  D ]  }	 ||	      j                  d	      sd
}  ||      }|s|st        | dd|       S |r|j                  n|}
t        | ||
d
d      S # t        $ r }t        | dt        |            cY d}~S d}~ww xY w)zRemove credentials for a provider.

    Params:
        slug: provider slug (e.g. "deepseek", "xai")

    Returns success status and the provider's slug.
    r   )rk  clear_provider_auth)remove_provider_env_credentialr  r   r  zslug is requiredFrP  T  zno credentials found for )r  rI   disconnected  N)rr  rk  rz  rv  r{  r   r7   r  ru  rI   ra  r5   r6   )r   r  rk  rz  r{  r  rw  cleared_envcleared_authrz  r  r  s               rD   r  r  j7  s   ('JR

6"(b//1T#566#''- w//.. '1"599'B"&K' +40<T%>tf#EFF(/T% $
 	
  'Cs1v&&'s0   ?C A	C C ,C 	C5C0*C50C5>	   r  r  r  rp  r  renamerN  rP  rv  >   helpr`   rk  c                 H   | j                  d      }t        |       }||sy| j                  d      t        | j                  d      xs d      }n)| d   5  t        | j                  dg             }d d d        ddd	|j                  d
      xs- t	        |       j                  d
      xs t        |d
d      xs d dt        |j                  d      xs d      ddt        |j                  d      xs d      dg}t        |j                  d      xs d      }|r|j                  d|d       |j                  dt        |j                  d      xs d      ddt        |j                  d      xs d      ddt        |j                  d      xs d      ddt        |j                  d      xs d      dg       |j                  d      rq|j                  dt        |j                  d      xs d      ddt        |j                  d      xs d      dd t        |j                  d!      xs d       d"       |j                  d#dd$t        |j                  d%      xs d      dg       d&j                  |      S # 1 sw Y   &xY w)'NrN  .(._.) No active agent -- send a message first.rC  r   rO  rP  zSession Token Usagex   ────────────────────────────────────────r	  r   r   r	  zInput tokens:                 r  r
  zOutput tokens:                r   r  zReasoning tokens:             zPrompt tokens:                r  zCompletion tokens:            r  zTotal tokens:                 r  zAPI calls:                    r  r  zCurrent context:              r   / r	  r  %)zMessages:                     zCompressions:                 r  r   )	r   r  r  r  r>  r   r  r#  r*   )r#  rN  r  rB  r	  r  s         rD   _format_live_usage_outputr  7  s   KK E#G,E}U?{{,-9GKK(ABGaH^$ 	<Ir :;M	< 	 	C
%))G$|(8(A(E(Eg(N|RYZ_ahjlRm|q|}~
(UYYw-?-D1)Ea(HI
(UYYx-@-EA)Fq(IJE EIIk*/a0I5i]CD	LL,S81D1I-J1,MN,S<1H1MA-Nq,QR,S71C1Hq-I!,LM,S71C1Hq-I!,LM		
 yy,599^,1215S599]+0q1!4 5EII/05A67r;	
 
LL,]1,=>,S>1J1Oa-PQR,ST	
 99UC	< 	<s   JJ!c           
         | d   5  t        | j                  dg             }d d d        t               }|(| j                  d      r	 |j                  | d   d      }t              }|syddg}t        |d	
      D ]  \  }}t        |j                  d      xs d      }|dk(  rdn|dk(  rdn|j                         }t        |j                  d      xs |j                  d      xs d      j                         }	t        |	      dkD  r|	d d  d}	|j                  d| d| d|	xs d         dj                  |      S # 1 sw Y   %xY w# t        $ r Y w xY w)NrO  rP  r   Tr	  No conversation history yet.zConversation Historyr  r   )r   r)  rT  r*  Your?  Hermesr   rk  r   i  r  r  z #z] z	(no text)r   )r_  r   ra  rM  r5   r  r  r6   r  r7   r  r  r*   )
r#  rP  rk  rn  r	  r3  rK  r)  r9  r   s
             rD   _format_live_history_outputr  7  s{   		  3w{{9b123	B	~'++m4	55&$ 6 G
 $G,H-#  &`  aE!(!4 @W7;;v&3)49LXRVR\R\R^7;;v&F'++i*@FBGMMOt9s?4Cj\%Dqr#b)<(=>?@ 99U+3 3  		s   EE E	EEc                     | j                  d      }t        |       }|d|vry|j                  d      xs  t        |dd       xs t        |dd       xs d}|syd| S )	NrN  r  (No active agent -- send a message first.r  r  r   z=Current system prompt is not built yet; send a message first.zCurrent system prompt:
)r   r>  r   )r#  rN  r?  r  s       rD   _format_live_prompt_outputr  7  s}    KK Eg&F}69

?# 	53T:	5148	 	  N%fX..r   c                 F   g }t               }|1| j                  d      r 	 t        |j                  | d   d            }|s2| d   5  t        t        | j                  dg                   }d d d        t        |       }t        |       }|rdt        |       dndg}i }|D ]8  }t        |j                  d	      xs d
      }|j                  |d      dz   ||<   : |j                  d|j                  dd       d|j                  dd       d|j                  dd       d|j                  dd              |j                  d      xs |j                  d      xs d}	|j                  d      xs d}
|	r|j                  d|	        |j                  d|
        t        |j                  d      xs |j                  d      xs d      }t        |j                  d      xs d      }|r?|r'||z  dz  }|j                  d|d d!|d d"|d#d$       n|j                  d|d d%       |j                  d&      r1|j                  d't        |j                  d&      xs d      d        d(j                  |      S # t        $ r g }Y Rw xY w# 1 sw Y   ,xY w))Nr   Tr	  rO  rP  zConversation: z	 messages(Conversation is empty (no messages yet).r)  rT  r   r   z  user: r*  z, assistant: r?  z, tool: r  z
, system: r@  r   r   r  r  r	  z
Provider: r  r  r  r  zContext usage: ~r
  r  z	 tokens (rL  r  z tokensr  zCompressions: r   )ra  r   r  rM  r5   r_  r  r>  r  r6   r  r  r*   )r#  rn  rk  r  r?  r	  rolesr   r)  r   r  r  r  	usage_pcts                 rD   _format_live_context_outputr  8  s   H	B	~'++m4	+//0FZ^/_H
 ^$ 	N+DY1K,LMH	N#G,Eg&F5=.Xy1CmE E -3776?/i0iia(1,d- 
LL
599VQ'(eiiQ6O5P Q61%&j8Q1G0H	J JJw;599W#5;Ezz*%/Hwug&'	LL:hZ()uyy0KEIIg4FK!LLeii.3!4K%3s:ILL"<"2#k!_IiX[_\^_ LL+L+;7CDyy ~c%))N*C*Hq&I!%LMN99UG  	H		N 	Ns   J %JJJJ c                    t        | j                  d      |       }t        |t              r|j                  d      ni }t        |t              r|syg }|j	                         D ]+  }t        |t
              s|j                  d |D               - t        t        |            }|sydj                  t        |      dj                  d |D                    S )NrN  r`   No tools available.c              3   2   K   | ]  }t        |        y wr   r  r  s     rD   r  z,_format_live_tools_output.<locals>.<genexpr>=8  s     ;tT;s   zAvailable tools ({}):
{}r   c              3   &   K   | ]	  }d |   yw)  Nr   r  s     rD   r  z,_format_live_tools_output.<locals>.<genexpr>B8  s     <d4&k<s   )rR  r   r  r   ra  r_  r#  r!  r^  ri  r  r*   )r#  rH  groupsr  group_namess        rD   _format_live_tools_outputr  58  s    W-w7D",T4"8TXXgbFfd#6$E}} <k4(LL;{;;< 3u:E$&--E
DII<e<< r   c                  (   	 ddl m}  ddg}| j                         D ]I  \  }}|j                  | d       |j                         D ]  \  }}|j                  d|dd|         K d	j	                  |      S # t
        $ r}d
| cY d }~S d }~ww xY w)Nr   )COMMANDS_BY_CATEGORYzAvailable commands:r   r  r  z<15r  r   zhelp unavailable: )r  r  rf  r  r*   r5   )r  r	  r  rg  r  r  r!  s          rD   _format_live_help_outputr  F8  s    
*<&+"6"<"<"> 	4HhLLH:Q(%^^- 4	Tr#c!D6234	4 yy *#C5))*s   A6A9 9	BBBBc                     | j                  d      }|t        |dd      nd}|t        |dd      nd}|r|r	d| d| dS |rd| S y)	NrN  r   r   r  zCurrent model: r	  r	  zCurrent model: (unknown))r   r   )r#  rN  r   r  s       rD   _format_live_model_outputr  T8  sg    KK E+0+<GE7B'"E161Bwuj"-H r(155 ((%r   r  c                 J   |xs dj                  d      j                         }|xs d}|dk(  r|j                         st        |xs i       S |t        vr|t
        v r|t        |      sy |t
        v r|t        |      sy |dk(  r!|yt        | |d| j                               S |dk(  r|yt        |      S |d	k(  r|y
t        |      S |dk(  r|yt        |      S |dk(  rqt        d   dd| i      }|j                  d      r!t        |d   j                  d      xs d      S t        |j                  di       j                  d      xs d      S |dk(  r|yt        |      S |dk(  r|yt        |      S |dk(  r
t!               S |dk(  ry|dk(  ry|dk(  ry|d k(  ry!y )"Nr   r  r   rv  zno active session for /compressz
/compress r  r  rP  r  r  r  rN  rz	  r  r   rK  zstatus unavailabler  r   rk  r  r`   r  r  r  z?Screen clear is terminal-only; desktop/TUI chat left unchanged.rp  z]Use /model to view or switch the current model; desktop users can also open the model picker.r  z)Use /title <name> to rename this session.r  z3Use /reasoning <effort> to change reasoning effort.)r2  r  r7   r  _LIVE_SESSION_DIRECT_COMMANDS_ISOLATED_SESSION_READ_COMMANDSr"  _mirror_slash_side_effectsr  r  r  rR   r   r6   r  r  r  )r-  r#  rI   r  responses        rD   _live_slash_command_outputr  _8  s   JBs#))+D
)Cwsyy{(B770033#*73.. :7 Cz?4)#w*SE8J8P8P8RSSw?C(11y?1*733x?=)'22x,-hs8KL<< x(,,Y7O;OPP8<<"-11(;ArBBy?=*733w?((11v~'))wPxnx:xDr   c                    |j                  d      j                  dd      }|sy|d   t        |      dkD  r|d   j                         nd|j	                  d      }}}h d}t        |      rx||v rtd| }	 t        | ||d	
      }	|	j	                  d      dv r"t        |	j	                  d      xs d| d      S t        ||	       t        |	j	                  d      xs d      S ||v r|j	                  d      rd| S 	 |dk(  r#|r!|rt        | ||      }|j	                  dd      S |dk(  r*|r(|r&t        |t                     \  }}t        | |||       y|dk(  rM|rKt               }t        |j	                  d      xs i j	                  dd            }|xs d|_        d|_        y|dk(  rU|rRddlm} ddlm} |d   5  t+        |j	                  dg             }ddd       t              }t-        |dd      xs d}t-        |dd      xs d}|r ||||       nd}t/        ||       t1        | |       |d   5  t+        |j	                  dg             }ddd       t-        |dd      xs |}t-        |dd      xs |}r ||||       nd}t3        d!| t5        ||              |||||t-        |d"d      #      }|d$   |d%   g}|j	                  d&      r|j7                  |d&          d'j9                  |      S |d(k(  rA|r?|j;                         }|d)v rd*|_        n|d+v rd|_        t3        d!| t5        ||             y|d,k(  r|rt?        |d-      r|jA                          y|d.k(  rdd/l!m"} |jG                          y# t        $ r}
d| d|
 cY d}
~
S d}
~
ww xY w# 1 sw Y   xY w# 1 sw Y   [xY w# t        $ r}d0| cY d}~S d}~ww xY w)1z?Apply side effects that must also hit the gateway's live agent.r  Nr   r   r   rN  >   r   r  rv  r  zslash.Tr	  zcompute-host z	 failed: r  >   r   r	  rK  z failedr   r  u=   session busy — /interrupt the current turn before running /r   r   r  r  r  rv  r	  r  rO  rP  r  r`   r  rP  r  r	  r  r  r  r   r  >   r  r  r  >   r  r  z
reload-mcpreload_mcp_toolsrZ
  rI
  zlive session sync failed: )$r2  r  r  r7   r   r"  rg  r5   r6   rI  r  r
  r  r  r  r  r  r	  r	  r  r  r_  r   r  r  r  rR  r  r*   r  r  r`  r  r:
  r2
  rI  )r-  r#  r   r  rI   r  rN  _MUTATES_WHILE_RUNNINGrc  r	  r!  r  r  r  r  r	  r  _before_messages_before_countr  r  _before_tokens_after_messagesr	  r	  _after_tokens_fb_linesr  r2
  r  s                                  rD   r  r  8  sJ   NN3%%dA.Ea Z!^q	G #D L!'*t7M/MdV_
	>,%	C 776?88swwy)P}ZL-PQQ+GS93778$*++%%'++i*@NtfUUJ07?su(gs;F::i,,]"su 5c9; GE:)#w
EJJ I X%+C%swww'7'=2&B&B?TV&WXJ,6,>$E)*.E'@  ZE WJ( D#'Ir(B#C D 01M!%)@"EKKUGT2:dF
 ! .$Kv   &gs3,S':( C"&w{{9b'A"BC '/F K Z{"5'48BFL
 # .#3DL   .#}UG'DE. ")%1Et"LC *os<'89Fwwvc&k*99V$$V^99;D~%%/"**%)".#}UG'DE  \!e?Q0R""$  V^?%%' i  	>":,iu==	><D D C CH  0+A3//0s   7N
  'O (.O AO )O N(A!O  N5B'O AO 
#O .O 
	N%N N% N%(N2-O 5N?:O 	OOOOrm   c           	      "   t        ||       \  }}|r|S |j                  dd      j                         }|st        | dd      S |j	                  d      r|j                  d      n|}|j                  d      }|r|d   ndj                         }t        |      dkD  r|d   nd}t        |j                  d	d      |||      }	|	t        | d
|	xs di      S |t        v r#t        d   | |||j                  d	d      d      S |t        v r8|r#|j                  d      d   j                         nd}
|
dv rt        | dd      S 	 ddlm} ddlm}  ||       ||      nd }|2t        d   | |j                  d      ||j                  d	d      d      S 	 	 ddlm} d| }| |       v rt        | dd|       S 	 d }d }|r	 ddlm}m}  ||      }|r,|r*	  | ||            }t        | d
t1        |xs d      i      S |j                  d      }|s`	 t3        |d   t5        |j                  d      dt7                     |j                  d            }t9        |j                  d	d      ||       	 |j;                  |      }t=        |j                  d	d      ||      }d
|xs di}|r||d<   t        | |      S # t$        $ r Y 4w xY w# t$        $ r Y w xY w# t$        $ r d }d }Y w xY w# t$        $ r}t        | d
d| i      cY d }~S d }~ww xY w# t$        $ r}t        | dd|       cY d }~S d }~ww xY w# t$        $ rF}	 |j?                          n# t$        $ r Y nw xY wd |d<   t        | dt1        |            cY d }~S d }~ww xY w) Nr   r   r4  empty commandr  r   r  r   r  r   r  r  )rI   r  r  >   r  r  r
  zVsnapshot restore mutates live config/state; use command.dispatch for /snapshot restore)r  r  rF  z(skill command: use command.dispatch for r  zPlugin command error: r]  r   rN  r   r   r  r  zslash worker start failed: r   ) r  r   r7   r  r  r2  r  r  r  r  ra  rw  rR   ry  r  r  r  r  r5   r  rG  r  r  r  r6   r   r   r  rz  r   r  r   )r   r  r#  r  r  	_cmd_text
_cmd_parts	_cmd_base_cmd_arglive_outputr  r  r  _bundle_keyrG  _cmd_keyplugin_handlerr  r  r  r  rp  r   r   r  s                            rD   r  r  9  s   ,LGS


**Y
#
)
)
+CC// $'>>##6

3CI!,J",A";;=I #J! 3z!}H,

<$gy(K 3;#?-@AA++ *+!$jjr:
 	
 ,,>FX^^Q^/288:B
..h B7 y)1 'y1 	
 "./'..s3#"(**\2">  #	;yk?)++TEhZP  , N$(!		1
 8	BN
 7	F2>(3KLFsXs6+B]'CDEE [[(F	F!&G,g~7GH$[[8F
 6::lB7&I'C,VZZb-I7TWXV4}5!(GI3  k      	1!N,0)	1  	FsX)?s'CDEE	F  	FT%@#DEE	F  '	LLN 		"&Cs1v&&'s   AJ> #K K (K2 AL 5AL? >	K
K	KKK/.K/2	L;LLL	L<"L71L<7L<?	N	MN		M&#N	%M&&N	N	N_voice_event_sidc                 `    t         5  t        }ddd       t        | |       y# 1 sw Y   xY w)a4  Emit a voice event toward the session that most recently turned the
    mode on. Voice is process-global (one microphone), so there's only ever
    one sid to target; the TUI handler treats an empty sid as "active
    session". Kept separate from _emit to make the lack of per-call sid
    argument explicit.N)_voice_sid_lockr  r  )r  r  r-  s      rD   _voice_emitr  9  s-     
 	%g s   $-c                  d    t         j                  j                  dd      j                         dk(  S )a  Current voice-mode flag (runtime-only, CLI parity).

    cli.py initialises ``_voice_mode = False`` at startup and only flips
    it via ``/voice on``; it never reads a persisted enable bit from
    config.yaml.  We match that: no config lookup, env var only.  This
    avoids the TUI auto-starting in REC the next time the user opens it
    just because they happened to enable voice in a prior session.
    HERMES_VOICEr   r  r,   r  r   r7   r   r   rD   _voice_mode_enabledr  9  s'     ::>>."-335<<r   c                  d    t         j                  j                  dd      j                         dk(  S )zCWhether agent replies should be spoken back via TTS (runtime only).HERMES_VOICE_TTSr   r  r  r   r   rD   r
  r
  9  s&    ::>>,b1779S@@r   c                      t               } t        | t              r| j                  d      nd}t        |t              r|S i S )u*  Shape-safe accessor for the ``voice:`` block in config.yaml.

    ``_load_cfg()`` returns raw ``yaml.safe_load()`` output, so both the
    root AND ``voice`` may be any YAML scalar / list / None. A hand-edit
    like ``voice: true`` or a malformed top-level config that parses to
    a scalar would otherwise break ``.get("…")`` and take every
    ``voice.*`` branch down with it (Copilot round-3..7 review on
    #19835). Coerce through ``isinstance`` at every level so malformed
    config falls back to an empty dict instead of crashing /voice.
    voiceN)r  r  r   r   )r  	voice_cfgs     rD   _voice_cfg_dictr  9  s8     +C$.sD$9 tI"9d39;;r   c                  r    t               j                  d      } t        | t              r| rt        |       S dS )z@Current ``voice.record_key`` value, documented default on error.
record_keyzctrl+b)r  r   r  r6   )r  s    rD   _voice_record_keyr  9  s/     "&&|4J(S9j3z?VhVr   zvoice.togglec                    |j                  dd      }|dk(  rt               t               t               d}	 ddlm}  |       }t        |j                  d            |d<   t        |j                  d            |d<   t        |j                  d            |d<   |j                  d	      xs d
|d	<   t        | |      S |dv r_|dk(  }|rdndt        j                  d<   |s!	 ddlm}  |        dt        j                  d<   t        | |t               t               d      S |dk(  rQt               st!        | dd      S t                }	|	rdndt        j                  d<   t        | dt               |	d      S t!        | dd|       S # t        $ r }t        j                  d|       Y d}~d}~ww xY w# t        $ r Y t        $ r }t        j                  d|       Y d}~d}~ww xY w)u3  CLI parity for the ``/voice`` slash command.

    Subcommands:

    * ``status`` — report mode + TTS flags (default when action is unknown).
    * ``on`` / ``off`` — flip voice *mode* (the umbrella bit). Turning it
      off also tears down any active continuous recording loop. Does NOT
      start recording on its own; recording is driven by ``voice.record``
      (Ctrl+B) after mode is on, matching cli.py's enable/Ctrl+B split.
    * ``tts`` — toggle speech-output of agent replies. Requires mode on
      (mirrors CLI's _toggle_voice_tts guard).
    actionrN  )r  r  ttsr   )check_voice_requirementsr  audio_availablestt_availabledetailsr   z2voice.toggle status: requirements probe failed: %sN>   r  r  r  r  r  r  stop_continuousz3voice: stop_continuous failed during toggle off: %sr  r    z"enable voice mode first: /voice onTi  unknown voice action: )r   r  r  r
  tools.voice_moder  r   r5   r  r   ra  r,   r  r
  r  r
  r  )
r   r  r  r  r  reqsr  r  r  	new_values
             rD   r  r  9  s    ZZ(+F +,+-%'

	TA+-D#'(=#>GK )-dhh7H.I)JG%&'+DHH_,E'FGO$!%)!4!:GI 3  D. -4S

>"Y<! .1BJJ)*"/1)+
 	
 "$T#GHH*,,	09s

%&
 /1 
 	
 T3F8<==s  	T NNOQRSS	T*   YTVWXXYs6   A<F "F4 	F1F,,F14	G'?G'G""G'zvoice.recordc                    |j                  dd      }|dvrt        | dd|       S 	 |dk(  rt               st        | dd      S t        5  |j                  d      xs t        ad	d	d	       d
dlm} t               }|j                  d      }|j                  d      }t        |t        t        f      rt        |t              s|nd}t        |t        t        f      rt        |t              s|nd} |d d d ||d      }	|	du rt        | ddi      S t        | ddi      S t        5  |j                  d      xs t        ad	d	d	       d
dlm}
  |
d       t        | ddi      S # 1 sw Y   xY w# 1 sw Y   3xY w# t        $ r t        | dd      cY S t        $ r }t        | dt!        |            cY d	}~S d	}~ww xY w)a  VAD-bounded push-to-talk capture, CLI-parity.

    ``start`` begins one VAD-bounded capture and emits ``voice.transcript``
    after silence stops the recorder. ``stop`` forces transcription of the
    active buffer, matching classic CLI push-to-talk. The voice wrapper retains
    no-speech counts across single-shot starts, so three consecutive silent
    captures emit ``voice.transcript`` with ``no_speech_limit=True``.
    r  r   >   rZ
  r   r  r  r
  u+   voice mode is off — enable with /voice onr  Nr   )start_continuoussilence_thresholdsilence_durationr  g      @c                     t        dd| i      S )Nvoice.transcriptr   r  r  s    rD   r   z_.<locals>.<lambda>Y:  s    4FQR(T r   c                     t        dd| i      S )Nzvoice.statusr  r  )r  s    rD   r   z_.<locals>.<lambda>Z:  s    K!$M r   c                      t        dddi      S )Nr  no_speech_limitTr  r   r   rD   r   z_.<locals>.<lambda>[:  s    &):D(A) r   F)on_transcript	on_statuson_silent_limitr  r  auto_restartrN  rz  	recordingr  T)force_transcribestopped  u9   voice module not available — install audio dependencies)r   r  r  r  r  r
  r  r  r  r  r  r   ra  r  r
  r5   r6   )r   r  r  r  r  ro	  durationsafe_thresholdsafe_durationr  r  r  s               rD   r  r  ):  s    ZZ'*F&&C!7x@AA;'W&(C'TUU  P#)::l#;#O?O P : ()I!&9:I }}%78H i#u6"9d3  	  he5jSW>X  
 'TM! #1!."	G %36 233sX{344  	L%zz,7K;K	L 	5.39-..aP PT	L 	L  
R
 	
  'Cs1v&&'sf   F F 
E($B0F F #F )E5$F (E2-F 5E>:F GG!F<6G<Gz	voice.ttsc                 B   |j                  dd      }|st        | dd      S 	 ddlm} t	        j
                  ||fd      j                          t        | d	d
i      S # t        $ r t        | dd      cY S t        $ r }t        | dt        |            cY d }~S d }~ww xY w)Nr   r   i  rW  r   r
  TrY
  rN  speaking  zvoice module not available)r   r  r
  r
  r   r   r   ra  r
  r5   r6   )r   r  r   r
  r  s        rD   r  r  v:  s    ::fb!DC//'/
$FLLN3:.// =C;<< 'Cs1v&&'s#   :A B6B>BBBzinsights.getc           	         |j                  dd      }t               }|t        | d      S 	 t        j                         |dz  z
  }|j	                  dd      D cg c]  }|j                  d	      xs d
|k\  r| }}t        | |t        |      t        d |D              d      S c c}w # t        $ r }t        | dt        |            cY d }~S d }~ww xY w)Ndaysr  r  r  iQ r  T)r  r  ry  r   c              3   @   K   | ]  }|j                  d d        yw)rB  r   Nr  r  s     rD   r  z_.<locals>.<genexpr>:  s     Haoq 9Hs   )r  r   rn  )r   ra  r  r3   r"  ra  r  sumr5   r  r6   )r   r  r  rk  cutoffr  r$  r  s           rD   r  r  :  s    ::fb!D	B	z$St44'te|+ **4*H
l#(qV3 
 

 IH4HH
 	

  'Cs1v&&'s/   /B- !B(=*B- (B- -	C6CCCzrollback.listc                      t        |       \  }}|r|S 	  fd}t        ||      S # t        $ r }t         dt	        |            cY d }~S d }~ww xY w)Nc                    | j                   st        dg d      S t        d| j                  |      D cg c]8  }|j                  dd      |j                  dd      |j                  dd      d: c}d      S c c}w )	NF)r  r  Tr  r   r	  rK  )r  r	  rK  )r  ra  r  r   )r  r   r  r   s      rD   goz_.<locals>.go:  s    ;;3E" EFF# "%!5!5c!:$ 	 %&EE&"$5)*{B)?'(uuY';$
 $s   =A=r  )r  r  r5   r  r6   )r   r  r#  r  r  r  s   `     rD   r  r  :  sW    %LGS

'	$ !"-- 'Cs1v&&'s   ' 	AAAAzrollback.restorec                 h   t        ||       \  }|r|S |j                  dd      |j                  dd      st        | dd      S sj                  d      rt        | dd      S 	 fd	}t        | t	        |            S # t
        $ r }t        | d
t        |            cY d }~S d }~ww xY w)Nr  r   	file_pathr  hash requiredr  r[  uI   session busy — /interrupt the current turn before full rollback.restorec                    t        | |      }| j                  ||xs d       }|j                  d      rsd}d   5  j                  dg       }|rD|d   j                  d      dv r.|j                          |d	z  }|r|d   j                  d      dv r.|r,|d   j                  d      d
k(  r|j                          |d	z  }|r!t	        j                  dd            d	z   d<   d d d        ||d<   |S # 1 sw Y   xY w)N)r  r}  r   rO  rP  r  r)  >   r  r?  r   r*  r1  history_removed)r  r  r   r(  r  )	r  r   r  r  rA  rP  r  r#  r   s	         rD   r  z_.<locals>.go:  s   /S&AH[[h):Kt[LFzz)$Y^, %kk)R8G!gbkoof&=AV&V1 "gbkoof&=AV&V 72;??6#:f#D1,=q ABQF   12 -4()M s   AC:AC::Dr  )r  r   r  ra  r  r5   r6   )r   r  r  r  r  r  r#  r   s        @@@rD   r  r  :  s    %LGS

ZZ#F

;+IC// Y/W
 	

'	( 3)'2677 'Cs1v&&'s   +B 	B1B,&B1,B1zrollback.diffc                   	 t        ||       \  }}|r|S |j                  dd      		st        | dd      S 	 t        |	fd      }|j                  dd      d d }|j                  dd      |d	}t	        ||j                  d
d            }|r||d<   t        | |      S # t        $ r }t        | dt        |            cY d }~S d }~ww xY w)Nr  r   r  r  c                 >    | j                  |t        | |            S r   )diffr  )r  r   r   s     rD   r   z_.<locals>.<lambda>:  s    SXXc+CCf+UV r   r  r	  rQ  )rQ  r  r3  r4  rz  i  )r  r   r  r  rO   ra  r5   r6   )
r   r  r#  r  r  r  r  rz  r  r   s
            @rD   r  r  :  s    %LGS

ZZ#FC//'V
 eeFB&55,c:sGKK$;<"*GJ3   'Cs1v&&'s   A'B 	C(C=CCc                  f   t         j                  j                  dd      j                         } | r| S 	 ddlm}  |       }t        |t              r|j                  di       ni }t        |t              r-t        |j                  dd      xs d      j                         S 	 y# t        $ r Y yw xY w)u6  Return the configured browser CDP override without network I/O.

    ``/browser status`` must be fast — calling
    ``tools.browser_tool._get_cdp_override`` would invoke
    ``_resolve_cdp_override``, which performs an HTTP probe to
    ``.../json/version`` for discovery-style URLs.  That probe has
    a multi-second timeout and would block the TUI on a slow or
    unreachable host even though status only needs to report whether
    an override is set.

    Mirrors the env/config precedence of ``_get_cdp_override`` (env
    var first, then ``browser.cdp_url`` from config.yaml) without the
    websocket-resolution step, so the answer reflects user intent
    even when the configured host is not currently reachable.  The
    actual WS normalization happens in ``browser_navigate`` on the
    next tool call.
    BROWSER_CDP_URLr   r   r  browsercdp_url)
r,   r  r   r7   r^  r  r  r   r6   r5   )env_urlr  r  browser_cfgs       rD   _resolve_browser_cdp_urlr  ;  s    $ jjnn.399;G50:30Ecggi,2k4({y"5;<BBDD )   s   A-B$ $	B0/B0c                     	 | j                   xs d}| j                  dv }| j                  dv xr | j                  dv xr	 |dk(  xr |S # t        $ r Y yw xY w)u  Match the discovery-style local default; never the concrete WS form.

    A user-supplied ``ws://127.0.0.1:9222/devtools/browser/<id>`` is a
    real, connectable endpoint — collapsing it to bare ``http://...:9222``
    would strip the path and break the connect.
    r4  F>   r   r  /json/json/version>   wshttp>   	127.0.0.1	localhost$  )portr>  r.   schemehostname)r  r  discovery_paths      rD   _is_default_local_cdpr  -;  ss    {{ b [[$GGN' 	OO99	DL	 		  s   A	 		AAr  c                     dd l }	 |j                  j                  | |      5 }dt        |dd      cxk  xr dk  nc cd d d        S # 1 sw Y   y xY w# t        $ r Y yw xY w)Nr   r   r  rN  ,  F)urllib.requestrequesturlopenr   r5   )r  r   urllibr  s       rD   _http_okr  B;  s_    ^^##C#9 	=T'$#6<<	= 	= 	= s-   A A	A AA A 	A A c                     dddj                  | j                  | j                        }| d| j                   j                  d      }| d| dgS )Nr  https)r  wss://r  r  r  )r   r  netlocr   )r  r  r  s      rD   _probe_urlsr%  L;  sX    7+//v}}MFXS(//4DfM"tfEN33r   c                     | j                   j                  d      r| j                         S | j                  dddd      j                         S )N/devtools/browser/r   )r.   r  r  fragment)r.   r  geturl_replace)r  s    rD   _normalize_cdp_urlr+  R;  sC    
 {{23}}??2R"?ELLNNr   r  r@  c                 R    ddl m}  |||      }|rd|gndd| dg}d|  dg|d	S )
Nr   )manual_chrome_debug_commandzSStart a Chromium-family browser with remote debugging, then retry /browser connect:zNNo supported Chromium-family browser executable was found in this environment.zLInstall one or start a Chromium-family browser with --remote-debugging-port=z, then retry /browser connect.z Browser CDP is not reachable at r  uj   Browser not connected — start a Chromium-family browser with remote debugging and retry /browser connect)hermes_cli.browser_connectr-  )r  r  r@  r-  r   r  s         rD   _failure_messagesr/  \;  sl    F)$7G  
_`gh ]Z[_Z``~
 	 +3%q1	 	u r   r{   c                     |j                  dd      }|dk(  r"t               }t        | t        |      |d      S |dk(  rt	        |       S |dk7  rt        | dd|       S t        | |      S )Nr  rN  	connectedr  
disconnectconnectr
  zunknown action: )r   r  ra  r   _browser_disconnectr  _browser_connect)r   r  r  r  s       rD   r  r  o;  sw    ZZ(+F&(3d3i<=="3''C!1&:;;C((r   c           	         dd l }ddlm} ddlm} ddlm} |j                  d      }|3t        |t              s#t        | ddt        |      j                         S |xs dj                         xs |}|j                  d	      xs d|j                         }g d
ddt        dt        dd ffd}	 |d|v r|nd|       }
|
j                  dvrt        | dd|       S |
j                   st        | dd|       S 	 |
j"                  xs |
j                  dv rdnd}t'        |
      r|} ||      }
|
j"                  xs d}	 |
j                  dv rK|
j(                  j+                  d      r0dd l}	 |j/                  |
j                   |fd      5  	 d d d        net'        |
      r*dd!lm}m}m}m}  ||d      }|}| ||      r ||      } |	d"| d#| d$       n |	d%        |||      }|j:                  rht=        j>                         d&z   }t=        j>                         |k  r: ||d'      }|rn-t=        j@                  d(       t=        j>                         |k  r:|r |	d)|        nR|jB                  }|r
 |	|d*       tE        |||      d+d  D ]  } |	|d*        tG        | d,|d-      S  |	d.|        |} ||      }
n/tI        |
      }tK        d/ |D              }|st        | dd|       S tM        |
      } |        |tN        jP                  d0<    |        d1|d2}r|d3<   tG        | |      S # t$        $ r t        | dd|       cY S w xY w# 1 sw Y   xY w# t0        $ r}t        | dd| d |       cY d }~S d }~ww xY w# tR        $ r }t        | dt        |            cY d }~S d }~ww xY w)4Nr   )DEFAULT_BROWSER_CDP_URLcleanup_all_browsers)urlparser  r
  z"browser url must be a string, got r   r  rH  )r  rK  r  r   c                N    j                  |        rt        d| |d       y y )Nzbrowser.progress)rK  r  )r  r  )rK  r  rn  r-  s     rD   announcez"_browser_connect.<locals>.announce;  s+      $cw+OP r   r#  zhttp://>   r  r"  r  r!  zunsupported browser url: zmissing host in browser url: >   r"  r!  i  r4  zinvalid port in browser url: r  >   r  r"  r'  r	  r   r8  zcould not reach browser CDP at r%   )discover_local_cdp_urlfind_free_debug_portlaunch_chrome_debuglocal_port_in_usezPort u    is occupied by another application that isn't a CDP browser (an IDE debugger or dev server may be using it) — launching a debug browser on port z instead...uW   Chromium-family browser isn't running with remote debugging — attempting to launch...g      $@g      ?r  z7Chromium-family browser launched and listening on port r   r   F)r2  r  rn  z0Chromium-family browser is already listening at c              3   6   K   | ]  }t        |d         yw)r	  r   N)r  r  s     rD   r  z#_browser_connect.<locals>.<genexpr>;  s     >!Xa-->s   r  Tr1  rn  )*r  r.  r8  tools.browser_toolr:  urllib.parser;  r   r  r6   r  r  r9   r7   r@  r  r  r  r>  r  r.   r  socketcreate_connectionr	  r>  r?  r@  rA  launchedr3   r  r  r  r/  ra  r%  r  r+  r,   r  r5   )r   r  r  r8  r:  r;  raw_urlr  r@  r=  r  r  rE  r  r>  r?  r@  rA  r  launch_portlaunchdeadliner  r   probesr   r  r  rn  r-  s                               @@rD   r6  r6  ;  s(   B7%jjG:gs#;;DM<R<R;ST
 	
 =b


!
<%<C
**\
"
(bC__FH/5 Q# Q Q$ Q Uc\c?F}}::C!:3%@AA??C!>seDEEF{{Pfmm7G&GsR V$%#{{"d\' ==M)fkk.D.D /
 U--v.Es-S  #6*  0cBJK!$T*"6t"<Kv &N '-{4 q -[&A??  $~~/$6H..*X5%;KQT%U
%!

3	 ..*X5 QR]Q^_ ";;D W5 1#{F KAB O 6 W565(S  KJ<XY Cc]F (F>v>>BC)H'NOO'/
 	(2

$% 04J!GG&
sGW  FC!>seDEEF(  UC)HRPQs'STTU^  'Cs1v&&'s    M
 -N 6M6 M)M6 CN ,AN AN ,N 
M&%M&)M3.M6 6	N?NNN NN 	O(O=OOc                     dd} |        t         j                  j                  dd         |        t        | ddi      S )Nc                  >    	 ddl m}   |         y # t        $ r Y y w xY w)Nr   r9  )rC  r:  r5   r9  s    rD   reapz!_browser_disconnect.<locals>.reap<  s"    	? " 		s    	r  r2  Fr   )r,   r  r(  ra  )r   rO  s     rD   r5  r5  <  s8     	FJJNN$d+Fs[%())r   zplugins.listc                 $   	 ddl m} t        | d |       j                  j	                         D cg c]!  \  }}|t        |dd      t        |dd      d# c}}i      S c c}}w # t        $ r }t        | d	t        |            cY d }~S d }~ww xY w)
Nr   )get_plugin_managerpluginsr  ?r  T)rI   r  r  r  )	r  rQ  ra  _pluginsrf  r   r5   r  r6   )r   r  rQ  rc  r"  r  s         rD   r  r   <  s    '9 !3 4 = = C C E 1	 !"#*1i#=#*1i#>	
 	
  'Cs1v&&'s.   /A& &A A&  A& &	B/B
B
Bzconfig.showc                    	 t               }t               }t        j                  j	                  dd      xs |j	                  dd      }t        |      dkD  rd|dd   nd}t        j                  j	                  dd      xs |j	                  d	d      }d
d
|gd|xs dgd|ggdddt        t        |d            gddj                  |j	                  dg             xs dgdt        |j	                  dd            ggdddt        j                         gdt        t        dz        ggdg}t        | d|i      S # t        $ r }t        | dt        |            cY d }~S d }~ww xY w)NHERMES_API_KEYr   rG  r  z****z	(not set)HERMES_BASE_URLr  ModelzBase URLz	(default)zAPI Key)r  r$  Agentz	Max Turnsr  Toolsetsr  r,  r  Verboser  FEnvironmentzWorking DirzConfig Filer  r  r  )r  r  r,   r  r   r  r6   r  r*   r   r  ra  r5   r  )	r   r  r  r   rG  r  r  r  r  s	            rD   r  r  6<  sv   "'k **..!126P#'')R:P*-g,*:4~&::>>"3R8SCGGJPR<S !e$!8[9' ! #nS"&=">?3773Er+J!K!TuUCGGIu$= >? '"BIIK0"C}(D$EF#
2 3X.// 'Cs1v&&'s   D<D? ?	E(E#E(#E(z
tools.listc           	         	 ddl m}m} t        j	                  |j	                  dd            }|rt        t        |d   dg       xs g       nt        t               xs g       }g }t         |       j                               D ]3  } ||      }|s|j                  ||d   |d   |r||v nd	|d
   d       5 t        | d|i      S # t        $ r }	t        | dt        |	            cY d }	~	S d }	~	ww xY w)Nr   get_all_toolsetsget_toolset_infor  r   rN  r,  r  r  Tresolved_tools)rI   r  r  r  r`   r"  r8  r"  r`  ra  rQ   r   r^  r   r3  r!  r  r  ra  r5   r  r6   
r   r  r`  ra  r#  r  rf  rI   rH  r  s
             rD   r  r  ]<  s   '?--

< <=  (*<bAGRH+-34 	 +-2245 	D#D)DLL #'#6"&|"429twt!"23		 3U+,, 'Cs1v&&'s   CC	 		C2C-'C2-C2z
tools.showc           
         	 ddl m}m} t        j	                  |j	                  dd            }|rt        |d   dd       n	t               } ||d      }i }t        |d	 
      D ]  }|d   d   }	t        |d   j	                  dd      xs d      j                  d      d   }
d|
v r|
d |
j                  d      dz    }
|j                   ||	      xs dg       j                  |	|
d        t        | t        |j                               D 	cg c]
  \  }	}|	|d c}}	t        |      d      S c c}}	w # t         $ r }t#        | dt        |            cY d }~S d }~ww xY w)Nr   )r  get_tool_definitionsr  r   rN  r,  T)r,  r-  c                     | d   d   S )Nr  rI   r   r  s    rD   r   z_.<locals>.<lambda><  s    *f0E r   r  r  rI   r  r   z. r   rT  rI   r  )rI   r`   )r  r  rs  )r  r  rf  rQ   r   r   r3  r!  r6   r  r  rf  r  ra  rf  r  r5   r  )r   r  r  rf  r#  r  r`   r  r  rI   r  r$  r  s                rD   r  r  |<  s|   #'J--

< <=  GG$&8$?') 	
 %g$O5&EF 
	D
#F+DtJ'++M2>D"EKKDQRSTDt|2djj.23 4T : GiLSS #'
	  '-X^^-=&>"d "D1 U	
 		
  'Cs1v&&'s0   DD: D4 D: 4D: :	E#EE#E#ztools.configurec           
         t        |j                  dd      xs d      j                         j                         }|j                  dg       xs g D cg c]5  }t        |      j                         st        |      j                         7 }}|dvrt	        | dd|       S |st	        | dd      S 	 d	d
lm}m} d	dlm	}m
}m}	m}
m}  |       }|D ch c]  \  }}}|
 c}} |       z  }|D cg c]	  }d|vs| }}|D cg c]	  }d|v s| }}|D cg c]	  }||vs| }}|D cg c]	  }||v s| }}|r |	|d||       |r
 ||||      n	t               } ||       t        j                  |j                  dd            }|rt!        |j                  dd      |      nd }t#         |
 |       dd            }|D cg c]#  }||vrd|vs|j%                  dd      d	   |vr|% }}t'        | |||t#        |      t)        |      |d      S c c}w c c}}w c c}w c c}w c c}w c c}w c c}w # t*        $ r }t	        | dt        |            cY d }~S d }~ww xY w)Nr  r   r  >   r  disabler^  zunknown tools action: r
  znames requiredr   )r  save_config)CONFIGURABLE_TOOLSETS_apply_mcp_change_apply_toolset_changer  _get_plugin_toolset_keysr  r8  r  Fr  r   )changedr,  rH  missing_serversr  rT  r~  )r6   r   r7   r  r  r^  r  rk  r$  rl  rm  rn  r  ro  r^  rQ   rX  r!  r  ra  r   r5   )r   r  r  rI   targetsr  rk  rl  rm  rn  r  ro  r  ts_keyr  valid_toolsetstoolset_targetsmcp_targetsrT  rq  r#  rH  r  rp  r  s                            rD   r  r  <  s   Hb)/R0668>>@F&,jj"&=&C"s4yGXD	G  **C!7x@AAC/007'>	
 	
 m'<
#vq!F
$&' -4GDs$4GG(/?3$;t??$3RDt>7Q4RR,;VDt~?U4VV!#uovF <Gc;7CE 	 	C--

< <=  !L"!=wG 	
 uRWX

  
7"DDJJsA$6q$9$P 
 
 "$+#)/#:g"

 
	
g&
 H?RV&
$  'Cs1v&&'s   H3H4"H? H #H? 3	H&=H&H? 	H+H+H? 	H0%H0)H? /	H59H5=BH? (H:4&H?  H? ?	I(I#I(#I(ztoolsets.listc                    	 ddl m}m} t        j	                  |j	                  dd            }|rt        t        |d   dg       xs g       nt        t               xs g       }g }t         |       j                               D ]/  } ||      }|s|j                  ||d   |d   |r||v nd	d
       1 t        | d|i      S # t        $ r }	t        | dt        |	            cY d }	~	S d }	~	ww xY w)Nr   r_  r  r   rN  r,  r  r  T)rI   r  r  r  r"  r  rc  rd  s
             rD   r  r  <  s    '?--

< <=  (*<bAGRH+-34 	 +-2245 	D#D)DLL #'#6"&|"429twt			 3U+,, 'Cs1v&&'s   CC 	C.C)#C.)C.zagents.listc                     	 ddl m} |j                         }t        | d|D cg c]  }|d   |d   d d |d   |d   d	 c}i      S c c}w # t        $ r }t        | d
t        |            cY d }~S d }~ww xY w)Nr   rI
  rP  r  r   r4  rN  uptime_seconds)r  r   rN  uptimerg  )r:
  r2
  rL  ra  r5   r  r6   )r   r  r2
  procsr  r  s         rD   r  r  =  s    '; ..0 #  '(o#$Y<#4"#H+"#$4"5	

 	
  'Cs1v&&'s.   !A A A A 	A6A1+A61A6zcron.managec                    |j                  dd      |j                  dd      }}	 ddlm} |dk(  r&t        | t	        j
                   |d                  S |dk(  rIt        | t	        j
                   |d	||j                  d
d      |j                  dd                        S |dv r't        | t	        j
                   |||                  S t        | dd|       S # t        $ r }t        | dt        |            cY d }~S d }~ww xY w)Nr  r_  rI   r   r   )cronjob)r  r%  createscheduler  )r  rI   r  r  >   r  remover  )r  job_idr\  zunknown cron action: i  )	r   tools.cronjob_toolsr}  ra  r   r   r  r5   r6   )r   r  r  jidr}  r  s         rD   r  r  =  s    **Xv.

620FCF'/VsDJJwf'=>??U?

' !'J!;%zz(B7	
 
 22sDJJwfS'IJKKC!6vh?@@ 'Cs1v&&'s0   0C  AC  %*C  C   	D	)D>D	D	r   c                    	 t        |j                  dd      xs d      }t        |j                  dd      xs d      }t        |j                  dd      xs d      }	 dd	lm} dd
lm}  |       }t        |  ||t        d|      t        d|      |            S # t        t        f$ r	 d\  }}}Y Uw xY w# t        $ r}t        | dd|       cY d}~S d}~ww xY w)u'  Pre-render the learning timeline for the TUI ``/journey`` overlay.

    Returns ``frames`` (reveal 0→1) plus static legend/summary/bucket metadata,
    so Ink can render and walk the tree locally without round-tripping the
    gateway. Shares its renderer with the ``hermes journey`` CLI.
    r3  r4  r$     r  0   )r4  r  r  r   )build_learning_graph)render_framesr{
  r   )r3  r$  r  r=  zlearning.frames failed: N)r  r   rS  r>  agent.learning_graphr  agent.learning_graph_renderr  ra  rF  r5   r  )	r   r  r3  r$  r  r  r  r  r!  s	            rD   r  r  :=  s    (6::fb)/R06::fb)/R0VZZ"-34A==&(3gCDMBPT^deff z" ('dF(  AC!9#?@@As0   AB  <B8 B54B58	CCCCzlearning.detailc                     	 ddl m} t        |  |t        |j	                  dd                        S # t
        $ r}t        | dd|       cY d}~S d}~ww xY w)z7Current content of a journey node, for an edit prefill.r   )node_detailr   r   r=  zlearning.detail failed: N)agent.learning_mutationsr  ra  r6   r   r5   r  )r   r  r  r!  s       rD   r  r  R=  V    A83C

4(<$=>?? AC!9#?@@A   03 	AAAAzlearning.deletec                     	 ddl m} t        |  |t        |j	                  dd                        S # t
        $ r}t        | dd|       cY d}~S d}~ww xY w)uM   Delete a journey node — skills are archived (restorable), memories removed.r   )delete_noder   r   r=  zlearning.delete failed: N)r  r  ra  r6   r   r5   r  )r   r  r  r!  s       rD   r  r  ]=  r  r  zlearning.editc                     	 ddl m} t        |  |t        |j	                  dd            t        |j	                  dd                        S # t
        $ r}t        | dd|       cY d}~S d}~ww xY w)	z<Rewrite a journey node's content (SKILL.md or memory chunk).r   )	edit_noder   r   r+  r=  zlearning.edit failed: N)r  r  ra  r6   r   r5   r  )r   r  r  r!  s       rD   r  r  h=  sf    ?63	#fjjr&:";SIWYAZ=[\]] ?C!7u=>>?s   A
A 	A0A+%A0+A0rz   c                 ^   |j                  dd      |j                  dd      }}	 |dk(  rddlm} t        | d |       i      S |dk(  rXdd	lm}m}m}  || | |             d
d      xs g }t        | d|D 	cg c]  }	|	j                  |	j                  d c}	i      S |dk(  r/ddl
m}
  G d d      } |
|d |              t        | d|d      S |dk(  rqddl
m} t        |j                  dd      xs d      xs |j                         rt        |      nd}t        |  ||t        |j                  dd                        S |dk(  rddl
m} t        | d ||      xs i i      S t!        | dd |       S c c}	w # t"        $ r }t!        | d!t%        |            cY d }~S d }~ww xY w)"Nr  r_  r  r   r   r  r   rZ  )
GitHubAuthcreate_source_routerunified_searchr  r{
  )source_filterr  r]  rh  install)
do_installc                       e Zd Zd Zy)_.<locals>._Qc                      y r   r   )r   r   r  s      rD   r:   z_.<locals>._Q.print=  s    r   N)r9   r   r   r:   r   r   rD   _Qr  =  s    r   r  T)skip_confirmconsole)r)  rI   r  )browse_skillsr^  r   	page_size)r^  r  r
  )inspect_skillrH  r^  zunknown skills action: i  )r   r  r  ra  tools.skills_hubr  r  r  rI   r  hermes_cli.skills_hubr  r  r  isdigitr  r  r5   r6   )r   r  r  r  r  r  r  r  r  r  r  r  r  pgr  r  s                   rD   r  r  s=  s   JJx0&**Wb2IEF5'V>sX';'=>??X  (6"'	    PS KLF   Y8  u4>s$>??X;VZZ*/a0 #mmoE
1  ]c&**[RT:U6VW  Y;sV]5%9%?R@AAC!8ABB7 8  'Cs1v&&'sN   F 5F 9 E>F !3F A5F "F .F >F 	F,F'!F,'F,zskills.reloadc                 F   	 ddl m}  |       }|j                  d      xs g }|j                  d      xs g }t        |j                  d      xs d      }dg}|s|s|j	                  d       |r)|j	                  d       |j                  d	 |D               |r)|j	                  d
       |j                  d |D               |j	                  | d       t        | dj                  |      |d      S # t        $ r }t        | dt        |            cY d }~S d }~ww xY w)Nr   )reload_skillsrb  rA  r  zReloading skills...zNo new skills detected.zAdded skills:c              3   F   K   | ]  }d |j                  dd         ywz  - rI   r   Nr  r  s     rD   r  z_.<locals>.<genexpr>=  s#     I44 456I   !zRemoved skills:c              3   F   K   | ]  }d |j                  dd         ywr  r  r  s     rD   r  z_.<locals>.<genexpr>=  s#     K44 456Kr  z skill(s) availabler   )r   r  r  )r  r  r   r  r  r#  ra  r*   r5   r  r6   )	r   r  r  r  rb  rA  r  r	  r  s	            rD   r  r  =  s    '6

7#)r**Y'-2FJJw',1-&'WLL23LL)LLI5IILL*+LLK7KKw1233499U#3vFGG 'Cs1v&&'s   C4C7 7	D  DD D r}   c           	         |j                  dd      }	 ddlmmmm fd}|dk(  r5 |       }t        d |D              }t        | ||t        |      |z
  d      S |dk(  rdd	lm	} |j                  d
      xs dj                         st        | dd      S t        |j                  d            } ||      }|j                  d      s t        | d|j                  d      xs d      S t        fd |       D        d      }	t        | dt        |j                  d            |	d      S t        | dd|       S # t        $ r }
t        | dt        |
            cY d}
~
S d}
~
ww xY w)u=  List installed plugins with activation state, or toggle one on/off.

    Backs the TUI Plugins Hub. Uses the same disk-discovery + enable/disable
    primitives as ``hermes plugins`` / the dashboard, so the three surfaces
    agree on what's installed and what's enabled.

    Actions:
      - ``list``   → {"plugins": [{name, version, description, source,
                       status}], "user_count": N, "bundled_count": M}
      - ``toggle`` → flip ``name`` based on ``enable`` (bool). Returns the
                       refreshed row plus {"ok", "unchanged"}.
    r  r_  r   )_discover_all_plugins_get_disabled_set_get_enabled_set_plugin_statusc                              }  
       }g }t         	             D ];  \  }}}}}}|j                  |t        |xs d      |xs d| || ||      d       = |S )Nr   r  )rI   r  r  rB  rN  )r!  r  r6   )r  r1  r  rI   r  r  rB  _dirrw  r  r  r  r  s            rD   _rowsz_.<locals>._rows=  s    &(G(*HC:@%'; 6gtVT3 

 $#&w}"#5'+zr"("0wc"R Jr   c              3   2   K   | ]  }|d    dk7  sd  yw)rB  bundledr   Nr   r  s     rD   r  z_.<locals>.<genexpr>=  s     I1(y0HQIs   )rR  
user_countbundled_countrw  )"dashboard_set_agent_plugin_enabledrI   r   r  z plugins.toggle requires a 'name'r  )r  r   r  r   ztoggle failedc              3   4   K   | ]  }|d    k(  s|  yw)rI   Nr   )r  r  rI   s     rD   r  z_.<locals>.<genexpr>>  s     @aai4.?@r(  NT	unchanged)r   r  rI   r  r^  zunknown plugins action: )r   hermes_cli.plugins_cmdr  r  r  r  r  ra  r  r  r7   r  r   r  r5   r6   )r   r  r  r  r$  r  r  r  r  rl  r  r  r  r  r  rI   s              @@@@@rD   r  r  =  st    ZZ&)F='	
 	
	$ V7DIIIJ#",%(Y%;  XQJJv&,"335DC'IJJ&**X./F7fMF::d#Cvzz'':'MoNN@57@$GC!%fjj&=!> !	  C!9&BCC 'Cs1v&&'s8   AE '<E $AE 9AE <E 	E5E0*E50E5rl   c           	         |j                  dd      }|st        | dd      S 	 ddlm}m}  ||      \  }}|rt        | dd| d	      S  ||      \  }}}	|rt        | dd
|	 d	      S 	 	 t        j                  |ddddt        j                         t        j                        }
t        | |
j                  dd  |
j                  dd  |
j                  d      S # t
        $ r t        | dd      cY S w xY w# t        j                  $ r t        | dd      cY S t         $ r }t        | dt#        |            cY d }~S d }~ww xY w)Nr   r   r4  r  r   )detect_dangerous_commanddetect_hardline_commandr|  zblocked (hardline): z'. Use the agent for dangerous commands.z	blocked: rv  z=shell.exec unavailable: approval safety module not importableTr  )r  r  r   r   r   r   rK  i0)r   r<   r  i  zcommand timed out (30s)i  )r   r  rv  r  r  r
  r   r   r,   r   r  ra  r   r<   r   r  r5   r6   )r   r  r  r  r  is_hardlinehardline_descis_dangerousr  r  r  r  s               rD   r  r  >  se   
**Y
#CC//`T%<S%A"]T1-@gh  !9 =aTYtf,ST  'NNtDtRRYY[$$
 ((56*((56*
 	
  `C^__` $$ :C899 'Cs1v&&'s<   %C 	C *A/C6 C32C36 E E  D;5E ;E r   )rI  r   )r]  )r  )r   )NNNNr  )r  rF  )NNNNNNN)r4  NNN)g?(  atexitconcurrent.futures
concurrentr1  r  rV  r
  r   rs  r,   r   r   r;   r   r3   rt  r   r	  r   typingr   r   r	   r=  r
   r   r   r   hermes_cli.env_loaderr   utilsr   r  r   agent.replay_cleanupr   r  r   tui_gateway.transportr   r   r   r   r   rt  r9   r  r  __file__r  r.   r*   r0   rE   
excepthookrL   r  rM   r5   tui_gateway.renderrN   rO   rP   rQ   r   r6   ri  rR   r|  rS   tuplerw  rT   rU   r  rV   r   _stdout_lockrS  RLockre  rx  rW   rX   r  rT  r  r  r   _slash_timeoutr>  rS  rF  r   _ws_orphan_reap_gracer  r  r!  r  r  r  _rpc_pool_workersfuturesThreadPoolExecutorr   registerr   r   r<   r   r  r  r   r  r   r  r  r"  r,  r6  rE  rH  rq  rx  rz  r|  r~  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  ra  r  r  r  r  r  r  r  r	  r  r  r-  r,  r  r  r"  r/  r<  r>  rI  rV  rb  rg  rq  r|  r  r  ra  r  r  r  r  r  r  r  r  r  r  r  r  run_git_gitr6  r5  	repo_rootr  common_repo_rootr  r  r  r;  r  r  r  r2  r  r&  r/  contextmanagerr  r  r?  rD  r/  rM  rN  rO  rI  r  r  rU  r_  rc  r_  r  r  ro  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  r3  r7  r:  r<  r?  rE  rK  rT  r  r  r  r  r  r  r  r  r  r  r  rR  r'  r)  r-  r/  r:  rA  rE  objectrI  rQ  rT  rd  rn  r{  r  r  r  r  r  r  r  r  r  r  r   r  r
  r  r  r  r  r"  r&  r8  r;  rC  rG  rS  rX  r  rf  r{  r  r  r  r  r  r  r  r  r  r  r  r  r  r  rQ  r  r  r  rT  r  r  r  r0  r3  r6  r  r  rf  rj  r  rr  rq  r  rv  rC  r  r  r  r  r  r  r  r  r  r  r  r  r\  re  rq  r  r^  rr  r  r  r  r  r  r  r  r  r	  r  r	  r	  r<	  rI	  r	  r	  r	  r	  r	  r 
  r"
  r%
  r0
  rG
  rW
  r  r  r  r  r  r
  r  r
  r
  r
  r
  r.  r0  r5  r7  r:  r>  rA  rF  rI  rk  r  r  r  r  r  r  r  r  r  r  r  r
  r  r!  rN  rh  rp  rw  ry  r  r  r  r  r  r  r  r  r  r#  r7  r:  rA  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r
  r  r  r  r  r  r%  r+  r/  r6  r5  r   r   rD   <module>r     s9           	   
      , ,  5 ! : 8 !  
		8	$  $x.*?*?*F*F*O WW\\,0GH
44 : *	 	7 Q P	4T	?  "$sH}
 "35$sE#y.//
0 58: $sE#t)$445 :$sCx. 
	3: y~~INN	 "y~~
D4K 
EDL 	%y~~' 2::>>*FGO4PN c>2 !!


:;Ct
 c#89 F => OQf	3rzz~~;<CD
 	--!  	. 	 G H
 zzZZ
  ""6E 
 () y yxJs JL$ L EI!$t7:Tz	( 	  	
 3d
?(	M$+ 	M$ 	M3	33 	3
 
3x ! "  S T 0Mtd{ M Md M` BM td{ 3 QU @ d t C D4K , 0;D[),	 9D 
c 
# 
 
>TD[ >T ># $ B %4"!"
38_"J=%2::>>*DEQRN S.)7T 7Xs XT X X$ X"C  	83 	8 	8$ 	8:&	8 " #  $> >K3: K$+ K"4 ) 9$+ 9#* 9$$+ #* 0d
 "Pc P@D @T @*H H3 H H    .	 0 >D >5 5 5 4$; $ (dTk (# C $ c d 06dTk 6d 6
= =dTk =d =B,C ,c ,D , ,RV ,:E E# E EC ETX E6 	  	
 D[  
&, ,4$; ,4 ,,B B3 BcDj B M# Ms Ms Md t ;T ;d ;RC Rc Rd R C E#sD.$9D$@ &	 	 	&$ &8I#6 &$+ &R1 1C 1% 14$; 1p9C p9$ p94 p9fL
$# # D4K 3 2&!t &! &!X && ",,  ) : : $$ $+ # $ $ $N-D -
$+ # 2'TD[ 'S '
4$; 
4 
nD nT nbF$ F4 F:   6 Ht  H#  H$  HFd   F &N 5c? M $) !13 ../ +8C 8# 8S 8S 8$+ cSVh < 4  F   4  c c $  		t 	
 
<4 D +# C $  s :d
 d &d & .3 4
'cDj 
'S 
'+C$J +3 +eCHo @ %S4Z"8  J ; X4$; X4 Xv74$; 7$ 7t$N4$; $N4 $NNT T T*+M +M +Ms +MW[ +M\	 	 56 67	9S 	9c  
5 
5	
 i y Y U E 	% 
5 	% g E W  
5! (T c 4
8# 
8td{ 
8
C$J 
 Pd P-C - 
G# 
GVS	D 0 VrQS QS Q9# 9$ 95 5 5-s -T -.2(	D 	
$+ 
$ 
: %*!%#$(N	NN N
 "N N *N TkN 
Nb,
s ,
T ,
d ,
b # $#'"&2121t21 :21 D[	21
 4Z21 3921r !%!%V	VV 	V
 V 
Vr9 9x	 	&d &s &Bs    HTD[ HT Hs td{ :C$+ C CLC t   d t " $   ! ! !H+3 +3 +)$ )3 ))f ) )6 6 67V 7C 7C$J 7/ /S /edl /sTz /8* *3 *c * *6,-3 ,-c ,- ,-D ,-RU ,-d r7	r7r7 *r7 4Z	r7
 $;r7| #%S$Y $$inn& 
 (* De$ )  F F F
:0# :0 :0 :0zFC FD FR8`c 8` 8`S 8`$ 8`v+ +@ K$+ K KA A4$; A%S/ A(3  BD+	++),+;>+
4+\N Ns Ns N	tCy 	+"#S #T #L	C 	D 	8d 8# 8TW 8cghlcm 8v7s 7C 7C 7,s S T D%c %D %T %PGC G4 GT  #'54K55v "(,$(-1(,$(v	v	v d
v
 3J%v Tzv  $d{v :v Tzv| c+	c+	c+ 	c+
 c+ 
tc+ $Jc+LP# PGNs N N N# %S/ "4C "4d3i "4C "4J3 3 <T# T# Tn9$t* 9d 9x T
 03 3 <0# 0# 0$ c d 
$D 
$ 
$ 
$$$ $4 $FT F F F F( Z  Zt  ZC  ZD  ZF+*+* +*(++*8;+*	D[+*\"3 " "$ "J   ,T ,dTk ,$ T4 TD T Tn *'4 *'D *' *'Z (.4 (.D (. (.V )4 )D ) )" S4 SD S S. 13B 3 # c 4 4  %*. $,033 3 
	3
 3 3 3 !4K3 +3 3 #Tk3 
3l	(,
39$s 5 D  t4 tD t tn 4 D  0s s 
c 
D 
S 
d s  C C C $ S $ : ;=  C  3 5d3Cd3J D T & "&#	## *	#
 # 4# 
#L "(4 "(D "( "(J 4 D  . &)4 &)D &) &)R P'4 P'D P' P'ftd{ & 7$4 7$D 7$ 7$t T4 TD T Tn 4 D  4 74 7D 7 7. 4 D  . #$4 D  %:d  ))..* (* D% * % EDL  	 	 	$ 8'5 '('u (' ('V(*DI ** 
,4 ,D ,  ,0 ,4 ,D ,  ,* d,4 d,D d,  d,N NF4 NFD NF  NFb <4 <D <  <2 <4 <D <  <8 <4 <D <  <2 !<4 !<D !<  !<H 54 5D 5  5B 	=4 	=D 	=  	= ;4 ;D ;  ;& 06 6u 6$ 6 .1 `s `S `& "9>># 5C   0"	BJJNN;<UDT@UV   B&3 &4 &"s "t "
'S 'T '
&s &t &
 
"4 
"D 
" 
" ?4 ?D ? ?< m>4 m>D m> m>` _;4 _;D _; _;\ T  FOt Od$T $  c4 cD c c$  T B :4 :D : :9D 9x h4 hD h h$ $ N4 ND N  N0 N4 ND N N, N4 ND N N" "f4 "fD "f  "fL f4 fD f f2  N4 ND N !N8 N4 ND N N* %`4 %`D %` %`P 924 92D 92 92x 4 D  , *4 *D * *6 t'4 t'D t' t'n 3'4 3'D 3' 3'l (4 (D ( ( PP4 PPD PP PPf =/4 =/D =/ =/L 4 D  & :4 :D : : ?4 ?D ? ?&  # @ @$ @4: ( 'C4 'CD 'C 'CT /24 /2D /2 /2d 4 D  . T4 TD T T0 /4 /D / / s-4 s-D s- s-lVs VT V VQU Vr(# ( (4 (D (DD T "t " "Jp3p3&)p348p3	p3f*?Z
C 
$ 
9?? 
y yt y3 y4 yx $4 $D $ $N ''4 ''D '' ''X + (  /eE%*%s*+ s C EDL 0  c &M9S> M4 E  PS X\ * 94 9D 9 9x w
4 w
D w
 w
t $(  S S ,%$ % % %T d %C %C %$ # $ F# F$+ F"># >% >,&"&" &" 	&"
 &" 4:&"R +'4 +'D +' +'\ 4 D  & +'4 +'D +' +'\ **4 **D ** **Z m*4 m*D m* m*f 16 & +4 +D + +  )4 )D ) !)
 A4 AD A A >4 >D > > '4 'D ' '0 y94 y9D y9 y9D S St 3 8  /"- - #- .!P P "P #$C C %C$ #$K K %K '(	K 	K )	K *+K K ,K ()K K *K $%- - &- #$- - %- '(< < )<
 $%s s &sX X X /c /d /& )-t F FT
 FR !"'4 'D ' #'  '4 'D ' !'4 #)  $ B!5!537!5
4:tDz4:sTz9:!5H(,=@VZ
4t, '4 'D ' '4 #$'4 'D ' %'2 a94 a9D a9 a9H '4 'D ' ' B84 B8D B8 B8P '4 'D ' '  " '4 'D ' ' '4 'D ' ', _'4 _'D _' _'D '4 'D ' '( (Ys^ 	*
DsC}%& 	  +4+ 3   ,5j&5I+J )C. J _'4 _'D _' _'DDI #*   
'4 'D ' '> '4 'D ' '&   _O4 _OD _O _OH  4 D  8   $ & #INN$ 35d3eT#Y.//0 5\3 \49 \~4s 43 45c?T3I 4n @&4 @&D @& @&F;C ;s ;D ;04	Ks KtDzD'8 K\ K'4 K'D K' K'\ ''4 ''D '' ''T R'4 R'D R' R'j 0'4 0'D 0' 0'l !*
!  #,,H"I )t ) )X # 2/ / / + +# +\t  "*# *&t & &8C 8(4. 8 8RU 8ZbcfZg 8xnC n$ n n nb }'4 }'D }' }'F !).." # s TD[ D 	=T 	=AD A
< <"W3 W ]>4 ]>D ]> ]>@ I'4 I'D I' I'X '4 'D ' '$ '4 'D ' '6 '4 'D ' ': +'4 +'D +' +'\ '4 'D ' '2# BT *#  $ 449 4O# O3 c 3 49 & )4 )D ) ) L$ L4 L^* *" '4 'D ' '* #'4 #'D #' #'L '4 'D ' '< $'4 $'D $' $'N A'4 A'D A' A'H '4 'D ' ': '4 'D ' '. '4 'D ' '4 A4 AD A A. A4 AD A A A4 AD A A ?4 ?D ? ? 7'4 7'D 7' 7't '4 'D ' '0 K'4 K'D K' K'\ #'4 #'D #' #'yl  		, 	I N$ 	I ! !L 	I L 	: %8_N%@X 	: 0/0s   >A|( %A|4 %A} ,A} 
%A}$ D86A}: |(A|1|0A|1|4	A}} A}}	A}}A}}	A}!} A}!}$A}7}6A}7}:A~	~A~	