
    ,j                   D   d Z ddlm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 ddlmZ dd	lmZmZmZ dd
lmZmZm Z  ddl!m"Z"m#Z# ddl$m%Z% ddl&m'Z'm(Z(m)Z)m*Z*  ej+        d          Z, G d d          Z-dS )u  Gateway slash-command handlers for GatewayRunner.

Extracted from ``gateway/run.py`` (god-file decomposition Phase 3b). These are
the in-session slash commands (/model, /reset, /usage, /compress, ...) the
gateway dispatches from ``_handle_message``. There are 42 of them (~3,200 LOC);
lifting them into a mixin that ``GatewayRunner`` inherits keeps every
``self._handle_*_command`` dispatch + test reference working via the MRO, while
removing the bulk from run.py.

Module-level run.py helpers a handler needs (``_hermes_home``,
``_load_gateway_config``, ``_resolve_gateway_model``, etc.) are imported lazily
inside the handler body — a deferred ``from gateway.run import ...`` resolves at
call time (run.py fully loaded by then), avoiding an import cycle.
    )annotationsNdatetime)Path)AnyOptionalUnion)fetch_account_usagerender_account_usage_lines)t)HomeChannelPlatformPlatformConfig)EphemeralReplyMessageEventMessageType)SessionSourcebuild_session_key)cfg_get)atomic_json_writeatomic_yaml_writebase_url_host_matchesis_truthy_valuezgateway.runc                     e Zd ZdZdDdZdEdZdFd	ZdFd
ZdFdZdFdZ	e
dGd            ZdHdZe
dId            ZdFdZdEdZdFdZdEdZdFdZdFdZdFdZdJdZdFd ZdFd!ZdFd"ZdKd$ZdKd%ZdFd&ZdFd'ZdFd(ZdFd)ZdFd*ZdFd+Z dFd,Z!dFd-Z"dFd.Z#dEd/Z$dFd0Z%dFd1Z&dFd2Z'dLdMd5Z(dFd6Z)dFd7Z*dFd8Z+dFd9Z,dFd:Z-dFd;Z.dJd<Z/dFd=Z0dFd>Z1dJd?Z2dFd@Z3dFdAZ4dFdBZ5dCS )NGatewaySlashCommandsMixinz4In-session slash-command handlers for GatewayRunner.returnstrc                    t          | dd          r| j                            |          nd}|t          |dd          ndS )a  Return the prefix users can always type to reach Hermes commands.

        Reads the adapter's ``typed_command_prefix`` capability flag
        (default "/"). Slack and Matrix return "!" because typed "/"
        commands are blocked in Slack threads / reserved by Matrix clients;
        their adapters rewrite "!command" to "/command" on receive.
        Instruction text built for those platforms must show the prefix
        that actually works when typed.
        adaptersNtyped_command_prefix/)getattrr   get)selfplatformadapters      ;/home/ubuntu/.hermes/hermes-agent/gateway/slash_commands.py_typed_command_prefix_forz3GatewaySlashCommandsMixin._typed_command_prefix_for3   sN     29z41P1PZ$-##H---VZ@G@Sww 6<<<Y\\    eventr   Union[str, EphemeralReply]c                
  K   |j         }|                     |          }|                     |d           |                     |           | j        j                            |          }t          | dd          }|n|5  | j                            |          }t          |t                    r|d         n|r|nd}ddd           n# 1 swxY w Y   ||                     |           |                     |           t          | dd          }||                    |d           	 ddlm}	  |	             n# t           $ r Y nw xY w	 ddlm}
  |
             n# t           $ r Y nw xY w| j                            |          }| j                            |d           |                     |d           t-          | d	          r| j                            |d           |                     |           |r|j        nd}	 dd
lm}  |d||j        r|j        j        ndd||r|j        nd           n# t           $ r Y nw xY w| j                            d|j        r|j        j        nd|j         |d           d{V  | j                            d|j        r|j        j        nd|j         |d           d{V  	 | !                                }n# t           $ r d}Y nw xY w|r%| "                    |          ptG          d          }n@| j        $                    |d          }| "                    |          ptG          d          }|%                                &                                }d}|r| j'        r|rddl(m)} 	 |*                    |          }n7# tV          $ r*}d}tG          dtY          |                    }Y d}~nd}~ww xY w|rs	 | j'        -                    |j        |           tG          d|          }nQ# tV          $ r(}tG          dtY          |                    }Y d}~n$d}~wt           $ r Y nw xY w|stG          d          }||z   }| .                    |          rF|D	 | /                    ||           n,# t           $ r t`          1                    dd           Y nw xY w	 dd
lm} |r|j        nd} |d||j        r|j        j        ndd||           n# t           $ r Y nw xY w	 dd l2m3} tG          d! |            "          }n# t           $ r d}Y nw xY w|rti          | d#| |           S ti          | |           S )$zHandle /new or /reset command.session_resetreason_agent_cache_lockNr   _queued_events)clear_env_passthrough)clear_credential_files_pending_model_notes)invoke_hookon_session_finalize new_session)
session_idr%   r/   old_session_idnew_session_idzsession:end)r%   user_idsession_keyzsession:resetzgateway.reset.header_defaultT)	force_newzgateway.reset.header_new	SessionDBzgateway.reset.title_rejectederrorzgateway.reset.header_titledtitlez"gateway.reset.title_error_untitledz"gateway.reset.title_empty_untitledz*Failed to rebind Telegram topic after /newexc_infoon_session_reset)get_random_tipzgateway.reset.tip)tip

)5source_session_key_for_source"_invalidate_session_run_generation_release_running_agent_statesession_store_entriesr#   r"   _agent_cache
isinstancetuple_cleanup_agent_resources_evict_cached_agentpoptools.env_passthroughr2   	Exceptiontools.credential_filesr3   reset_session_session_model_overrides_set_session_reasoning_overridehasattrr4   &_clear_session_boundary_security_stater9   hermes_cli.pluginsr5   r%   valuehooksemitr<   _format_session_info_telegram_topic_new_headerr   get_or_create_sessionget_command_argsstrip_session_dbhermes_stater@   sanitize_title
ValueErrorr   set_session_title_is_telegram_topic_lane_record_telegram_topic_bindingloggerdebughermes_cli.tipsrH   r   )r$   r*   rK   r=   	old_entry_cache_lock_cached
_old_agent_qer2   r3   	new_entry_old_sid_invoke_hooksession_infoheader
_title_arg_title_noter@   	sanitizede_new_sidrH   	_tip_lines                           r'   _handle_reset_commandz/GatewaySlashCommandsMixin._handle_reset_command@   s      226:://O/TTT 	))+666 &/33K@@	
 d$7>>" h h+//<<+5gu+E+EgWQZZV]Kg77cg
h h h h h h h h h h h h h h h %--j999  ---
 d,d33?GGK&&&	CCCCCC!!#### 	 	 	D		EEEEEE""$$$$ 	 	 	D	 &44[AA	 	%))+t<<<,,[$???4/00 	=%))+t<<<
 	33K@@@+4>9''$	FFFFFFL%#28/I..r$'7@Jy33d      	 	 	D	 joom17H--b~&.
 .
   	 	 	 	 	 	 	 jooo17H--b~&0
 0
   	 	 	 	 	 	 		4466LL 	 	 	LLL	  	^44V<<aB`@a@aFF *@@SW@XXI44V<<]B\@]@]F ++--3355
 	F$* 	Fy 	F......N%44Z@@		 N N N 	 >c!ffMMMN  
F$66y7KYWWW<INNNFF! X X X"#$HPSTUPVPV"W"W"WKKKKKK    D  F DEE+% ''// 	ZI4IZ33FIFFFF Z Z ZITXYYYYYZ	FFFFFF/8By++dHL"#28/I..r$''      	 	 	D		666666->>3C3CDDDII 	 	 	III	  	L!V"J"J"Jy"J"JKKK444555s   ?>C		CC*D; ;
EEE 
E*)E*3H8 8
IIK K'&K'N! !
O+ OO1P 
Q
P::Q
	Q
;R &R;:R;?5S5 5
TTT& &T54T5c                   K   ddl m} ddlm}  |            } |            }t	          d|          t	          d|          g}d                    |          S )	u@   Handle /profile — show active profile name and home directory.r   display_hermes_home)get_active_profile_namezgateway.profile.header)profilezgateway.profile.home)home
)hermes_constantsr   hermes_cli.profilesr   r   join)r$   r*   r   r   displayprofile_nameliness          r'   _handle_profile_commandz1GatewaySlashCommandsMixin._handle_profile_command   s      888888??????%%''..00 &===$7333

 yyr)   c                ^  K   ddl m} |j        } || j        |          }|r|j        r|j        j        nd}|r|j        ndpd}|                                dv rdnd}|r|j        nd	pd}|j	        sd
| d| d| dS |
                    |          rd
| d| d| dS ddg}	t          |j                  }
t                      }g }|	|
z   D ]0}||vr*|                    |           |                    |           1|rd                    d |D                       nd}d
| d| d| d| S )uD  Handle /whoami — show the user's slash command access on this scope.

        Always works (it's in the always-allowed floor of slash_access).
        Reports: platform, scope (DM vs group), the user's tier
        (admin / user / unrestricted), and the slash commands they can
        actually run on this scope.
        r   )policy_for_source?r7   dm>   r7   r   directprivateDMzgroup/channelNu   **You** —  (z)
User ID: `z\`
Tier: unrestricted (no admin list configured for this scope)
Slash commands: all availablez/`
Tier: **admin**
Slash commands: all availablehelpwhoami, c              3      K   | ]	}d | V  
dS )r!   N ).0cs     r'   	<genexpr>zCGatewaySlashCommandsMixin._handle_whoami_command.<locals>.<genexpr>!  s(       ; ;QQ ; ; ; ; ; ;r)   z(none)z)`
Tier: user
Slash commands you can run: )gateway.slash_accessr   rK   configr%   r`   	chat_typelowerr<   enabledis_adminsorteduser_allowed_commandssetaddappendr   )r$   r*   _policy_for_sourcerK   policyr%   r   scoper<   floor
configuredseenrunnabler   runnable_strs                  r'   _handle_whoami_commandz0GatewaySlashCommandsMixin._handle_whoami_command   s      	QPPPPP##DK88,2OvO6?((C)/7V%%R@D	!))-LLLRa%+56>>=#~ 	1x 1 15 1 1$1 1 1 ??7## 	1x 1 15 1 1$1 1 1 "F899
 # 	# 	#A}}"""?GUtyy ; ;( ; ; ;;;;X:8 : :u : : : : ,8: :	
r)   c                R   K   ddl }ddl}ddl}ddlm} |j        pd                                }|                    d          r|                    d          }|                    d          r)|t          d          d                                         }|r |j
        |          ng }dd}d}	|	t          |          k     rp||	         }
|
dk    r(|	dz   t          |          k    rnK||	dz            |	d	z  }	I|
                    d
          r"|

                    dd          d         |	dz  }	|
}	 |dk    }	  |j        ||           d{V }n(# t          $ r}t          d|          cY d}~S d}~ww xY w|rb|r_ |j        d|          }|rK|                    d          	 |j        }t#          |dd          }t%          |d          r|j        nt)          |pd                                          t)          t#          |dd          pd          t)          t#          |dd          pd          t)          t#          |dd          pd          pdrLrJ fd} |j        |           d{V  |                                dz   t          d          z   }n2# t          $ r%}t.                              d|           Y d}~nd}~ww xY wt          |          dk    r|dd         dz   t          d          z   }|pt          d          S )u  Handle /kanban — delegate to the shared kanban CLI.

        Run the potentially-blocking DB work in a thread pool so the
        gateway event loop stays responsive.  Read operations (list,
        show, context, tail) are permitted while an agent is running;
        mutations are allowed too because the board is profile-agnostic
        and does not touch the running agent's state.

        For ``/kanban create`` invocations we also auto-subscribe the
        originating gateway source (platform + chat + thread) to the new
        task's terminal events, so the user hears back when the worker
        completes / blocks / auto-blocks / crashes without having to poll.
        r   N)	run_slashr7   r!   kanbanz--board      z--board==createzgateway.kanban.error_prefixrA   zCreated\s+(t_[0-9a-f]+)\br%   r`   chat_id	thread_idr<   c                    ddl m}  |                               }	 |                     |pd t	          dd           p                                           |                                 d S # |                                 w xY w)Nr   )	kanban_db)board_kanban_notifier_profile)task_idr%   r   r   r<   notifier_profile)
hermes_clir   connectadd_notify_subr"   _active_profile_nameclose)	_kbconnr   platform_strrequested_boardr$   r   r   r<   s	     r'   _subz>GatewaySlashCommandsMixin._handle_kanban_command.<locals>._subo  s    CCCCCC#&;;_;#E#ED	- # 2 2$('-97.7.?4,35<TC]_c5d5d  6Dhl  iB  iB  iD  iD !3 !" !" !" !%



s   AA6 6Br   z gateway.kanban.subscribed_suffix)r   z'kanban create auto-subscribe failed: %si  zgateway.kanban.truncated_suffixzgateway.kanban.no_output)asyncioreshlexhermes_cli.kanbanr   textrg   
startswithlstriplensplit	to_threadrX   r   searchgrouprK   r"   r]   r`   r   r   rstripro   warning)r$   r*   r   r   r   r   r   tokensactionitok	is_createoutputexcmrK   r%   r   r   r   r   r   r   r<   s   `                 @@@@@@r'   _handle_kanban_commandz0GatewaySlashCommandsMixin._handle_kanban_command)  s      				//////
 b''))??3 	$;;s##D??8$$ 	1H'..00D&*2T"""#f++oo)Ciq5CKK''"(Q-Q~~j)) "%))C"3"3A"6QFh&		?,7,Y========FF 	? 	? 	?2#>>>>>>>>>	?  "	S "	S	6??A  S''!**S"\F&vz4@@H*1(G*D*D]#hnZ\J]J]egg ! "'&)R"@"@"FBGGG #GFK$D$D$J K KI!'&)R"@"@"FBGGO4G#  - - - - - - - - - - - 0g/555555555"MMOO"# BGTTTU 
 ! S S SNN#LcRRRRRRRRS
 v;;ETE]T)A.O,P,PPF65666s7   E 
F %E;5F ;F 3DJ6 6
K% K  K%c                  K   |j         }| j                            |          }d | j                                        D             }|j        }|| j        v }|r| j                            |j                  nd}| 	                    ||          }d}	d}
| j
        r	 | j
                            |j                  }	n# t          $ r d}	Y nw xY w	 | j
                            |j                  }|rw|                    d          pd|                    d          pdz   |                    d          pdz   |                    d          pdz   |                    d	          pdz   }
n# t          $ r d}
Y nw xY wt          d
          dt          d|j                  g}|	r$|                    t          d|	                     |                    t          d|j                            d                    t          d|j                            d                    t          d|
d          t          d|rt          d          nt          d                    g           |r$|                    t          d|                     |j        t*          j        k    r| j                            t*          j                  }t/          |dt1          j        dd                    }|j        pd }|                    dt          d!          t          d"|j        p|j        #          t          d$|j        %          t          d&|'          t          d(|)          t          d*|                     |          +          g           |                    dt          d,d-                    |          .          g           d/                    |          S )0zHandle /status command.c                    g | ]	}|j         
S r   r`   r   ps     r'   
<listcomp>zDGatewaySlashCommandsMixin._handle_status_command.<locals>.<listcomp>  s    EEE1qwEEEr)   N)r&   r   input_tokensoutput_tokenscache_read_tokenscache_write_tokensreasoning_tokenszgateway.status.headerr7   zgateway.status.session_idr9   zgateway.status.titlerC   zgateway.status.createdz%Y-%m-%d %H:%M)	timestampzgateway.status.last_activityzgateway.status.tokens,r   zgateway.status.agent_runningzgateway.status.state_yeszgateway.status.state_nostatezgateway.status.queuedcount_matrix_session_scopeMATRIX_SESSION_SCOPEautononez"gateway.status.matrix_scope_headerz gateway.status.matrix_scope_room)roomz#gateway.status.matrix_scope_room_id)room_idz"gateway.status.matrix_scope_thread)r   z gateway.status.matrix_scope_mode)r   zgateway.status.matrix_scope_key)r=   zgateway.status.platformsr   )	platformsr   )rK   rO   re   r   keysr=   _running_agentsr#   r%   _queue_depthrh   get_session_titler9   rX   get_sessionr   r   extend
created_atstrftime
updated_atr   MATRIXr"   osgetenvr   	chat_namer   _redact_matrix_session_keyr   )r$   r*   rK   session_entryconnected_platformsr=   
is_runningr&   queue_depthrD   db_total_tokensrowr   r   threads                  r'   _handle_status_commandz0GatewaySlashCommandsMixin._handle_status_command  sI     *@@HHEE0B0B0D0DEEE $/ D$88
 9?H$-##FO444D''W'EE  	$(::=;STT   $&22=3KLL 005A77?338q:77#677<1> 77#788=A? 77#566;!	= $  $ $ $"#$ %&&)m6NOOO

  	ALL1???@@@&-2J2S2STd2e2efff,8P8Y8YZj8k8klll%.D.DEEE,U_  5BA6P4Q4Q4Qef  hA  fB  fB  C  C  C	
 	 	 	  	HLL2+FFFGGG?ho--m''88GG%<biH^`f>g>ghhE%/FLL67746;K;]v~^^^7PPP6&III4EBBB5 $ ? ? L L      	(DII>Q4R4RSSS
 	 	 	
 yys%   B= =CCBE) )E87E8r=   c                    t          | pd          }t          j        |                    d                                                    dd         }d| S )zFReturn a stable Matrix session-key fingerprint for shared room status.r7   utf-8N   zsha256:)r   hashlibsha256encode	hexdigest)r=   r   digests      r'   r  z4GatewaySlashCommandsMixin._redact_matrix_session_key  sT     ;$"%%G 4 455??AA#2#F!!!!r)   r9   Optional[SessionSource]c                d   t          t          | j                  dd          }t          |          r& || j        |          }|t          |dd          ndS t          | j        di           pi }|                                D ]*}t          |dd          |k    rt          |dd          c S +dS )z2Best-effort origin lookup for gateway session IDs.lookup_by_session_idNoriginrP   r9   )r"   typerO   callablevalues)r$   r9   lookupentryentriess        r'   _gateway_session_origin_for_idz8GatewaySlashCommandsMixin._gateway_session_origin_for_id  s    d0113I4PPF 	QF4-z::E5:5F75(D111DP $,j"==C^^%% 	6 	6EulD11Z??uh55555 @tr)   currentr   r   boolc                ~    |d uo9|j         t          j        k    o$| j         t          j        k    o|j        | j        k    S N)r%   r   r  r   )r(  r   s     r'   _same_matrix_roomz+GatewaySlashCommandsMixin._same_matrix_room  sG     $ 28?22 HO32 '/1		
r)   c                p	  K   ddl m} ddlm}m} t          j                    }|                     |j                  }t          | di           pi }t          | di           pi }g }	|	                                D ]\  }
}t          |                    |
|                    }t          dt          ||z
                      }||u }|	                    |
||rt          d          nt          d          |rdnt!          t          |d	d          pd          |rdnt!          t          |d
d          pd          d           |	                    d d           g }	 d |                                D             }n# t&          $ r g }Y nw xY wd t          | dt)                                pt)                      D             }t          d          dt          dt+          |	                    g}|	rt-          |	dd         d          D ]\  }}|d         |k    rt          d          nd}|d	         rd|d	          dnd}|d
         rd|d
          dnd}|                    | d|d          d|d          d ||d                     | | | 
           t+          |	          dk    r4|                    t          d!t+          |	          dz
                       |                    dt          d"t+          |                    g           |r|dd         D ]}d#                    t!          |                    d$d                                                              }t+          |          d%k    r|dd&         d'z   }|                    d(|                    d	d)           d |t          |                    d*d                               d| d           t+          |          dk    r4|                    t          d!t+          |          dz
                       |                    dt          d+t+          |                    g           |	s;|s9|s7|                    d           |                    t          d,                     d-                    |          S ).z>Handle /agents command - list active agents and running tasks.r   _AGENT_PENDING_SENTINEL)format_uptime_shortprocess_registryr   _running_agents_tszgateway.agents.state_startingzgateway.agents.state_runningr7   r9   model)r=   elapsedr   r9   r3  c                    | d         S )Nr4  r   )r  s    r'   <lambda>zBGatewaySlashCommandsMixin._handle_agents_command.<locals>.<lambda>  s
    I r)   T)keyreversec                D    g | ]}|                     d           dk    |S )statusrunningr#   r   s     r'   r   zDGatewaySlashCommandsMixin._handle_agents_command.<locals>.<listcomp>  s7     ! ! !55??i// ///r)   c                P    g | ]#}t          |d            |j                    !|$S )done)r]   r>  )r   r   s     r'   r   zDGatewaySlashCommandsMixin._handle_agents_command.<locals>.<listcomp>  sH     
 
 
q&!!
*0!&((

 
 
r)   _background_taskszgateway.agents.headerzgateway.agents.active_agentsr   Nr  r   r=   zgateway.agents.this_chatu    · ``z. `u   ` · r   u    · r4  zgateway.agents.morez gateway.agents.running_processes commandZ   W   ...z- `r   uptime_secondszgateway.agents.async_jobszgateway.agents.noner   )gateway.runr/  tools.process_registryr0  r1  timerL   rK   r"   itemsfloatr#   maxintr   r   r   sortlist_sessionsrX   r   r   	enumerater  r   r   )r$   r*   r/  r0  r1  nowcurrent_session_keyrunning_agentsrunning_started
agent_rowsr=   agentstartedr4  
is_pendingrunning_processesbackground_tasksr   idxr  r(  sidr3  proccmds                            r'   _handle_agents_commandz0GatewaySlashCommandsMixin._handle_agents_command  s     777777PPPPPPPPikk"::5<HH&t->CCIr '.BB G G M2!#
"0"6"6"8"8 	 	KO//SAABBG!Sw//00G"99J#.&CMtQ>???STUsStSt(2"c""GE<Y[<\<\<b`b8c8c#-YRR3wugr7R7R7XVX3Y3Y     	66EEE(*	#! !+99;;! ! !  	# 	# 	# "	#
 
&9355AAJSUU
 
 
 %&&,C
OODDD
  
	S%j"oq99  S;>};MQd;d;d!6777jl69,6GO2c,/2222R36w<G/G////R R Rs=1 R RG R R**3y>::R<?RAFRHOR R    :##Q4C
OOb<PQQQRRR4C@Q<R<RSSS	
 	
 	
  
	Z)#2#.  hhs488Ir#:#:;;AACCDDs88b==crc(U*C\$((<55 \ \**3txx8H!/L/L+M+MNN\ \UX\ \ \    $%%**Q4C@Q<R<RUW<WXXXYYY-S9I5J5JKKK	
 	
 	
  	3"3 	3<L 	3LLLL011222yys   E> >FFc                :  K   ddl m}m} |j        }| j                            |          }|j        }| j                            |          }||u rV| 	                    |||d           d{V  t                              d|           t          t          d                    S |r;| 	                    |||d           d{V  t          t          d	                    S |                     ||          }|r|                     |          r}|D ]!}	| 	                    |	||d
           d{V  "t                              d|t!          |          d                    |                     t          t          d	                    S t          d          S )a  Handle /stop command - interrupt a running agent.

        When an agent is truly hung (blocked thread that never checks
        _interrupt_requested), the early intercept in _handle_message()
        handles /stop before this method is reached.  This handler fires
        only through normal command dispatch (no running agent) or as a
        fallback.  Force-clean the session lock in all cases for safety.

        The session is preserved so the user can continue the conversation.
        r   )r/  _INTERRUPT_REASON_STOPstop_command_pending)interrupt_reasoninvalidation_reasonNu2   STOP (pending) for session %s — sentinel clearedzgateway.stop.stopped_pendingstop_command_handlerzgateway.stop.stoppedstop_command_thread_siblinguC   STOP (thread sibling) by %s — interrupted %d run(s) in thread: %sr   zgateway.stop.no_active)rG  r/  ra  rK   rO   re   r=   r   r#   _interrupt_and_clear_sessionro   infor   r   _sibling_thread_run_keys_is_user_authorizedr   r   )
r$   r*   r/  ra  rK   r  r=   rV  sibling_keyssibling_keys
             r'   _handle_stop_commandz.GatewaySlashCommandsMixin._handle_stop_commandT  s6      	POOOOOOO*@@HH#/$((55+++33!7$:	 4          KKLkZZZ!!$B"C"CDDD 		= 33!7$:	 4          "!$:";";<<< 44V[II 	=D44V<< 	=+  77%;(E	 8           KKUL!!		,''	   "!$:";";<<<)***r)   c           
     R  K   t          |dd          pd                                }|                    d          }|rJ|d                                                             d                              d          r
|dd	         }|r|d         nd
                                }t          |          dk    r|d                                         nd}d/d}|d
k    r]dg}t          d | j        	                                D                       }|r,|
                    dd                    |          z              n|
                    d           t          | di           pi }	|	r|	                                D ]\  }
}|                    d          rA|                    d          pd}|
                    d|
j         d| d|
j         d           [|                    dd          }|
                    d|
j         d| d           n|
                    d           d                    |          S |dv r|sd | d!S  ||          }|d"| S t          | di           pi }	|d#k    r]||	vr
|j         d$S |	|                             d          r
|j         d%S |                     |d&'           d(|j         d)|j         d*S ||	vr
|j         d+S |	|                             d          s
|j         d,S |                     |           d(|j         d-S 	 d.S )0u  Handle ``/platform list|pause|resume [name]`` — surface and
        manually control failed/paused gateway adapters.

        Examples:
            ``/platform list``           — show connected + failed/paused platforms
            ``/platform pause whatsapp`` — stop the reconnect watcher hammering whatsapp
            ``/platform resume whatsapp`` — re-queue a paused platform for retry
        contentr7   r   )maxsplitr   r!   r%   r   Nlistnamer   c                    | sd S t           j                                        D ]#}|j                                        | k    r|c S $d S r+  )r   __members__r#  r`   r   )rr  r   s     r'   _resolve_platformzMGatewaySlashCommandsMixin._handle_platform_command.<locals>._resolve_platform  sU     t)0022  7==??d**HHH +4r)   z**Gateway platforms**c              3  $   K   | ]}|j         V  d S r+  r   r   s     r'   r   zEGatewaySlashCommandsMixin._handle_platform_command.<locals>.<genexpr>  s$      EE1qwEEEEEEr)   zConnected: r   zConnected: (none)_failed_platformspausedpause_reasonu     · u    — PAUSED (z!). Resume with `/platform resume z`.attemptsu    — retrying (attempt )zFailed/paused: (none)r   >   pauseresumezUsage: /platform z <name>zUnknown platform: r|  zB is not in the retry queue (it's either connected or not enabled).z is already paused.zpaused via /platform pauser.   u   ✓ z' paused. Resume with `/platform resume z'` or `hermes gateway restart` to reset.u1    is not in the retry queue — nothing to resume.u*    is already retrying — no resume needed.u+    resumed — retrying on next watcher tick.u   Usage: /platform <list|pause|resume> [name]
  /platform list — show platform status
  /platform pause <name> — stop retrying a failing platform
  /platform resume <name> — re-queue a paused platform)rr  r   )r"   rg   r   r   r   r   r   r   r   r   r   r   rJ  r#   r`   _pause_failed_platform_resume_paused_platform)r$   r*   r   partsr   targetru  r   	connectedfailedr   rh  r/   rz  r%   s                  r'   _handle_platform_commandz2GatewaySlashCommandsMixin._handle_platform_command  s%      y"--3::<<

A
&& 	U1X^^%%,,S11<<ZHH 	!""IE#/%((6688%(ZZ!^^q!!!	 	 	 	 V,-EEE0B0B0D0DEEEEEI 2]TYYy-A-AABBBB0111T#6;;ArF 6%||~~  GAtxx)) 
!%.!9!9!EXIAG I I& I I=>WI I I   
 $(88J#:#:OAGOOHOOO    455599U###((( ;:6::::((00H4F444T#6;;ArF  6))#> C C C (#''11 B&nAAAA++H=Y+ZZZ:8> : :5=^: : : v%%~ * * * (#''11 ~ ) ) ) ((222U(.UUUUG	
 	
r)   c                r  K   ddl m} |                     |          rGt                              d|j        r|j        j        r|j        j        j        nd|j                   dS | j	        s| j
        rC|                                 }|rt          d|          S t          t          d                    S 	 |j        j        r|j        j        j        nd	|j        j        |j        j        d
}|j        j        r|j        j        |d<   |j        r
|j        |d<   |j        c	 t%          j        |j        |j        t)          |j                  n|j        j                  | _        n# t,          $ r |j        | _        Y nw xY wt/          |dz  |d	           n2# t,          $ r%}t                              d|           Y d	}~nd	}~ww xY w	 |j        j        r|j        j        j        nd	t3          j                    d}|j        
|j        |d<   t/          |dz  |d	           n2# t,          $ r%}t                              d|           Y d	}~nd	}~ww xY w|                                 }t5          t6          j                            d                    }t6          j                            d          pt6          j                            d          }	|s|	r|                      dd           n|                      dd           |rt          d|          S t          t          d                    S )zFHandle /restart command - drain active work, then restart the gateway.r   _hermes_homeuo   Ignoring redelivered /restart (platform=%s, update_id=%s) — already processed by a previous gateway instance.r   r7   zgateway.drainingr   zgateway.restart.in_progressN)r%   r   r   r   
message_id)r  z.restart_notify.json)indentz'Failed to write restart notify file: %s)r%   requested_at	update_idz.restart_last_processed.jsonz(Failed to write restart dedup marker: %sINVOCATION_IDz/.dockerenvz/run/.containerenvFT)detachedvia_servicezgateway.restart.restarting)!rG  r  _is_stale_restart_redeliveryro   rh  rK   r%   r`   platform_update_id_restart_requested	_draining_running_agent_countr   r   r   r   r   r  dataclassesreplacer   _restart_command_sourcerX   r   rp   rI  r)  r	  environr#   pathexistsrequest_restart)
r$   r*   r  r   notify_datar   
dedup_dataactive_agents_under_service_in_containers
             r'   _handle_restart_commandz1GatewaySlashCommandsMixin._handle_restart_command  s     ,,,,,, ,,U33 	KKD/4|^@U^%++[^(	   2" 	Ddn 	D--//E :+59999!!$A"B"BCCC	G;@<;PZEL177VZ </"\3 K
 |% B+0<+AK( =,1,<L)|'@3>3F +7 $'u'7#8#8#8"\4	4 4 4D00 ! @ @ @38<D000@55    
  	G 	G 	GLLBAFFFFFFFF	G	H;@<;PZEL177VZ $	 J '3*/*B
;'==    
  	H 	H 	HLLCQGGGGGGGG	H 1133 bjnn_==>>}55]H\9]9] 	C] 	C  %T BBBB  $E BBB 	>'}====a <==>>>sW   7A*F "AE( 'F (F>F  FF 
G	$GG	AH' '
I1IIc                &   K   ddl m}  |            S )u:   Handle /version — show the running Hermes Agent version.r   )format_banner_version_label)hermes_cli.bannerr  )r$   r*   r  s      r'   _handle_version_commandz1GatewaySlashCommandsMixin._handle_version_commandP  s'      AAAAAA**,,,r)   c           
       K   ddl m} ddlm} t	          d          g |            }	 ddlm}  |            }|r|                    t	          dt          |                               t          |          }|dd	         D ])}|                    d
| d||         d                     *t          |          d	k    r4|                    t	          dt          |          d	z
                       n# t          $ r Y nw xY w |d                    |          t          t          |dd          dd                    S )z/Handle /help command - list available commands.r   _telegramize_command_mentionsgateway_help_lineszgateway.help.headerget_skill_commandszgateway.help.skill_headerr   N
   r@     ` — descriptionzgateway.help.more_use_commandsr   rK   r%   )rG  r  hermes_cli.commandsr  r   agent.skill_commandsr  r   r   r   rX   r   r"   )	r$   r*   r  r  r   r  
skill_cmdssorted_cmdsr^  s	            r'   _handle_help_commandz.GatewaySlashCommandsMixin._handle_help_commandV  s     ======::::::#$$
!!
	??????++--J cQ:#j//RRRSSS$Z00&ss+ R RCLL!PS!P!P
30N!P!PQQQQ{##b((LL#C3{K[K[^`K`!a!a!abbb 	 	 	D	,,IIeGE8T22JEE
 
 	
s   CC8 8
DDc           
       K   ddl m} ddlm} |                                                                }|r0	 t          |          }n!# t          $ r t          d          cY S w xY wd}t           |                      }	 ddl
m}  |            }|r|                    d           |                    t          d                     t          |          D ]Z}	||	                             d	d                                          pt          d
          }
|                    d|	 d|
            [n# t          $ r Y nw xY w|st          d          S ddlm} |j        j        |j        k    rdnd}t+          dt-          |          |z   dz
  |z            }t+          dt/          ||                    }|dz
  |z  }||||z            }t          dt-          |          ||          dg|}|dk    rg }|dk    r'|                    t          d|dz
                       ||k     r'|                    t          d|dz                        |                    dd                    |          g           ||k    r%|                    t          d||                      |d                    |          t5          t5          |dd           dd                     S )Nr   r  r  zgateway.commands.usager   r  r7   zgateway.commands.skill_headerr  zgateway.commands.default_descr@  r  zgateway.commands.none)r         zgateway.commands.header)totalpagetotal_pageszgateway.commands.nav_prev)r  zgateway.commands.nav_nextz | zgateway.commands.out_of_range)	requestedr  r   rK   r%   )rG  r  r  r  rf   rg   rM  rk   r   rq  r  r  r   r   r#   rX   gateway.configr   rK   r%   TELEGRAMrL  r   minr  r   r"   )r$   r*   r  r  raw_argsrequested_pager&  r  r  r^  descr   	page_sizer  r  startpage_entriesr   	nav_partss                      r'   _handle_commands_commandz2GatewaySlashCommandsMixin._handle_commands_commandp  ss     ======::::::))++1133 	3!$X 3 3 31222223 N ))++,,
	??????++--J :r"""q!@AABBB!*-- : :C%c?..}bAAGGIIoQOnMoMoDNN#8s#8#8$#8#89999 	 	 	D	  	.,---++++++,/83DDDBB"	!c'llY6:yHII1c.+6677Y&uUY%667 's7||$T_```
 

 ??Iaxx  #>TAX!N!N!NOOOk!!  #>TAX!N!N!NOOOLL"ejj334555>!!LL:n[_```aaa,,IIeGE8T22JEE
 
 	
s$   A A$#A$B3D5 5
EEOptional[str]c                    !"#$%&'()*+,-./0123K   ddl m}m% ddl3ddlm(m}m}m} ddl	m
}                                                                 } ||          \  }}	.}
|
r"	 ddlm}  |             n# t          $ r Y nw xY wd,d}d+d*d2d-|d	z  )	  %            }|r|                    d
i           }t#          |t$                    rB|                    dd          ,|                    d|          }|                    dd          +|                    d          2	 ddlm}  ||          -n%# t          $ r |                    d          -Y nw xY wn# t          $ r Y nw xY wj        1                     1          1                     1          0 j                            0i           }|rX|                    d
,          ,|                    d|          }|                    d+          +|                    d*          *|s|	s̉ j                            1j                  }|duot7          t9          |          dd          du}|r	  ||+,2-d          }n# t          $ r g }Y nw xY w|rw &0',"|#+!* dC !"#%&'(*+-2fd}                     1                                         }|                    1j         |,|0||           d{V //j!        rdS  ||          }tE          d,pd|          dg}	  ||+,2-d          }|D ]&}|d          rtE          d!          nd}|#                    d"|d#          d$|d%          d&| d'           |d(         rd)$                    d* |d(         D                       }|d+         tK          |d(                   k    r-tE          d,|d+         tK          |d(                   z
  -          nd}|#                    d.| |            n4|                    d/          r|#                    d0|d/          d&           |#                    d           (n# t          $ r Y nw xY w|#                    tE          d1                     |#                    tE          d2                     |#                    tE          d3                     d4$                    |          S  (||,+*.|	2-5	  	        //j!        stE          d6/j&        7          S dD%)*+,-./ 013fd8$d}	 dd9l'm(} tS          j*        |/j+        /j,        /j-        p+pd/j.        p*pd/j/        :           d{V }n# t          $ r d}Y nw xY w|UdE$,fd<} 0                    j        j                  } 1                    d
d=d>|j2         d?| d@| dA|B           d{V S  $             d{V S )Fu  Handle /model command — switch model for this session.

        Supports:
          /model                              — interactive picker (Telegram/Discord) or text list
          /model <name>                       — switch for this session only
          /model <name> --global              — switch and persist to config.yaml
          /model <name> --provider <provider> — switch provider + model
          /model --provider <provider>        — switch to provider, auto-detect model
        r   r  _load_gateway_configN)switch_modelparse_model_flagslist_authenticated_providerslist_picker_providers)	get_label)clear_provider_models_cacher7   
openrouterconfig.yamlr3  defaultproviderbase_url	providers)get_compatible_custom_providerscustom_providersapi_keysend_model_picker2   )current_providercurrent_base_urlcurrent_modeluser_providersr  
max_models_chat_idr   model_idprovider_slugr   c                  K    |d|	  	        }|j         st          d|j                  S d}t          dd          }t          dd          }|r1|/|5  |                              }ddd           n# 1 swxY w Y   |ru|d         m	 |d                             |j        |j        |j        |j	        |j
        	           n2# t          $ r%}t                              d
|           Y d}~nd}~ww xY wt          dd          }|s	 j                            j                  }	|                    |	j        |j                   n2# t          $ r%}t                              d|           Y d}~nd}~ww xY wt)          d          si _        d d|j         d|j        p|j         dj        <   |j        |j        |j        |j	        |j
        dj        <                                  |j        p|j        }
t          d|j                  g}|                    t          d|
                     |j        }ddlm} d}	              }|                    di           }t;          |t<                    r&|                    d          }|t?          |          }n# t          $ r Y nw xY w ||j        |j        |j	        ppd|j        ppd||          }|r&|                    t          d|d                     |r|j         r+|                    t          d|j         d                     |!                                r6|                    t          d |"                                !                     |                    t          d"|#                                #                     |                    t          d$                     d%$                    |          S )&z6Perform the model switch and return confirmation text.F		raw_inputr  r  r  current_api_key	is_globalexplicit_providerr  r  gateway.model.error_prefixrA   Nr0   rQ   r   	new_modelnew_providerr  r  api_modez/Picker model switch failed for cached agent: %srh   (Failed to persist model switch to DB: %sr4   $[Note: model was just switched from  to  via /. Adjust your self-identification accordingly.]r3  r  r  r  r  gateway.model.switchedr3  gateway.model.provider_labelr  resolve_display_context_lengthr3  context_lengthr7   r  r  
model_infor  config_context_lengthgateway.model.context_labelr   r   gateway.model.max_output_labelgateway.model.cost_labelcost gateway.model.capabilities_labelcapabilitiesgateway.model.session_only_hintr   )%successr   error_messager"   r#   r  r  target_providerr  r  r  rX   ro   r   rO   re   rK   update_session_modelr9   rp   r]   r4   provider_labelr[   rU   r   r  hermes_cli.model_switchr  rR   dictrM  
max_outputhas_cost_dataformat_costformat_capabilitiesr   ) r  r  r  resultcached_entryrs   _cacher   _sess_db_sess_entryplabelr   mir  _sw_config_ctx_sw_cfg_sw_model_cfg_sw_rawctx_cur_api_key_cur_base_url
_cur_model_cur_providerr  _self_session_key_switch_modelr  r  custom_provsr*   
user_provss                       r'   _on_model_selectedzKGatewaySlashCommandsMixin._handle_model_command.<locals>._on_model_selected  sk      "/&.-:*4-:,8&+.;+5-9
" 
" 
"  &~ _#$%AI]#^#^#^^ (,&-e5H$&O&O!(!E!E& H6+=!, H H/5zz,/G/GH H H H H H H H H H H H H H H' 
gLO,G	g ,Q < <.4.>171G,2N-3_-3_ != !" !" !" !" $- g g g &/`be f f f f f f f fg
 $+5-#F#F#/
".3.A.W.W$)L/" /" !) = =$/$:F<L!" !" !" !" $- " " " &$NPS!" !" !" !" !" !" !" !""  'u.DEE <9;E6M: M MSYSc M M#)#8#RF<RM M M 2<@ &,%5(.(>'-~(.(.H H6|D 11,??? "(!6!P&:P!"#;6CS!T!T!T UQ'EPV%W%W%WXXX#.ZZZZZZ)-!&:&:&<&<G,3KK,D,DM)->> B*7*;*;<L*M*M#*#658\\N( ! ! ! D!<<","2%+_%N8H%NB$*N$Ko$K')-92@    ^!LL+HTWQ[Q[)\)\)\]]] w!} o %Q/O[][hXlXl-m-m-m n n n!//11 c %Q/IPRP^P^P`P`-a-a-a b b b!LL+M\^\r\r\t\t)u)u)uvvvQ'H%I%IJJJ#yy///sU   BBB9C 
D C;;D ?E 
F!FFAJ8 8
KK)r   r  r  r  r=   on_model_selectedmetadatazgateway.model.current_labelunknown)r3  r     
is_currentzgateway.model.current_tagz**rr  z** `--provider slugr@  :modelsr   c              3  "   K   | ]
}d | d V  dS r@  Nr   r   r   s     r'   r   zBGatewaySlashCommandsMixin._handle_model_command.<locals>.<genexpr>  s*      .M.MAx1xxx.M.M.M.M.M.Mr)   total_modelsz gateway.model.more_models_suffixr   z  api_urlz  `z gateway.model.usage_switch_modelz#gateway.model.usage_switch_providerzgateway.model.usage_persistr   r  r  rA   c            	       K   d} t          dd          }t          dd          }|r1|/|5  |                              } ddd           n# 1 swxY w Y   | ru| d         m	 | d                             j        j        j        j        j                   n2# t          $ r%}t          
                    d|           Y d}~nd}~ww xY wt          dd          }|n	 j                                       }|                    |j        j                   n2# t          $ r%}t                              d|           Y d}~nd}~ww xY wt!          d	          si _        d
 dj         dj        pj         dj        <   j        j        j        j        j        dj        <                                  r:	                                 rAt-          d          5 }!                    |          pi }ddd           n# 1 swxY w Y   ni }|                    d          }t1          |t2                    r|}	nLt1          |t4                    r0|                                rd|                                i}	|	|d<   ni }	|	|d<   j        |	d<   j        |	d<   j        r
j        |	d<   ddlm}
  |
|           n2# t          $ r%}t          
                    d|           Y d}~nd}~ww xY wj        pj        }t=          dj                  g}|                    t=          d|                     j         }ddl!m"} d}	              }|                    di           }t1          |t2                    r&|                    d          }|tG          |          }n# t          $ r Y nw xY w |j        j        j        ppdj        ppd||          }|r&|                    t=          d|d !                     |r|j$        r+|                    t=          d"|j$        d !                     |%                                r6|                    t=          d#|&                                $                     |                    t=          d%|'                                &                     tQ          j        pdd'          rd(j        )                                v p
j        d)k    }|r"|                    t=          d*                     j*        r)|                    t=          d+j*        ,                     r#|                    t=          d-                     n"|                    t=          d.                     d/+                    |          S )0zGApply the resolved switch (agent, session, config) and build the reply.Nr0   rQ   r   r  z1In-place model switch failed for cached agent: %srh   r  r4   r  r  r  r  r  r  encodingr3  r  r  r  )save_configz"Failed to persist model switch: %sr  r  r  r  r  r  r7   r  r  r   r   r  r   r  r  r  zopenrouter.aiclaudeanthropic_messagesz$gateway.model.prompt_caching_enabledzgateway.model.warning_prefix)r   zgateway.model.saved_globalr  r   ),r"   r#   r  r  r	  r  r  r  rX   ro   r   rO   re   r
  r9   rp   r]   r4   r  r[   rU   r  open	safe_loadrR   r  r   rg   hermes_cli.configr8  r   r   r  r  r  rM  r  r  r  r  r   r   warning_messager   )"r  rs   r  r   r  r  fcfg	raw_model	model_cfgr8  r   r  r   r  r  _sw2_config_ctx_sw2_cfg_sw2_model_cfg_sw2_rawr  cache_enabledr  config_pathr  r  r  r%  persist_globalr  r$   r=   rK   yamls"                         r'   _finish_switchzGGatewaySlashCommandsMixin._handle_model_command.<locals>._finish_switch  sr       L!$(;TBBKT>488F ;v1  ; ;#)::k#:#:L; ; ; ; ; ; ; ; ; ; ; ; ; ; ;  
]Q ;	] O00"("2%+%; &!'!' 1     ! ] ] ]NN#VX[\\\\\\\\]
 t]D99H#"&"4"J"J6"R"RK11#.0@    !   LLBC        4!788 /,.)A} A A&JZ A A,F0FA A A %k2  )"2!>"O"O: :D)+6 $$[111  LL"))++ !!+@@@ :A"&.."3"3"9rC: : : : : : : : : : : : : : : ! !$ 0 0I!)T22 1$-		#Is33 1	8I8I 1%.	0A0A$B	'0G$&	'0G+1+;Ii(,2,BIj) @06	*-======K$$$$  L L LNN#GKKKKKKKKL $2Lf6LN/v7GHHHIELL9NSSSTTT "BNNNNNN"O//11!)gr!:!:nd33 8-112BCCH+*-h--   00 &B,<B?/?R!-&5  C  RQ<ZZPPPQQQ k= cLL#Cr}L`L`!a!a!abbb##%% WLL#=BNNDTDT!U!U!UVVVQAPRPfPfPhPhiiijjj 'v'<"oNNwS[_e_o_u_u_w_wSw ;?&::   HQEFFGGG% `Q=vG]^^^___ CQ;<<====Q@AABBB99U###s   AAA&9B   
C*C

C&:D! !
E+EE%K 6HK HK !H"B5K 
L"LL#AN? ?
OO)expensive_model_warning)r  r  r  r  choicec                D   K   | dk    rdpd dS               d {V S )Ncancelu6   🟡 Model switch cancelled. Current model unchanged (r*  z).r   )rM  rK  r  s    r'   _on_cost_confirmzIGatewaySlashCommandsMixin._handle_model_command.<locals>._on_cost_confirma  sU      X%%;)6Y; ; ; ,^---------r)   zExpensive Model Warningu$   ⚠️ **Expensive Model Warning**

z

_Text fallback: reply `zapprove` to switch or `z#cancel` to keep the current model._r*   rB  rD   messagehandler)r  r   r  r   r  r   r   r   r   r   )rM  r   r   r   )3rG  r  r  rJ  r  r  r  r  r  hermes_cli.providersr  rf   rg   hermes_cli.modelsr  rX   r#   rR   r  r=  r  rK   !_normalize_source_for_session_keyrL   r[   r   r%   r"   r!  _thread_metadata_for_source_reply_anchor_for_eventr  r   r  r   r   r   r   r  hermes_cli.model_cost_guardrL  r   r   r  r	  r  r  r  r(   _request_slash_confirmrR  )4r$   r*   r  r  r  r  r  r  model_inputr  force_refreshr  r  r@  rB  r  overrider&   
has_pickerr  r'  r)  r  r   r   tag
model_strsextra_cost_warningrL  rP  _pr  r  r   r!  rK  r  r"  r#  r$  rH  r  r  r  r%  rI  r  r=   rK   r&  rJ  s4   ``                              @@@@@@@@@@@@@@@@@@@@r'   _handle_model_commandz/GatewaySlashCommandsMixin._handle_model_command  s	      	CBBBBBBB	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	

 	322222))++1133 IZHYZbHcHcE&  	IIIIII++----    '
"]2	&&((C ?GGGR00	i.. E$-MM)R$@$@M'0}}ZAQ'R'R$'0}}Z'D'D$ WW[11
?QQQQQQ#B#B3#G#GLL  ? ? ?#&77+=#>#>LLL? 	 	 	D	 
 77??226::044["EE 	G$LL-@@M'||J8HII'||J8HII&ll9oFFO  w	$#4 w	$m''88Gt# RDMM+>EETQ 
  P$
# 5 5)9)9&3'1)5#%! ! !II ! # # # "III#  C$ !E#.L!.J$4M$4M#2Ll0 l0 l0 l0 l0 l0 l0 l0 l0 l0 l0 l0 l0 l0 l0 l0 l0 l0\  $??HdHdejHkHkllH#*#<#< &"+&3)9$/*<!) $= $ $      F ~ $#t 'Y'788N4M<VYaoppprtuE88%5%5"/#-%1   	 # 	% 	%A<=lOS!7888QSCLL!Rai!R!R&	!R!RC!R!R!RSSS{ <%)YY.M.M8.M.M.M%M%M
uv  xF  vG  JM  NO  PX  NY  JZ  JZ  vZ  vZ"DAnL]`cdefndo`p`pLp q q q q  `b%=*%=e%=%=>>>>y)) <%:1Y<%:%:%:;;;LL$$$$	%     LL=>>???LL@AABBBLL899:::99U### !-'-+$/%)

 

 

 ~ 	O19MNNNNP	$ P	$ P	$ P	$ P	$ P	$ P	$ P	$ P	$ P	$ P	$ P	$ P	$ P	$ P	$ P	$ P	$p 	!KKKKKK")"3' /B,<B?/?R!,# # #      MM  	! 	! 	! MMM	!$	. 	. 	. 	. 	. 	. 	. //0EFFB44/*]=R * *.0* *IK* * * ) 5 
 
 
 
 
 
 
 
 
 $^%%%%%%%%%s   0B 
BB#BE* 2E E* E&#E* %E&&E* *
E76E7,I> >JJ+D;Q' '
Q43Q47AU? ?VVc                j  K   ddl m} |r&|                                                                nd}|                    |          \  }}|rdd                    |          z   S 	 ddlm}m} n# t          $ r}d| cY d}~S d}~ww xY w |            }	|
                    |	|||nd	          }
|
j        rf|d|
j        r]	 |                     |j                  }|                     |           n,# t          $ r t                               d
d           Y nw xY w|
j        rdnd}| d|
j         S )u9  Handle /codex-runtime command in the gateway.

        Same surface as the CLI handler in cli.py:
            /codex-runtime                  — show current state
            /codex-runtime auto             — Hermes default runtime
            /codex-runtime codex_app_server — codex subprocess runtime
            /codex-runtime on / off         — synonyms

        On change, the cached agent for this session is evicted so the next
        message creates a fresh AIAgent with the new api_mode wired in
        (avoids prompt-cache invalidation mid-session).r   )codex_runtime_switchr7   u   ❌ u   
❌ )load_configr8  u   ❌ Could not load config: N)persist_callbackz7could not evict cached agent after codex-runtime changeTrE   u   ✓u   ✗rA  )r   rg  rf   rg   
parse_argsr   r=  rh  r8  rX   applyr  requires_new_sessionrL   rK   rU   ro   rp   rR  )r$   r*   crsr  	new_valueerrorsrh  r8  r   r@  r  r=   prefixs                r'   _handle_codex_runtime_commandz7GatewaySlashCommandsMixin._handle_codex_runtime_command{  s      	;:::::7<D5))++11333"NN844	6 	2HMM&1111	7BBBBBBBBB 	7 	7 	7666666666	7kmm-6-Bkk  
 
 > 	,i38S3,"::5<HH((5555 , , ,V&*  , , , , ,, !.3e++6>+++s0   &A/ /
B9B=BB/C2 2&DDc                l  K   ddl m}m} ddlm} |                                                                                                }|dz  }	  |            }t          |ddi           }n# t          $ r i }i }Y nw xY w|st          d |            	          S |st          d
          g}	|	                    t          d                     |                                D ]\  }
}t          |t                    r4|                    d          p|                    dd          dd         }n"t!          |          dk    r|dd         dz   n|}|	                    t          d|
|                     |	                    t          d                     d                    |	          S d }|dv r	 d|vs(t          |                    d          t                    si |d<   d|d         d<   t%          ||           n5# t          $ r(}t          dt'          |                    cY d}~S d}~ww xY wd| _        t          d          S ||v r |||                   }	 d|vs(t          |                    d          t                    si |d<   ||d         d<   t%          ||           n5# t          $ r(}t          dt'          |                    cY d}~S d}~ww xY w|| _        t          d|          S dd                    d |D                       z   }t          d ||!          S )"z8Handle /personality command - list or set a personality.r   r  r   r  rV  personalitiesr  z#gateway.personality.none_configured)r  zgateway.personality.headerzgateway.personality.none_optionr  system_promptr7   Nr  rE  zgateway.personality.item)rr  previewzgateway.personality.usager   c                   t          | t                    r|                     dd          g}|                     d          r|                    d| d                     |                     d          r|                    d| d                     d                    d |D                       S t          |           S )	Nru  r7   tonezTone: stylezStyle: r   c              3     K   | ]}||V  	d S r+  r   r   s     r'   r   zaGatewaySlashCommandsMixin._handle_personality_command.<locals>._resolve_prompt.<locals>.<genexpr>  s'       7 7qQ 7 7 7 7 7 7 7r)   )rR   r  r#   r   r   r   )r`   r  s     r'   _resolve_promptzNGatewaySlashCommandsMixin._handle_personality_command.<locals>._resolve_prompt  s    %&& 8?B77899V$$ ;LL!9%-!9!9:::99W%% =LL!;5>!;!;<<<yy 7 7E 7 7 7777u::r)   >   r   r  neutralzgateway.personality.save_failedrA   zgateway.personality.clearedzgateway.personality.set_torr  z`none`, r   c              3  "   K   | ]
}d | d V  dS r1  r   )r   ns     r'   r   zHGatewaySlashCommandsMixin._handle_personality_command.<locals>.<genexpr>  s*      *K*K8q888*K*K*K*K*K*Kr)   zgateway.personality.unknown)rr  	available)rG  r  r  r   r   rf   rg   r   r   rX   r   r   rJ  rR   r  r#   r   r   r   r   _ephemeral_system_prompt)r$   r*   r  r  r   argsrH  r   rs  r   rr  promptrv  r{  r   
new_promptr  s                    r'   _handle_personality_commandz5GatewaySlashCommandsMixin._handle_personality_command  s     BBBBBBBB888888%%''--//5577"]2	))++F#FG_bQQQMM 	 	 	FMMM	  	X:ATATAVAVWWWW 
	$3445ELL<==>>> - 3 3 5 5 X Xffd++ R$jj77_6::oWY;Z;Z[^\^[^;_GG58[[25E5EfSbSkE116GQ9gVVVWWWWLL67788899U###	 	 	 111J&((
6::g;N;NPT0U0U(&(F7O35w0!+v6666 J J J:#a&&IIIIIIIIIJ,.D)2333]""(t)<==JJ&((
6::g;N;NPT0U0U(&(F7O3=w0!+v6666 J J J:#a&&IIIIIIIIIJ -7D)1====*K*K]*K*K*K!K!KK	.TYOOOOsP   A- -A>=A>:AH 
H9H4.H94H9(AJ5 5
K'?K"K'"K'c                ^  K   |j         }| j                            |          }| j                            |j                  }d}d}t          t          |          dz
  dd          D ]A}||                             d          dk    r ||                             dd          }|} nB|st          d          S |d|         }| j        	                    |j        |           d	|_
        t          |t          j        ||j        |j        
          }	|                     |	           d{V S )z6Handle /retry command - re-send the last user message.Nr   roleuserro  r7   zgateway.retry.no_previousr   )r   message_typerK   raw_messagechannel_prompt)rK   rO   re   load_transcriptr9   ranger   r#   r   rewrite_transcriptlast_prompt_tokensr   r   TEXTr  r  _handle_message)
r$   r*   rK   r  historylast_user_msglast_user_idxr   	truncatedretry_events
             r'   _handle_retry_commandz/GatewaySlashCommandsMixin._handle_retry_command  sR     *@@HH$44]5MNN s7||a'R00 	 	Aqz~~f%%// '
y" = = ! 0
  	20111 N]N+	--m.F	RRR+,( #$)) /
 
 
 ))+666666666r)   'MessageEvent'c                  K   |                                 pd                                }|                                }|                     |          \  }}|t	          d          S |r|dk    r|                                S |dk    r|                    d          }|t	          d          S 	 |j        r$| j        	                    |j        j
                  nd}|j        r|                     |j                  nd}|r|r|                     ||           n2# t          $ r%}	t                              d	|	           Y d}	~	nd}	~	ww xY wt	          d
|j                  S |dk    r;|                                }|t	          d          S t	          d|j                  S |dv r|                                }
|                                 	 |j        r$| j        	                    |j        j
                  nd}|j        r|                     |j                  nd}|r|r|                     ||           n2# t          $ r%}	t                              d|	           Y d}	~	nd}	~	ww xY w|
rt	          d          nt	          d          S 	 |                    |          }n5# t*          $ r(}	t	          dt-          |	                    cY d}	~	S d}	~	ww xY w|j        r$| j        	                    |j        j
                  nd}|j        r|                     |j                  nd}|r|r}	 t/          |j        t0          j        |j        |j        |j                  }|                     |||           n2# t          $ r%}	t                              d|	           Y d}	~	nd}	~	ww xY wt	          d|j        |j                  S )u  Handle /goal for gateway platforms.

        Subcommands: ``/goal`` / ``/goal status`` / ``/goal pause`` /
        ``/goal resume`` / ``/goal clear``. Any other text becomes the
        new goal.

        Setting a new goal queues the goal text as the next turn so the
        agent starts working on it immediately — the post-turn
        continuation hook then takes over from there.
        r7   Ngateway.goal.unavailabler:  r|  zuser-pausedr.   zgateway.goal.no_goal_setz3goal pause: pending continuation cleanup failed: %szgateway.goal.paused)goalr}  zgateway.goal.no_resumezgateway.goal.resumed>   r>  stopclearz3goal clear: pending continuation cleanup failed: %szgateway.goal_clearedzgateway.no_active_goalzgateway.goal.invalidrA   )r   r  rK   r  r  zgoal kickoff enqueue failed: %szgateway.goal.set)budgetr  )rf   rg   r   _get_goal_manager_for_eventr   status_liner|  rK   r   r#   r%   rL   !_clear_goal_pending_continuationsrX   ro   rp   r  r}  has_goalr  r   rk   r   r   r   r  r  r  _enqueue_fifo	max_turns)r$   r*   r  r   mgrr  r   r&   
_quick_keyr   hadkickoff_events               r'   _handle_goal_commandz.GatewaySlashCommandsMixin._handle_goal_command  sF      &&((.B5577

!==eDD];/000 	%u((??$$$GII]I33E}3444YFKl\$-++EL,ABBBX\KP<aT99%,GGG]a
 Pz P:::wOOO Y Y YRTWXXXXXXXXY*<<<<HJJLLE}1222+%*====---,,..CIIKKKYFKl\$-++EL,ABBBX\KP<aT99%,GGG]a
 Pz P:::wOOO Y Y YRTWXXXXXXXXY03T1+,,,;S9T9TT	=GGDMMEE 	= 	= 	=+3s88<<<<<<<<<	=
 ?DlT$-##EL$9:::PTCH<YT11%,???UY
 	Ez 	E
E ,!,!1 <$/#(#7! ! ! "":}gFFFF E E E>DDDDDDDDE #EO%*MMMMsi   2A*D 
E'EEA*H> >
I-I((I-J' '
K1KKK1A	M; ;
N*N%%N*c                Z  K   |                                 pd                                }|                     |          \  }}|t          d          S |                                sdS |s+|                                 d|                                 S |                    dd          }|d                                         }t          |          dk    r|d                                         nd}|dk    r|sd	S 	 t          |                                d                   }n# t          $ r Y d
S w xY w	 |                    |          }	n## t          t          f$ r}
d|
 cY d}
~
S d}
~
ww xY wd| d|	 S |dk    rG	 |                                }n# t          $ r}
d|
 cY d}
~
S d}
~
ww xY w|rd| d|dk    rdnd dS dS 	 |                    |          }n## t          t          f$ r}
d|
 cY d}
~
S d}
~
ww xY w|j        rt          |j        j                  nd}d| d| S )a
  Handle /subgoal for gateway platforms (mirror of CLI handler).

        Subgoals are extra criteria appended to the active goal mid-loop.
        They modify state read at the next turn boundary, so this is safe
        to invoke while the agent is running.
        r7   Nr  z*No active goal. Set one with /goal <text>.r   r   r   removezUsage: /subgoal remove <n>z8/subgoal remove: <n> must be an integer (1-based index).z/subgoal remove: u   ✓ Removed subgoal z: r  z/subgoal clear: u   ✓ Cleared z subgoals.zNo subgoals to clear.z
/subgoal: u   ✓ Added subgoal )rf   rg   r  r   r  r  render_subgoalsr   r   r   rM  rk   remove_subgoal
IndexErrorRuntimeErrorclear_subgoalsadd_subgoalr   subgoals)r$   r*   r  r  _session_entryr   verbrestr[  removedr   prevr   s                r'   _handle_subgoal_commandz1GatewaySlashCommandsMixin._handle_subgoal_command_  s      &&((.B5577">>uEE^;/000||~~ 	@??  	Coo''BB3+>+>+@+@BBBD!$$ay  $'KK!OOvay   8 433R$**,,q/** R R RQQQR1,,S11- 1 1 103000000001:#:::::7??0))++ 0 0 0/#////////0 POdOO4199CC"OOOO**	&??4((DDL) 	& 	& 	&%%%%%%%%%	&),9c#)$%%%1C114111sl   'D) )
D76D7;E E1"E,&E1,E1F 
F1"F,&F1,F1
G   H 1G;5H ;H c                0  K   |j         }d}|                                                                }|rq	 t          |                                d                   }n@# t
          t          f$ r, t          d|                                d                   cY S w xY w|dk     rd}| j        	                    |          }| j        
                    |j        |          }|t          d          S d|_        	 t          |          }|                     |           n2# t          $ r%}t                               d|           Y d}~nd}~ww xY w|d         }	t%          |	          d	k    r|	dd	         d
z   n|	}
t          d|d         |d         |
          S )u4  Handle /undo [N] — back up N user turns (default 1), soft-deleting
        the truncated rows on disk and echoing the backed-up message text so
        the user can copy/edit and resend.

        Mirrors the CLI/TUI /undo: rewound rows stay in state.db (active=0)
        for audit and are hidden from re-prompts and search. The cached agent
        is evicted so the next message rebuilds context from the truncated
        (active-only) transcript — the gateway's equivalent of the CLI's
        in-place history surgery + memory-cache invalidation.
        r   r   zgateway.undo.invalid_countargNzgateway.undo.nothingz'undo: cached-agent eviction skipped: %starget_text   rE  zgateway.undo.removedturns_undonerewound_count)turnsr   rv  )rK   rf   rg   rM  r   rk   r  r   rO   re   rewind_sessionr9   r  r   rU   rX   ro   rp   r   )r$   r*   rK   r  r  r  r  r=   r   r  rv  s              r'   _handle_undo_commandz.GatewaySlashCommandsMixin._handle_undo_command  s       ))++1133 	P((+,,
+ P P P58>>;K;KA;NOOOOOOP1uu*@@HH#22=3KQOO>+,,, ,-(	G+F33K$$[1111 	G 	G 	GLLBAFFFFFFFF	G ]+/2;/?/?#/E/E+dsd#e++;"()	
 
 
 	
s)   'A :BB8$D 
E'EEc                ~  K   ddl m}m} |j        }|j        r|j        j        nd}|j        }|j        p|} ||          } ||          }	|j        }
	 ddl	m
}  ||t          |                      ||	t          |
pd                     n(# t          $ r}t          d|          cY d}~S d}~ww xY w|j        rn| j        j                            |j        t#          d	
                    }t%          |j        t          |          ||
rt          |
          nd          |_        t          d||          S )zOHandle /sethome command -- set the current chat as the platform's home channel.r   )_home_target_env_var_home_thread_env_varr*  )save_env_valuer7   zgateway.set_home.save_failedrA   NTr   )r%   r   rr  r   zgateway.set_home.success)rr  r   )rG  r  r  rK   r%   r`   r   r  r   r=  r  r   rX   r   r   r   
setdefaultr   r   home_channel)r$   r*   r  r  rK   platform_namer   r  env_keythread_env_keyr   r  r   platform_configs                 r'   _handle_set_home_commandz2GatewaySlashCommandsMixin._handle_set_home_command  s     JJJJJJJJ17O--i.$/	&&}55--m<<$		>888888N7CLL111 N>3yB+?+?@@@@ 	> 	> 	>31=========	>
 ? 
	"k3>>t,,, O ,7G,5?#i...4	, , ,O( +)WMMMMs   :B 
B5B0*B50B5c                P  K   |                                                                                                 }|j        j        }|j        j        }|                     ||          }| j                            |          }|dv rGd| j	        |<   | 
                                 |r|                     ||d           t          d          S |dv rGd| j	        |<   | 
                                 |r|                     ||d           t          d	          S |d
k    rGd| j	        |<   | 
                                 |r|                     ||d           t          d          S |dv r|                     |           d{V S |dk    r|                     |           d{V S |dk    r| j	                            |d          }t          d          t          d          t          d          d}| j                            |j        j                  }|                     |          }	|	rt#          |d          r|                    |	          }
|
rt          d|                    ||                    t          d|
d                   t          d|
d                   g}|
d         D ]S}|                    d          rt          d           nd!}|                    t          d"|d#         |$                     Td%                    |          S t          d|                    ||                    S | j	                            |d          }|dk    rHd| j	        |<   | 
                                 |r|                     ||d           t          d&          }nGd| j	        |<   | 
                                 |r|                     ||d           t          d'          }|duot#          |d(          }|rt          d)          nd!}t          d*||+          S ),z8Handle /voice [on|off|tts|channel|leave|status] command.>   onenable
voice_onlyTr  z gateway.voice.enabled_voice_only>   offdisabler  )disabledzgateway.voice.disabled_textttsallzgateway.voice.tts_enabled>   r   channelNleaver:  zgateway.voice.label_offzgateway.voice.label_voice_onlyzgateway.voice.label_all)r  r  r  get_voice_channel_infozgateway.voice.status_modelabelzgateway.voice.status_channelchannel_name)r  z!gateway.voice.status_participantsmember_countr   membersis_speakingzgateway.voice.speakingr7   zgateway.voice.status_memberdisplay_name)rr  r:  r   zgateway.voice.enabled_shortzgateway.voice.disabled_shortjoin_voice_channelzgateway.voice.help_channelszgateway.voice.help)togglechannels)rf   rg   r   rK   r   r%   
_voice_keyr   r#   _voice_mode_save_voice_modes_set_adapter_auto_tts_enabledr   _set_adapter_auto_tts_disabled_handle_voice_channel_join_handle_voice_channel_leave_get_guild_idr]   r  r   r   )r$   r*   r  r   r%   	voice_keyr&   modelabelsguild_idrh  r   r   r:  r(  toggle_linesupports_voice_channelsr  s                     r'   _handle_voice_commandz/GatewaySlashCommandsMixin._handle_voice_command  s     %%''--//5577,&<(OOHg66	-##H--###*6DY'""$$$ S227GT2RRR7888'''*/DY'""$$$ U33GWt3TTT2333U]]*/DY'""$$$ S227GT2RRR0111(((88?????????W__99%@@@@@@@@@X#''	599D233 @AA233 F m''(=>>G))%00H ,GG-EFF ,55h?? 	,5VZZd=S=STTT8$~BVWWW=T.EYZZZE
 ")_ n n@Am@T@T!\#;!<!<!<Z\Q'D1^K\ek%l%l%lmmmm99U+++0

48N8NOOOO &**9e<<G%.: +&&((( W66wQU6VVV =>>.3 +&&((( Y77SW7XXX >??
 '.T&9 'g-? ?# 5LS/000QS  )+QQQQr)   c           	       K   ddl m} ddlm}m} i }	 ddl}|dz  }|                                rot          |d          5 }|                    |          pi }	ddd           n# 1 swxY w Y   |		                    di           }t          |t                    rd	|i}n# t          $ r Y nw xY w|	                    d	d
          st          d          S  |d|	                    dd          |	                    dd          |	                    dd                    }
t          j        dt!          t#          j                                        }|                                                                }|s!|
                    |          } |||          S |
                    |          }|st          d|          S d}	 t-          |          dz
  }d|cxk    rt/          |          k     rn n||         d         }nt          dt/          |                    S n# t0          $ r |}Y nw xY w|
                    ||          }|d         rt          d|d         |d                   S t          d |d!         "          S )#uD   Handle /rollback command — list or restore filesystem checkpoints.r   r  )CheckpointManagerformat_checkpoint_listNr  r  r6  checkpointsr   Fzgateway.rollback.not_enabledTmax_snapshotsr  max_total_size_mbi  max_file_size_mbr  )r   r  r  r  TERMINAL_CWDzgateway.rollback.none_found)cwdr   hashzgateway.rollback.invalid_number)rL  r  zgateway.rollback.restoredrestored_tor/   )r   r/   zgateway.rollback.restore_failedrB   rA   )rG  r  tools.checkpoint_managerr  r  rJ  r  r;  r<  r#   rR   r)  rX   r   r	  r
  r   r   r   rf   rg   list_checkpointsrM  r   rk   restore)r$   r*   r  r  r  cp_cfg_y	_cfg_path_f_datar  r  r  r  target_hashr[  r  s                    r'   _handle_rollback_commandz2GatewaySlashCommandsMixin._handle_rollback_command:  sE     ,,,,,,VVVVVVVV 
	$}4I!! 1)g666 3"LL,,2E3 3 3 3 3 3 3 3 3 3 3 3 3 3 3="55fd++ 1'0F 	 	 	D	 zz)U++ 	53444 **_b99$jj)<cBB#ZZ(:B??	
 
 
 iDIKK(8(899$$&&,,.. 	<..s33K))+s;;; **3// 	=2<<<<	c((Q,CC****#k*******)#.v6:K@P@PQQQQ   	 	 	KKK	 S+..) 	+M*h'   
 2&/JJJJsH   .B! A&B! &A**B! -A*.2B! !
B.-B.AH% %H43H4c           
       K   |                                                                 }|st          d          S |j        }dt	          j                                        d           dt          j        d          	                                 }| 
                    |          }|j        rt          |j                  ng }|j        rt          |j                  ng }t          j        |                     ||||||                    }| j                            |           |                    | j        j                   |dd         t+          |          dk    rd	nd
z   }	t          d|	|          S )u)  Handle /background <prompt> — run a prompt in a separate background session.

        Spawns a new AIAgent in a background thread with its own session.
        When it completes, sends the result back to the same chat without
        modifying the active session's conversation history.
        zgateway.background.usagebg_z%H%M%S_   )event_message_id
media_urlsmedia_typesN<   rE  r7   zgateway.background.started)rv  r   )rf   rg   r   rK   r   rQ  r  r	  urandomhexrY  r  rq  r  r   create_task_run_background_taskr?  r   add_done_callbackdiscardr   )
r$   r*   r  rK   r   r  r  r  _taskrv  s
             r'   _handle_background_commandz4GatewaySlashCommandsMixin._handle_background_commandv  s}      ''))//11 	1/000Q//99QQBJqMM<M<M<O<OQQ77>> 05/?GT%*+++R
161BJd5,--- #%%!1%' &  	
 	
 	""5))) 6 >???"+#f++*:*:C-wPPPPr)   c                  K   ddl m}m} ddl|                                                                }|                     |          \  }}|dz  |                     |j                  }| 	                    |          }| 
                                | _        |                     |j        |          | _        d+fd}	|s| j        }
|
t          d	          }n=|
                    d
          du rt          d          }n|
                    dd          }| j        rt          d          nt          d          }|t!          | di           pi v }|rt          d          nt          d          }t          d|||          S  ||j        j                  }|dv r(d| _         |	d| dd           t          d|          S |dv r(d| _         |	d| dd           t          d|          S |                                }|dk    rd|rt          d          S |                     |d           |                                 | _        |                     |           t          d           S |d!k    rd
di}n/|d"v rd|d#}n%t          d$|p|                                %          S || _        |r |	d&|          r<|                     |d           |                     |           t          d'|(          S |                     ||           |                     |           t          d)|(          S |                     ||           |                     |           t          d*|(          S ),u]  Handle /reasoning command — manage reasoning effort and display toggle.

        Usage:
            /reasoning                       Show current effort level and display state
            /reasoning <level>               Set reasoning effort for this session only
            /reasoning <level> --global      Persist reasoning effort to config.yaml
            /reasoning reset                 Clear this session's reasoning override
            /reasoning show|on               Show model reasoning in responses
            /reasoning hide|off              Hide model reasoning from responses
        r   )r  _platform_config_keyNr  rK   r=   key_pathr   c                   	 i }                                 r@t          d          5 }	                    |          pi }ddd           n# 1 swxY w Y   |                     d          }|}|dd         D ].}||vst	          ||         t
                    si ||<   ||         }/|||d         <   t          |           dS # t          $ r'}t          	                    d| |           Y d}~dS d}~ww xY w	z(Save a dot-separated key to config.yaml.r  r6  Nr  r  Tz Failed to save config key %s: %sF
r  r;  r<  r   rR   r  r   rX   ro   rB   
r  r`   user_configr?  r   r(  kr   rH  rJ  s
           r'   _save_config_keyzMGatewaySlashCommandsMixin._handle_reasoning_command.<locals>._save_config_key  a    %%'' >kG<<< >&*nnQ&7&7&=2> > > > > > > > > > > > > > >~~c**%crc ) )A''z'!*d/K/K'%'
%ajGG$)R!!+{;;;t   ?1MMMuuuuu;   'C AC AC AA.C 
C7C22C7zgateway.reasoning.level_defaultr   Fz gateway.reasoning.level_disabledeffortmediumzgateway.reasoning.display_onzgateway.reasoning.display_off_session_reasoning_overrideszgateway.reasoning.scope_sessionzgateway.reasoning.scope_globalzgateway.reasoning.status)levelr   r   >   r  showTzdisplay.platforms.z.show_reasoningz gateway.reasoning.display_set_onr%   >   r  hidez!gateway.reasoning.display_set_offresetz*gateway.reasoning.reset_global_unsupportedzgateway.reasoning.reset_doner   >   lowhighxhighr*  minimal)r   r)  zgateway.reasoning.unknown_argr  zagent.reasoning_effortzgateway.reasoning.set_global)r)  z(gateway.reasoning.set_global_save_failedzgateway.reasoning.set_sessionr  r   )rG  r  r  rJ  rf   rg   _parse_reasoning_command_argsrW  rK   rL   _load_show_reasoning_show_reasoning!_resolve_session_reasoning_config_reasoning_configr   r#   r"   r%   r\   _load_reasoning_configrU   r   )r$   r*   r  r  r  r  rI  _reasoning_sourcer=   r&  rcr,  display_statehas_session_overrider   platform_keyr)  parsedrH  rJ  s                     @@r'   _handle_reasoning_commandz3GatewaySlashCommandsMixin._handle_reasoning_command  sV      	CBBBBBBB))++1133#AA(KKn"]2 !BB5<PP223DEE#88::!%!G!G<# "H "
 "

	 	 	 	 	 	 	(  	'Bz;<<	""e++<==x22 '80111677 
 $/74A_ac3d3d3jhj#k  (93444788 
 *%	    ,+EL,ABB>!!#'D O,OOOQUVVV7,OOOO?""#(D O,OOOQVWWW8<PPPP W GEFFF00dCCC%)%@%@%B%BD"$$[1113444V'FFDDD!%88FF/.hnn..   
 "( 	P 8&AA H44[$GGG((5557GGGG00fEEE$$[111?OOOO,,[&AAA  ---0@@@@r)   c                v   K   ddl m} ddlm} ddlm} ddlm} |                                	                                }|r|
                                ng }                     |j                  |dz  d fd	} |            }	|	                                  ||j        ||	|
          }
|
d}
|
S )uv  Handle /memory — review pending memory writes + toggle the approval gate.

        Memory entries are small enough to review inline in a chat bubble, so
        the full pending/approve/reject/approval flow works on every platform.
        Gate changes persist to config.yaml and evict the cached agent so the
        new setting takes effect on the next message.
        r   r  handle_pending_subcommandwrite_approval)MemoryStorer  r   r)  c                R   dd l }i }                                r@t          d          5 }|                    |          pi }d d d            n# 1 swxY w Y   t	          |           |                    di           d<   t          |                                          d S )Nr   r  r6  memoryrG  rJ  r  r;  r<  r)  r  r   rU   r   rJ  r$  r?  rH  r$   r=   s       r'   _set_approvalzGGatewaySlashCommandsMixin._handle_memory_command.<locals>._set_approval%      KKKK!!## :+888 :A"&.."3"3"9rK: : : : : : : : : : : : : : :EI']]K""8R001ABk;777$$[11111   AAA)memory_storeset_mode_fnNzWUnknown /memory subcommand. Use: pending, approve <id>, reject <id>, approval <on|off>.r   r)  )rG  r  "hermes_cli.write_approval_commandsrE  toolsrG  tools.memory_toolrH  rf   rg   r   rL   rK   load_from_diskMEMORY)r$   r*   r  rE  warH  r  r  rM  storeoutrH  r=   s   `          @@r'   _handle_memory_commandz0GatewaySlashCommandsMixin._handle_memory_command  s$      	-,,,,,PPPPPP......111111))++1133#+3x~~225<@@"]2		2 		2 		2 		2 		2 		2 		2 		2 ''It%]
 
 
 ;5C
r)   c                   K   ddl m} ddlm} ddlm} |                                                                }|r|                                ng } 	                    |j
                  |dz  |                    |j                  }t          |          o|d                                         dv }|s"|s |                    |j                  dk    rdS d fd
}	 ||j        ||	          }
|
dS |rb|d                                         dk    rDt!          |
          dk    r1t!          |          dk    r|d         nd}|
dd         d| d| dz   }
|
S )u  Handle /skills on the gateway — pending skill-write review only.

        The full skills hub (search/browse/install) stays CLI-only; this
        handler covers the write-approval review surface (pending / approve /
        reject / diff / approval) so a skill staged from a gateway session can
        be reviewed from that same session. Gated by ``skills.write_approval``
        via the CommandDef's ``gateway_config_gate``; also answers when staged
        writes still exist after the gate was turned off (so they are never
        stranded).

        ``diff`` output is truncated for chat bubbles — the full diff lives in
        the CLI (``/skills diff <id>``) and the pending JSON file.
        r   r  rD  rF  r  >   r  approvalzSkill write approval is off (skills.write_approval). Enable it with /skills approval on, then review staged writes here with /skills pending.r   r)  c                R   dd l }i }                                r@t          d          5 }|                    |          pi }d d d            n# 1 swxY w Y   t	          |           |                    di           d<   t          |                                          d S )Nr   r  r6  skillsrG  rK  rL  s       r'   rM  zGGatewaySlashCommandsMixin._handle_skills_command.<locals>._set_approval[  rN  rO  )rQ  NzUnknown /skills subcommand on this platform. Use: pending, approve <id>, reject <id>, diff <id>, approval <on|off>. (Search/install are CLI-only.)diffi  r   z<id>u-   
… (truncated — full diff: `/skills diff z*` on the CLI, or ~/.hermes/pending/skills/z.json)rR  )rG  r  rS  rE  rT  rG  rf   rg   r   rL   rK   write_approval_enabledSKILLSr)  r   pending_countr   )r$   r*   r  rE  rX  r  r  gate_onwants_togglerM  rZ  
pending_idrH  r=   s   `           @@r'   _handle_skills_commandz0GatewaySlashCommandsMixin._handle_skills_command=  s      	-,,,,,PPPPPP......))++1133#+3x~~225<@@"]2++BI66DzzMd1gmmoo9M&M 	9| 	90@0@0K0Kq0P0P8 8		2 		2 		2 		2 		2 		2 		2 		2 ('It
 
 
 ;5 5  	TDGMMOOv--#c((T//$'IIMMavJuu:Sj S S@JS S SSC 
r)   c                  K   ddl m}m}m} ddlddlm} |                                                                	                                }|dz  | 
                                | _         |            } ||          } ||          st          d          S dfd	}	|r|d
k    r:| j        dk    rt          d          nt          d          }
t          d|
          S |dv rd| _        d}t          d          }n.|dv rd| _        d}t          d          }nt          d|          S  |	d|          rt          d|          S t          d|          S )uL   Handle /fast — mirror the CLI Priority Processing toggle in gateway chats.r   )r  r  _resolve_gateway_modelN)model_supports_fast_moder  zgateway.fast.not_supportedr  r   c                   	 i }                                 r@t          d          5 }	                    |          pi }ddd           n# 1 swxY w Y   |                     d          }|}|dd         D ].}||vst	          ||         t
                    si ||<   ||         }/|||d         <   t          |           dS # t          $ r'}t          	                    d| |           Y d}~dS d}~ww xY wr!  r"  r#  s
           r'   r&  zHGatewaySlashCommandsMixin._handle_fast_command.<locals>._save_config_key  r'  r(  r:  priorityzgateway.fast.status_fastzgateway.fast.status_normalzgateway.fast.status)r  >   r  fastrm  zgateway.fast.label_fast>   r  normalrn  zgateway.fast.label_normalzgateway.fast.unknown_argr  zagent.service_tierzgateway.fast.savedr  zgateway.fast.session_onlyr5  )rG  r  r  ri  rJ  rV  rj  rf   rg   r   _load_service_tier_service_tierr   )r$   r*   r  r  ri  rj  r  r$  r3  r&  r:  saved_valuer  rH  rJ  s                @@r'   _handle_fast_commandz.GatewaySlashCommandsMixin._handle_fast_commandw  s     ZZZZZZZZZZ>>>>>>%%''--//5577"]2!4466**,,&&{33''.. 	31222	 	 	 	 	 	 	(  	9tx''6:6HJ6V6VQ1222\]^z\{\{F*8888>!!!+D K/00EE&&&!%D"K122EE/T::::0+>> 	8)7777,E::::r)   c                  K   ddl m}m}m} |                     |j                  } ||          }|r' ||           t          t          d                    S  ||           t          t          d                    S )uP   Handle /yolo — toggle dangerous command approval bypass for this session only.r   )disable_session_yoloenable_session_yolois_session_yolo_enabledzgateway.yolo.disabledzgateway.yolo.enabled)tools.approvalrt  ru  rv  rL   rK   r   r   )r$   r*   rt  ru  rv  r=   r(  s          r'   _handle_yolo_commandz.GatewaySlashCommandsMixin._handle_yolo_command  s      	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 225<@@))+66 	=  ---!!$;"<"<===,,,!!$:";";<<<r)   c                t  K   ddl m}m}m} |dz  } ||j        j                  }	  |            }t          t          |dd          d          }n# t          $ r d}Y nw xY w|st          d          S g d	}	t          d
          t          d          t          d          t          d          d	}
ddl
m}  |||dd          }||	vrd}|	                    |          dz   t          |	          z  }|	|         }	 d|vs(t          |                    d          t                     si |d<   |d         }d|vs(t          |                    d          t                     si |d<   ||d         vs.t          |d                             |          t                     si |d         |<   ||d         |         d<   t#          ||           |
|          dt          d|          z   S # t          $ rB}t$                              d|           |
|          dt          d|          z   cY d}~S d}~ww xY w)u  Handle /verbose command — cycle tool progress display mode.

        Gated by ``display.tool_progress_command`` in config.yaml (default off).
        When enabled, cycles the tool progress mode through off → new → all →
        verbose → off for the *current platform*.  The setting is saved to
        ``display.platforms.<platform>.tool_progress`` so each channel can
        have its own verbosity level independently.
        r   )r  r  r  r  r   tool_progress_commandFrt  zgateway.verbose.not_enabled)r  newr  verbosezgateway.verbose.mode_offzgateway.verbose.mode_newzgateway.verbose.mode_allzgateway.verbose.mode_verbose)resolve_display_settingtool_progressr  r   r   r   zgateway.verbose.saved_suffixr.  z%Failed to save tool_progress mode: %szgateway.verbose.save_failedrA   N)rG  r  r  r  rK   r%   r   r   rX   r   gateway.display_configr}  indexr   rR   r#   r  r   ro   r   )r$   r*   r  r  r  rH  r@  r$  gate_enabledcycledescriptionsr}  r(  r[  new_moder   r   s                    r'   _handle_verbose_commandz1GatewaySlashCommandsMixin._handle_verbose_command  s      	YXXXXXXXXX"]2++EL,ABB	!..00K*Y0GHH  LL  	! 	! 	! LLL	!  	42333 100/00/00/00788	
 
 	CBBBBB))+|_V[\\%G{{7##a'3u::5:	]++:kooi>X>XZ^3_3_+)+I&!),G'))GKK<T<TVZ1[1[)')$7;#777z'R]J^JbJbcoJpJprv?w?w757$\2BJGK .?k;777)---2\JJJK  	] 	] 	]NNBAFFF"8,00015RZ[3\3\3\\\\\\\\	]s0   *A A"!A" C*G+ +
H757H2,H72H7c                  K   ddl m}m}m}m} ddlm} |dz  } ||j        j                  }d}		 t          |dd          pd
                                }
|
                    d          rU|
                    dd	          }t          |          d	k    r,|d	         
                                                                }	n# t          $ r d}	Y nw xY w	  |            }n(# t          $ r}t!          d
|          cY d}~S d}~ww xY w |||          }|	dv rc|d         rt!          d          nt!          d          }d                    |                    d          pg           }t!          d|||          S |	dv rd}n&|	dv rd}n|	dk    r
|d          }nt!          d          S 	 t'          |                    d          t(                    si |d<   |d         }t'          |                    d          t(                    si |d<   ||d         d<   t+          ||           nC# t          $ r6}t,                              d|           t!          d|          cY d}~S d}~ww xY w|rt!          d          nt!          d          }d}|rJddlm}  | ||          pddd|                    d          pg d          }|rt!          d |!          }t!          d"||#          S )$u8  Handle /footer command — toggle the runtime-metadata footer.

        Usage:
            /footer           → toggle on/off
            /footer on        → enable globally
            /footer off       → disable globally
            /footer status    → show current state + fields

        The footer is saved to ``display.runtime_footer.enabled`` (global).
        Per-platform overrides under ``display.platforms.<platform>.runtime_footer``
        are respected but not modified here — edit config.yaml directly for
        per-platform control.
        r   )r  r  r  ri  )resolve_footer_configr  r7   rR  Nr!   r   zgateway.config_read_failedrA   >   r:  r   r   zgateway.footer.state_onzgateway.footer.state_offr   fieldszgateway.footer.status)r   r  r%   >   1r  truer  T>   0r  falser  Fzgateway.footer.usager   runtime_footerz)Failed to save runtime_footer.enabled: %szgateway.config_save_failed)format_runtime_footer)r3  context_pctr  )r3  context_tokensr  r  zgateway.footer.example_linerv  zgateway.footer.saved)r   example)rG  r  r  r  ri  gateway.runtime_footerr  rK   r%   r"   rg   r   r   r   r   rX   r   r   r#   rR   r  r   ro   r   r  )r$   r*   r  r  r  ri  r  rH  r@  r  r   r  r$  r   	effectiver   r  	new_stater   r  r  rv  s                         r'   _handle_footer_commandz0GatewaySlashCommandsMixin._handle_footer_command  s      	qppppppppppp@@@@@@"]2++EL,ABB 	E9d339r@@BBDs## 3

4++u::>>(..**0022C 	 	 	CCC		< 4 4 6 6KK 	< 	< 	<1;;;;;;;;;	< *)+|DD	/!!4=i4HkA/000aPjNkNkEYYy}}X66<"==F'%	    ///II444IIBYY%i00II+,,,
	<kooi88$?? ,)+I&!),Ggkk*:;;TBB /,.()3<G$%i0k;7777 	< 	< 	<NNFJJJ1;;;;;;;;;	< 1:\+,,,qA[?\?\ 
	LDDDDDD++,,[99AT # }}X..Q2Q2Q2Q	  G  L97KKK'ugFFFFsO   BC CC
C   
D*D :D D)A=H' '
I'1+I"I'"I'c                "	  "#$%K   |j         }| j                            |          }| j                            |j                  }|rt          |          dk     rt          d          S ddlm}m	}m
} |                                pd                                } ||          \  }	}
#	 ddlm} ddlm} ddlm} |                     |          }|                     ||	          \  }}|                    d
          st          d          S d |D             }g }|$|	r |||
          \  $}|sd}	|$ |d-i ||ddddg|j        d%	 d %_        t/          %dd          pd}t/          %dd          pd} ||||          "%j        }|                    $          s9t          d          |                     |           |                     %           S t9          j                    }|                    d"#$%fd           d{V \  }}|	r|r |||          }%j        }||j        k    r8||_        | j                                         |                      ||d           | j        !                    ||           | j        "                    |j#        d            ||||          } |||"|          }tI          t/          |dd                    }t/          |dd          }t/          |dd          }t/          |dd          }|                     |           |                     %           n/# |                     |           |                     %           w xY wd|d           g} #r$| %                    t          d!#"                     | %                    |d#                    |d$         r| %                    |d$                    |r'| %                    t          d%|pd&'                     n)|r'| %                    t          d(||pd&)                     d*&                    |           S # tN          $ r6}!tP          )                    d+|!           t          d,|!'          cY d}!~!S d}!~!ww xY w).ab  Handle /compress command -- manually compress conversation context.

        Accepts an optional focus topic: ``/compress <focus>`` guides the
        summariser to preserve information related to *focus* while being
        more aggressive about discarding everything else.

        Also accepts the boundary-aware form ``/compress here [N]``:
        summarize everything except the most recent ``N`` exchanges
        (default 2), kept verbatim. Inspired by Claude Code's Rewind
        "Summarize up to here" action (v2.1.139, May 2026,
        https://code.claude.com/docs/en/whats-new/2026-w20).
           zgateway.compress.not_enoughr   )parse_partial_compress_argsrejoin_compressed_head_and_tail"split_history_for_partial_compressr7   )AIAgent)summarize_manual_compression)estimate_request_tokens_roughr  r  zgateway.compress.no_providerc                    g | ]Y}|                     d           dv |                     d          .|                     d           |                     d          dZS )r  >   r  	assistantro  )r  ro  r<  r2  s     r'   r   zFGatewaySlashCommandsMixin._handle_compress_command.<locals>.<listcomp>~	  sg       55==$999aeeI>N>N9 v1553C3CDD999r)   FTrJ  )r3  max_iterations
quiet_modeskip_memoryenabled_toolsetsr9   c                     d S r+  r   )akws     r'   r6  zDGatewaySlashCommandsMixin._handle_compress_command.<locals>.<lambda>	  s    t r)   _cached_system_promptrT  N)ru  rT  zgateway.compress.nothing_to_doc                 8                         d d          S )Nr7   T)approx_tokensfocus_topicforce)_compress_context)r  r  head	tmp_agents   r'   r6  zDGatewaySlashCommandsMixin._handle_compress_command.<locals>.<lambda>	  s-    I77bP]kv  C7  D  D r)   zcompress-commandr.   )r  _last_compress_aborted_last_summary_error_last_aux_model_failure_model_last_aux_model_failure_erroru   🗜️ headlinezgateway.compress.focus_line)topic
token_linenotezgateway.compress.abortedzunknown errorrA   zgateway.compress.aux_failed)r3  rB   r   zManual compress failed: %szgateway.compress.failedr   )*rK   rO   re   r  r9   r   r   hermes_cli.partial_compressr  r  r  rf   rg   	run_agentr  !agent.manual_compression_feedbackr  agent.model_metadatar  rL   _resolve_session_agent_runtimer#   	_print_fnr"   context_compressorhas_content_to_compressrU   rT   r   get_running_looprun_in_executor_save_sync_telegram_topic_bindingr  update_sessionr=   r)  r   r   rX   ro   r   )&r$   r*   rK   r  r  r  r  r  	_raw_argspartial	keep_lastr  r  r  r=   r3  runtime_kwargsmsgstail_sys_prompt_tools
compressorloop
compressedr  r;   
new_tokenssummary_summary_aborted_summary_err_aux_fail_model_aux_fail_errr   r   r  r  r  r  s&                                     @@@@r'   _handle_compress_commandz2GatewaySlashCommandsMixin._handle_compress_commandS	  sX      *@@HH$44]5MNN 	4#g,,**2333	
 	
 	
 	
 	
 	
 	
 	
 	
 	

 ++--3::<<	*E*Ei*P*P'KJ	9))))))VVVVVVJJJJJJ66v>>K$($G$G' %H % %!E> "%%i00 97888    D DD  ??iPP
d  #GD     "*(3   IH9&;&;	# &i1H"MMSQS GT::Bd = =6! ! ! '9
!99$?? ?=>>p ((555--i8888o /11&*&:&: D  D  D  D  D  D  D' ' ! ! ! ! ! !
A  St S!@!@T!R!RJ "+!5!]%===/=M,&,,...556H 6    "55njQQQ"11!-! 2    ;:k  
 76!	  $(
<TV[(\(\#]#] &z3H$OO #**6UW["\"\ '
4SUY Z Z ((555--i8888 ((555--i88885
 3556E RQ<KPPPQQQLL.///v .WV_--- 2+>      ! 5-,?     99U### 	9 	9 	9NN7;;;.a888888888	9sL   -A$Q >Q A&M 7*Q "D;M +Q ,M44CQ 
R+R	R	Rr7   r  c                h  K   |j         }|j        t          j        k    s|j        dk    rt          d          S | j        sddlm}  |t          d                    S t          | dd          }t          |          rH	  ||          st          d	          S n,# t          $ r t                              d
d           Y nw xY w|                                                                }|                                dv r|                                 S |                                dv r|                     |          S |r2|j        st          d          S |                     ||           d{V S |                     |           d{V }|                    d          r|                    d          du r?|                     |          r|                     |           d{V  t          d          S |                    d          du r?|                     |          r|                     |           d{V  t          d          S 	 | j                            t5          |j                  t5          |j                  |                    d          |                    d                     nB# t          $ r5}t                              d           t          d|          cY d}~S d}~ww xY w|j        s|                     |           d{V  |j        r	 | j                            t5          |j                  t5          |j                            }n.# t          $ r! t                              dd           d}Y nw xY w|rwt5          |                    d          pd          }	d}
	 | j                             |	          }
n# t          $ r d}
Y nw xY w|
pt          d          }t          d||	           S t          d!          S | !                    |          S )"z:Handle /topic for Telegram DM user-managed topic sessions.r   zgateway.topic.not_telegram_dmr   format_session_db_unavailable,gateway.shared.session_db_unavailable_prefixrp  rj  Nzgateway.topic.unauthorizedzTopic auth check failedTrE   >   -h--helpr   r   >   r  r  r  z!gateway.topic.restore_needs_topiccheckedhas_topics_enabledFzgateway.topic.topics_disabledallows_users_to_create_topicsz$gateway.topic.topics_user_disallowed)r   r<   r  r  z$Failed to enable Telegram topic modezgateway.topic.enable_failedrA   )r   r   z%Failed to read Telegram topic bindingr9   r7   zgateway.topic.untitled_sessionzgateway.topic.bound_status)r  r9   zgateway.topic.thread_ready)"rK   r%   r   r  r   r   rh   ri   r  r"   r"  rX   ro   rp   rf   rg   r   _telegram_topic_help_text%_disable_telegram_topic_mode_for_chatr   _restore_telegram_topic_session _get_telegram_topic_capabilitiesr#   %_should_send_telegram_capability_hint _send_telegram_topic_setup_imageenable_telegram_topic_moder   r   r<   	exception_ensure_telegram_system_topicget_telegram_topic_bindingr  #_telegram_topic_root_status_message)r$   r*   r  rK   r  auth_fnr  r   bindingr9   rD   session_labels               r'   _handle_topic_commandz/GatewaySlashCommandsMixin._handle_topic_command	  s     ?h///63Ct3K3K4555 	kBBBBBB00:h8i8ijjjj $ 5t<<G 	GGwv ;9:::; G G G6FFFFFG %%''--// ::<<88811333 ::<<555==fEEE 	K# ><=====eTJJJJJJJJJ!BB6JJJJJJJJI&& 
	A 455>> ==fEE H??GGGGGGGGG8999 ?@@EII==fEE H??GGGGGGGGG?@@@		?77FN++FN++#/#3#34H#I#I.:.>.>?^._._	 8      	? 	? 	?CDDD2#>>>>>>>>>	?  	=44V<<<<<<<<< 	3*EE//!&"233 F      DtTTT   \!:!:!@bAA
! ,>>zJJEE  ! ! ! EEE! % L+K)L)L0')   
 122277???sV    B &CCA(J< <
K;*K60K;6K;(A M) )(NN O O*)O*c                  K   |j         }| j                            |          }|j        }| j        sddlm}  |t          d                    S | j                            |          }|G	 | j        	                    ||j
        r|j
        j        nd|j                   n# t          $ r Y nw xY w|                                                                }|r	 | j                            |          }n(# t"          $ r}	t          d|		          cY d}	~	S d}	~	ww xY w|st          d
          S 	 | j                            ||          rt          d|          S t          d          S # t"          $ r}	t          d|		          cY d}	~	S d}	~	ww xY w| j                            |          }
|
rt          d||
          S t          d|          S )uB   Handle /title command — set or show the current session's title.r   r  r  r  Nr*  )r9   rK   r<   zgateway.shared.warn_passthroughrA   zgateway.title.empty_after_cleanzgateway.title.set_torC   zgateway.title.not_foundz gateway.title.current_with_title)r9   rD   zgateway.title.current_no_titler   )rK   rO   re   r9   rh   ri   r  r   r  create_sessionr%   r`   r<   rX   rf   rg   rj   rk   rl   )r$   r*   rK   r  r9   r  existing_title	title_argr~   r   rD   s              r'   _handle_title_commandz/GatewaySlashCommandsMixin._handle_title_commandV
  se     *@@HH"-
 	kBBBBBB00:h8i8ijjjj );;JGG! //)4:OR6?00"N 0    
     **,,2244	 	RE ,;;IFF		 E E E:!DDDDDDDDDE <:;;;E#55j)LL 839EEEE6777 E E E:!DDDDDDDDDE $66zBBE R;
Z_````9jQQQQsT   .5B$ $
B10B1C8 8
DDDD2+E- E- -
F7FFFc           	     *   K    j         sddlm}  |t          d                    S |j                                       }|                                                                }	 t          j	        |          }n(# t          $ r}t          d|          cY d}~S d}~ww xY wd|v }d	|v }d
                    d |D                                                       }	t          |	          dk    r||	d         dk    r|	d         dk    sH|	d         dk    r|	d         dk    s0|	d         dk    r|	d         dk    s|	d         dk    r(|	d         dk    r|	dd                                         }	dB fd}
|	s1	  |
            }j        t          j        k    rm|skg }|D ]d}                     t#          |                    d          pd                    }                     |          r|                    |           e|}|s5j        t          j        k    r|st          d          S t          d          S t          d          g}t+          |dd         d          D ]\  }}|d         }j        t          j        k    rN|rL                     t#          |                    d          pd                    }|r| d |j        p|j         }|                    d!d          dd"         }|rt          d#|$          nd}|                    t          d%|||&                     |                    t          d'                     d(                    |          S # t0          $ r6}t2                              d)|           t          d*|          cY d}~S d}~ww xY w|	                                rB	  |
            }j        t          j        k    rm|skg }|D ]d}                     t#          |                    d          pd                    }                     |          r|                    |           e|}nC# t0          $ r6}t2                              d+|           t          d*|          cY d}~S d}~ww xY wt9          |	          }|dk     s|t          |          k    rt          d,|-          S ||dz
           }|                    d          }|                    d          p|	}	n? j                             |	          }|r	|d         }n j                             |	          }|st          d.|	/          S 	  j                             |          }n3# t0          $ r&}t2                              d0||           Y d}~nd}~ww xY wj        t          j        k    r^                     |          }                     |          s3|s1|t          d1|	/          S t          d2|j        p|j        |	3          S  j         !                              }|j"        |k    rt          d4|	/          S  #                    |            j         $                    ||          }|st          d5          S  %                    |            &                    |            j         '                    |          p|	} j         (                    |          }|rt          d6 |D                       nd}|rd7| d8|dk    rd9nd d:nd}j        t          j        k    r!|rt          d;|j        pj        |<          S |st          d=|>          S |dk    rt          d?||@          S t          dA||@          S )Cu@   Handle /resume command — list or switch to a previous session.r   r  r  r  zgateway.resume.parse_errorrA   N--all--cross-roomrA  c              3  "   K   | ]
}|d v|V  dS )>   r  r  Nr   r   s     r'   r   zCGatewaySlashCommandsMixin._handle_resume_command.<locals>.<genexpr>
  s-      OOaA5N,N,N,N,N,N,NOOr)   r   <r  >[]"'r   r   
list[dict]c                     j         rj         j        nd } j                            | d          }d |D             d d         S )Nr  )rK   limitc                <    g | ]}|                     d           |S rC   r<  )r   r  s     r'   r   zcGatewaySlashCommandsMixin._handle_resume_command.<locals>._list_titled_sessions.<locals>.<listcomp>
  s'    :::!155>>:A:::r)   )r%   r`   rh   list_sessions_rich)user_sourcesessionsr$   rK   s     r'   _list_titled_sessionszOGatewaySlashCommandsMixin._handle_resume_command.<locals>._list_titled_sessions
  sR    39?L&///K'::+UW:XXH::x:::3B3??r)   idr7   z'gateway.resume.matrix_no_named_sessionsz gateway.resume.no_named_sessionszgateway.resume.list_headerr  )r  rD   u    — rv  (   z"gateway.resume.list_preview_suffixr  z!gateway.resume.list_item_numbered)r  rD   preview_partz#gateway.resume.list_footer_numberedr   z"Failed to list titled sessions: %szgateway.resume.list_failedz5Failed to list titled sessions for numeric resume: %szgateway.resume.out_of_range)r  zgateway.resume.not_foundr}  z0Failed to resolve resume continuation for %s: %sz'gateway.resume.matrix_blocked_no_originz(gateway.resume.matrix_blocked_other_room)r   rr  zgateway.resume.already_onzgateway.resume.switch_failedc                D    g | ]}|                     d           dk    |S r  r  r<  r2  s     r'   r   zDGatewaySlashCommandsMixin._handle_resume_command.<locals>.<listcomp>  ,    GGGqquuV}}/F/F/F/F/Fr)   r   z messager  r{  z(gateway.resume.matrix_cross_room_success)rD   r   msg_partzgateway.resume.resumed_no_countrC   zgateway.resume.resumed_one)rD   r   zgateway.resume.resumed_many)r   r  ))rh   ri   r  r   rK   rL   rf   rg   r   r   rk   r   r   r%   r   r  r'  r   r#   r,  r   rP  r  r   rX   ro   rp   isdigitrM  r  resolve_session_by_titleresolve_resume_session_idrO   re   r9   rN   switch_sessionr^   rU   r  r  ) r$   r*   r  r=   r  r  r   	allow_allallow_cross_roomrr  r  titledscopedr  r   r   r[  rD   rv  r	  r   r  r  	target_idsessiontarget_origincurrent_entryrw   r  	msg_countr  rK   s    `                              @r'   _handle_resume_commandz0GatewaySlashCommandsMixin._handle_resume_command
  s      	kBBBBBB00:h8i8ijjjj226::))++1133	>K))EE 	> 	> 	>1=========	>u$	)U2xxOO5OOOOOUUWW t99>>!W^^RCQ348s??Q348s??Q348s??":##%%D	@ 	@ 	@ 	@ 	@ 	@ 	@
  	@@..00?ho55i5F# - -!%!D!DStIZXZE[E[!\!\11&&AA -"MM!,,,#F A(/99)9 !JKKK?@@@7889'ss1=== | |FCgJE(/99i9!%!D!DStIZXZE[E[!\!\! X',$W$W63C3Uv~$W$WEeeIr223B37G_f#n1%ISZ#[#[#[#[lnLLL#FcY^my!z!z!z{{{{QDEEFFFyy''' @ @ @A1EEE5Q?????????@
 <<>> 	L@..00?ho55i5F# - -!%!D!DStIZXZE[E[!\!\11&&AA -"MM!,,,#F @ @ @TVWXXX5Q?????????@ IIEqyyECKK//6eDDDDEAI&F

4((I::g&&.$DD &22488G L#DM		 ,EEdKK	 	</d;;;;	[(BB9MMII 	[ 	[ 	[LLKYXYZZZZZZZZ	[ ?ho-- ??	JJM))&-@@ IY  (FTRRRR>&0IM4I    *@@HH#y000t<<<< 	))+666 &55k9MM	 	5344433K@@@ 	  ---  229==E $44Y??LSZCGGGGGGHHHYZ	OX`K	KK)q..33bKKKK^`?ho--2B-:%7!	     	E6eDDDD>>1iPPPP.e9MMMMs   .B 
B(B#B(#B(>B3M+ 2M+ D)M+ +
N+5+N& N+&N+BQ 
R+RRRU3 3
V#=VV#c                  K   ddl }| j        sddlm}  |t	          d                    S |j        }|                     |          }| j                            |          }| j        	                    |j
                  }|st	          d          S |                                                                }ddlm}	 |	                                }
|
                    d          }|                                j        dd	         }| d
| }|r|}n=| j                            |j
                  }|pd}| j                            |          }|j
        }	 | j                            ||j        r|j        j        ndt/          | j        t2                    r0| j                            di           pi                     d          ndd|i|           nC# t6          $ r6}t8                              d|           t	          d|          cY d}~S d}~ww xY w|D ]"}	 | j                            ||                    dd          |                    d          |                    d          p|                    d          |                    d          |                    d          |                    d          |                    d          |                    d          |                    d          |                    d          |                    d           !           # t6          $ r Y  w xY w	 | j                            ||           n# t6          $ r Y nw xY w| j                             ||          }|st	          d"          S | !                    |           | "                    |           tG          d# |D                       }|d$k    rd%nd&}t	          |||||'          S )(u  Handle /branch [name] — fork the current session into a new independent copy.

        Copies conversation history to a new session so the user can explore
        a different approach without losing the original.
        Inspired by Claude Code's /branch command.
        r   Nr  r  r  zgateway.branch.no_conversationr   z%Y%m%d_%H%M%S   r  branchgatewayr3  r  _branched_from)r9   rK   r3  model_configparent_session_idz#Failed to create branch session: %szgateway.branch.create_failedrA   r  r  ro  	tool_namerr  
tool_callstool_call_idfinish_reason	reasoningreasoning_contentreasoning_detailscodex_reasoning_itemscodex_message_items)r9   r  ro  r#  r$  r%  r&  r'  r(  r)  r*  r+  zgateway.branch.switch_failedc                D    g | ]}|                     d           dk    |S r  r<  r2  s     r'   r   zDGatewaySlashCommandsMixin._handle_branch_command.<locals>.<listcomp>}  r  r)   r   zgateway.branch.branched_onezgateway.branch.branched_many)rD   r   parentr{  )$uuidrh   ri   r  r   rK   rL   rO   re   r  r9   rf   rg   r   rQ  r  uuid4r  r  get_next_title_in_lineager  r%   r`   rR   r   r  r#   rX   ro   rB   append_messagerl   r  r^   rU   r   )r$   r*   _uuidr  rK   r=   r  r  branch_name_dtrQ  timestamp_str
short_uuidr;   branch_titlecurrent_titlebaser"  r   msgrw   r  r7  s                          r'   _handle_branch_commandz0GatewaySlashCommandsMixin._handle_branch_command   sg      	 	kBBBBBB00:h8i8ijjjj226:: *@@HH$44]5MNN 	75666,,..4466 	-,,,,,ggii_55[[]]&rr*
)88J88  	L&LL ,>>}?WXXM ,HD+EEdKKL)4
	>++)06Nv,,YMWX\XceiMjMjtt{w339r>>yIIIpt.0AB"3 ,      	> 	> 	>LL>BBB31=========	>
  	 	C //-00GGI..!ggk22Ecggfoo"ww|44!$!8!8"%''/":":!ggk22&)gg.A&B&B&)gg.A&B&B*-''2I*J*J(+0E(F(F 0        	..~|LLLL 	 	 	D	 &55k>RR	 	5344433K@@@ 	  ---GGGGGGHH	/8A~~++CaL	BSYghhhhsD   A>G 
H#+HHH"DL11
L?>L?M 
M,+M,c                h  K   ddl m} 	 t          j        |d           d{V }n# t          $ r d}Y nw xY w||j        st          d          S dg}|j        D ]?}|                                	                    d          r*|
                    |           @|j        r/|
                    d	           |
                    |j                   |j        rG|
                    d	           |
                    d
|j                    |
                    d           d                    |          S )u&  Handle /credits -- show Nous credit balance and the top-up handoff.

        Renders the balance block + identity line + a tappable top-up URL that
        opens the portal billing page with the modal open. The terminal does NOT
        confirm, poll, or track payment (billing phase 2a) — checkout happens in
        the browser and the next /credits shows the new balance. The tappable URL
        is the affordance: it works on every platform (button-capable or plain
        text like SMS/email). Fetched off the event loop; fail-open.
        r   )build_credits_viewTmarkdownNzgateway.credits.not_logged_inu   💳 **Nous credits**u   📈r7   zTop up: uP   Complete your top-up in the browser — credits will appear in /credits shortly.r   )agent.account_usager=  r   r   rX   	logged_inr   balance_linesr   r   r   identity_line	topup_urlr   )r$   r*   r=  viewr   lines         r'   _handle_credits_commandz1GatewaySlashCommandsMixin._handle_credits_command  sj      	;:::::	 *+=MMMMMMMMMDD 	 	 	DDD	 <t~<455534& 	 	D{{}}''// LL 	-LLLL+,,,> 	mLLLL4DN44555LLklllyys   ' 66c           
       K   ddl m} |j        }|                     |          }| j                            |          }|r||u r_t          | dd          }t          | dd          }|r;|9|5  |                    |          }|r|d         }ddd           n# 1 swxY w Y   |r||urt          |dd          nd}	|r||urt          |dd          nd}
|r||urt          |dd          nd}|	st          | d	d          }	 | j                            |          }| j	        
                    |j                  pi }n# t          $ r i }Y nw xY w|	p|                    d
          }	|
p|                    d          }
g }g }|	rJ	 t          j        t          |	|
|           d{V }n# t          $ r d}Y nw xY w|rt!          |d          }	 ddlm} t          j        |d           d{V }n# t          $ r g }Y nw xY w|rt'          |d          r|j        dk    rg }|                                }|rO|j        rHddlm} |                    t5          d ||                               |                    d           t          |dd          pd}t          |dd          pd}t          |dd          pd}t          |dd          pd}|                    t5          d                     |                    t5          d|j                             |                    t5          d|d                     |r&|                    t5          d|d                     |r&|                    t5          d |d                     |                    t5          d!|d                     |                    t5          d"|j        d                     |                    t5          d#|j                             	 dd$lm}m}  ||j         |||||%          t          |dd          t          |dd          &          }|j         I|j!        d'k    rd(nd}|                    t5          d)|tE          |j                   d*+                     n-|j!        d,k    r"|                    t5          d-                     n# t          $ r Y nw xY w|j#        }|j$        r_|j%        r tM          d.|j$        |j%        z  d.z            nd}|                    t5          d/|j$        d|j%        d|d01                     |j'        r)|                    t5          d2|j'                             |r*|                    d           |(                    |           |r*|                    d           |(                    |           d3)                    |          S | j                            |          }| j        *                    |j                  } | rdd4l+m,}! d5 | D             }" |!|"          }#t5          d6          t5          d7t[          |"                    t5          d8|#d          t5          d9          g}|r*|                    d           |(                    |           |r*|                    d           |(                    |           d3)                    |          S |s|rRt]          |          }$|r,|$r|$                    d           |$(                    |           d3)                    |$          S t5          d:          S );a:  Handle /usage command -- show token usage for the current session.

        Checks both _running_agents (mid-turn) and _agent_cache (between turns)
        so that rate limits, cost estimates, and detailed token breakdowns are
        available whenever the user asks, not only while the agent is running.
        r   r.  r0   NrQ   r  r  r  rh   billing_providerbilling_base_url)r  r  Tr>  )nous_credits_linessession_total_tokens)format_rate_limit_compactzgateway.usage.rate_limitsr   r7   session_input_tokenssession_output_tokenssession_cache_read_tokenssession_cache_write_tokenszgateway.usage.header_sessionzgateway.usage.label_modelr  z gateway.usage.label_input_tokensr   r   zgateway.usage.label_cache_readzgateway.usage.label_cache_writez!gateway.usage.label_output_tokenszgateway.usage.label_totalzgateway.usage.label_api_calls)CanonicalUsageestimate_usage_cost)r   r   r   r   )r  r  	estimated~zgateway.usage.label_costz.4f)rp  amountincludedz!gateway.usage.label_cost_includedd   zgateway.usage.label_contextz.0f)usedr  pctz gateway.usage.label_compressionsr   )estimate_messages_tokens_roughc                j    g | ]0}|                     d           dv |                     d          .|1S )r  >   r  r  ro  r<  r2  s     r'   r   zCGatewaySlashCommandsMixin._handle_usage_command.<locals>.<listcomp>0  sB    fff!!%%--;P*P*PUVUZUZ[dUeUe*PA*P*P*Pr)   z!gateway.usage.header_session_infozgateway.usage.label_messagesz%gateway.usage.label_estimated_contextz"gateway.usage.detailed_after_firstzgateway.usage.no_data)/rG  r/  rK   rL   r   r#   r"   rO   re   rh   r  r9   rX   r   r   r
   r   r@  rK  r]   session_api_callsget_rate_limit_statehas_dataagent.rate_limit_trackerrM  r   r   r3  rL  agent.usage_pricingrR  rS  
amount_usdr:  rK  r  r  r  r  compression_countr  r   r  r  r[  r   rq  )%r$   r*   r/  rK   r=   rV  rs   r  cachedr  r  r  _entry_for_billing	persistedaccount_linescredits_linesaccount_snapshotrK  r   rl_staterM  r   r   
cache_readcache_writerR  rS  cost_resultrp  r  rZ  r  r  r[  r  approxr  s%                                        r'   _handle_usage_commandz/GatewaySlashCommandsMixin._handle_usage_command  sb	      	877777226:: $((55 	*!888!$(;TBBKT>488F *v1  * *#ZZ44F * &q	* * * * * * * * * * * * * * * 8=oNeAeAe75*d333ko7<oNeAeAe75*d333ko5:muLc?c?c'%D111im 	EGD->>J%)%7%M%Mf%U%U" ,889K9VWW][]		   			D9==1C#D#DHD9==1C#D#DH $&#% 	\()0):'%#	* * * $ $ $ $ $ $    ( ( (#'   ( \ :;KVZ [ [ [	>>>>>>")"34FQU"V"V"VVVVVVVMM 	 	 	MMM	  @	$WU$:;; @	$@WZ[@[@[E 1133H !H- !NNNNNNQ:B[B[\dBeBefffgggR    #5*@!DDIL#E+BAFFK!M (CQGGL1J!%)EqIINQKLL9::;;;LL6ekJJJKKKLL=EXEXYYYZZZ [Q?*GXGXYYYZZZ ]Q@;HZHZ[[[\\\LL>FZFZ[[[\\\LL6A[>_>_```aaaLL:%BYZZZ[[[SSSSSSSS11K"N%1&3*4+6	   %UJ==$UJ==
 
 
 )5$/$6+$E$ESS2FLL#=fX]^i^tXuXuU{U{!|!|!|}}}} ':55LL#F!G!GHHH    *C% VUXUgnc#s58JJSPQQQmnQ<cF\C`C`knk}  iB  iB  KN  HT  HT  U  U  U  V  V  V$ aQAI^___``` ,R   ]+++ ,R   ]+++99U### *@@HH$44]5MNN 	$KKKKKKffwfffD33D99F5660D		BBB9FOOO677	E  ,R   ]+++ ,R   ]+++99U### 	$M 	$''E , %LL$$$]+++99U###()))s[   - BB B;D? ?EE#F* *F98F9"G3 3HHCS 
S&%S&c                  	
K   |                                                                 }t          j        dd|          }d
d|r|                                }d}|t          |          k     r||         dk    r`|dz   t          |          k     rJ	 t          ||dz                      
n*# t          $ r t          d||dz            	          cY S w xY w|d
z  }nm||         dk    r'|dz   t          |          k     r||dz            |d
z  }n:||         	                                rt          ||                   
|dz  }n|dz  }|t          |          k     	 ddl
m	 ddlm t          j                    }	
fd}|                    d|           d{V S # t"          $ r8}t$                              d|d           t          d|          cY d}~S d}~ww xY w)z>Handle /insights command -- show usage insights and analytics.z'[\u2012\u2013\u2014\u2015](days|source)z--\1   Nr   z--daysr   zgateway.insights.invalid_daysr   r   z--sourcer?   )InsightsEnginec                                  }  |           }|                               }|                    |          }|                                  |S )N)daysrK   )generateformat_gatewayr   )dbenginereportr  rr  r@   rt  rK   s       r'   _run_insightszIGatewaySlashCommandsMixin._handle_insights_command.<locals>._run_insightsm  sW    Y[['++d6BB..v66


r)   zInsights command error: %sTrE   zgateway.insights.errorrA   )rf   rg   r   subr   r   rM  rk   r   r  ri   r@   agent.insightsrr  r   r  r  rX   ro   rB   )r$   r*   r  r  r   r  rz  r   rr  r@   rt  rK   s           @@@@r'   _handle_insights_commandz2GatewaySlashCommandsMixin._handle_insights_commandI  sj     %%''--// v@'4PP  	JJLLEAc%jj..8x''AECJJ,>,>V"5Q<00% V V V !@aRSeUUUUUUVFAA1X++AE

0B0B"1q5\FFAA1X%%'' uQx==DFAAFA c%jj.. 	8......555555+--D        --dMBBBBBBBBB 	8 	8 	8LL5q4LHHH-Q777777777	8s1   B/ /$CC AF# #
G%--G G% G%c                   K   j         }                     |                                           }t          |t                    r|                    d          nd}d}t          |t                    r#t          |                    dd                    }|s                                d{V S d fd	}t          d
          } 	                    dd||           d{V S )u  Handle /reload-mcp — reconnect MCP servers and rebuild the cached agent.

        Reloading MCP tools invalidates the provider prompt cache for the
        active session (tool schemas are baked into the system prompt).  The
        next message re-sends full input tokens, which is expensive on
        long-context or high-reasoning models.

        To surface that cost, the command routes through the slash-confirm
        primitive: users get an Approve Once / Always Approve / Cancel
        prompt before the reload actually runs.  "Always Approve" persists
        ``approvals.mcp_reload_confirm: false`` so the prompt is silenced
        for subsequent reloads in any session.

        Users can also skip the confirm by flipping the config key directly.
        	approvalsNTmcp_reload_confirmrM  r   r   r  c                p  K   | dk    rt          d          S | dk    ra	 ddlm}  |dd           t                              d           n2# t
          $ r%}t                              d	|           Y d }~nd }~ww xY w                               d {V }| dk    r| d
t          d          z   S |S )NrO  zgateway.reload_mcp.cancelledalwaysr   )save_config_valuezapprovals.mcp_reload_confirmFz7User opted out of /reload-mcp confirmation (session=%s)z.Failed to persist mcp_reload_confirm=false: %srJ   z"gateway.reload_mcp.always_followup)r   clir  ro   rh  rX   r   _execute_mcp_reload)rM  r  r   r  r*   r$   r=   s       r'   _on_confirmzIGatewaySlashCommandsMixin._handle_reload_mcp_command.<locals>._on_confirm  s     !!7888!!Z555555%%&DeLLLKKQ#    ! Z Z ZNN#SUXYYYYYYYYZ  33E::::::::F!! +O)P)PPPMs   -A 
A=A88A=z!gateway.reload_mcp.confirm_promptz
reload-mcpz/reload-mcprQ  )rM  r   r   r  )
rK   rL   _read_user_configrR   r  r#   r)  r  r   r[  )	r$   r*   rK   r$  r  confirm_requiredr  prompt_messager=   s	   ``      @r'   _handle_reload_mcp_commandz4GatewaySlashCommandsMixin._handle_reload_mcp_commandz  sD       226:: ,,..4>{D4Q4Q[KOOK000W[	i&& 	O#IMM2F$M$MNN 	911%888888888	 	 	 	 	 	 	 	( >??00 " 1 
 
 
 
 
 
 
 
 	
r)   c           
       K   t          j                    }	 ddlm} |                    d|           d{V }|                    dg           }|                    dg           }|                    dd          }t          | j                                                  D ]}t          |dd          }	t          |	          s#	  |	            }
t          j        |
          r|
 d{V  K# t          $ r5}t                              dt          |d	|          |           Y d}~d}~ww xY wt!          d
          g}|s]|s[|                    t!          d                     |                    t!          d|                     d                    |          S dd}|rE|                    t!          d                     |D ] }|                     ||                     !|rE|                    t!          d                     |D ] }|                     ||                     !|                    t!          d|                     dg}|rM|                    d           |                    d           |D ] }|                     ||                     !|rM|                    d           |                    d           |D ] }|                     ||                     !|                    d           |                    d           d                    |          }|                     |j                  }t+          | d          si | _        |r
|| j        |<   d                    |          S # t          $ r6}t                              d|           t!          d|          cY d}~S d}~ww xY w) u  Handle /reload-skills — rescan skills dir, queue a note for next turn.

        Skills don't need to be in the system prompt for the model to use
        them (they're invoked via ``/skill-name``, ``skills_list``, or
        ``skill_view`` at runtime), so this does NOT clear the prompt cache
        — prefix caching stays intact.

        If any skills were added or removed, a one-shot note is queued on
        ``self._pending_skills_reload_notes[session_key]``. The gateway
        prepends it to the NEXT user message in this session (see the
        consumer at ~L11025 in ``_run_agent_turn``), then clears it. Nothing
        is written to the session transcript out-of-band, so message
        alternation is preserved.
        r   )reload_skillsNaddedr  r  refresh_skill_groupz)Adapter %s refresh_skill_group raised: %srr  zgateway.reload_skills.headerzgateway.reload_skills.no_newzgateway.reload_skills.totalr   r   itemr  r   r   c                    |                      dd          }|                      dd          }|rt          d||          S t          d|          S )Nrr  r7   r  z$gateway.reload_skills.item_with_desc)rr  r  z"gateway.reload_skills.item_no_descr}  )r#   r   )r  nmr  s      r'   	_fmt_linezJGatewaySlashCommandsMixin._handle_reload_skills_command.<locals>._fmt_line  s\    XXfb))xxr22 YC"SWXXXX=BGGGGr)   z"gateway.reload_skills.added_headerz$gateway.reload_skills.removed_headerz[USER INITIATED SKILLS RELOAD:r7   zAdded Skills:zRemoved Skills:z,Use skills_list to see the updated catalog.]_pending_skills_reload_noteszSkills reload failed: %szgateway.reload_skills.failedrA   )r  r  r   r   )r   r  r  r  r  r#   rq  r   r#  r"   r"  inspectisawaitablerX   ro   r   r   r   r   rL   rK   r]   r  )r$   r*   r  r  r  r  r  r  r&   refreshmayber   r   r  r  sectionsr  r=   r   s                      r'   _handle_reload_skills_commandz7GatewaySlashCommandsMixin._handle_reload_skills_command  sX      '))R	>:::::://mDDDDDDDDFJJw++EjjB//GJJw**E   4 4 6 677  !'+@$GG(( #GIIE*511 $#    NNC993        5667E ( (Q=>>???Q<EJJJKKKyy'''H H H H  2QCDDEEE! 2 2DLL41111 2QEFFGGG# 2 2DLL41111LL8FFFGGG 99H 5###000! 5 5DOOIIdOO4444 5### 1222# 5 5DOOIIdOO4444OOBOOJKKK99X&&D66u|DDK4!?@@ 7461 FAE1+>99U### 	> 	> 	>NN5q99931=========	>sP   B-N &C,+N ,
D+6+D&!N &D++A1N G'N 
O+O :O Oc           
       K   	 ddl m}m} n7# t          $ r*}t                              d|           d| cY d}~S d}~ww xY w |            }|sd |             dS dt          |           d	d
g}|D ]}t          |                    dg                     }|                    d          pd| d}	|                    d|d          d|	 d| d           |                    dg           D ]}
|                    d|
            |                    d
           |                    d           d	                    |          S )u  Handle /bundles — list installed skill bundles.

        Mirrors the CLI ``/bundles`` handler. Returns a single text
        message suitable for any gateway adapter; bundles are loaded by
        invoking the bundle's own ``/<slug>`` command, not by this one.
        r   )list_bundles_bundles_dirzBundles command unavailable: %szBundles subsystem unavailable: NzNo skill bundles installed.
Create one on the host with:
  `hermes bundles create <name> --skill <s1> --skill <s2>`
Directory: `r@  z**Skill Bundles** (z installed):r7   r_  r  zLoad z skillsu   • `/r-  r  z _(z	 skills)_u       · z6Invoke a bundle with `/<slug>` to load all its skills.r   )
agent.skill_bundlesr  r  rX   ro   r   r   r#   r   r   )r$   r*   r  r  r   bundlesr   rh  skill_countr  r  s              r'   _handle_bundles_commandz1GatewaySlashCommandsMixin._handle_bundles_command  s     	;FFFFFFFFF 	; 	; 	;NN<cBBB:S::::::::	; ,.. 	1  ,|~~1 1 1 Bs7||AAA2F 	, 	,Ddhhx4455K88M**J.Jk.J.J.JDLLLfLLTLLkLLL   XXh++ , ,]q]]++++,RMNNNyys    
A<AAc                <  K   |j         }|                     |          }ddlm}m}  ||          sA|| j        v r)| j                            |           t          d          S t          d          S |                                	                                
                                                                }d|v }d |D             }t          d |D                       rd}	nt          d	 |D                       rd
}	nd}	 |||	|          }
|
st          d          S | j                            |j                  }|r|                    |j                   t$                              d|
|	           |
dk    rdnd}t          d|	 d| |
          S )u  Handle /approve command — unblock waiting agent thread(s).

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

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

        Usage:
            /approve              — approve oldest pending command once
            /approve all          — approve ALL pending commands at once
            /approve session      — approve oldest + remember for session
            /approve all session  — approve all + remember for session
            /approve always       — approve oldest + remember permanently
            /approve all always   — approve all + remember permanently
        r   resolve_gateway_approvalhas_blocking_approvalzgateway.approval_expiredzgateway.approve.no_pendingr  c                    g | ]
}|d k    |S )r  r   r   r  s     r'   r   zEGatewaySlashCommandsMixin._handle_approve_command.<locals>.<listcomp>d  s    3331U

Q


r)   c              3     K   | ]}|d v V  	dS )>   r  	permanentpermanentlyNr   r  s     r'   r   zDGatewaySlashCommandsMixin._handle_approve_command.<locals>.<genexpr>f  s(      NNqq::NNNNNNr)   r  c              3     K   | ]}|d v V  	dS )>   sesr  Nr   r  s     r'   r   zDGatewaySlashCommandsMixin._handle_approve_command.<locals>.<genexpr>h  s(      <<Q((<<<<<<r)   r  onceresolve_allz7User approved %d dangerous command(s) via /approve (%s)r   pluralsingularzgateway.approve.r  r   )rK   rL   rw  r  r  _pending_approvalsrV   r   rf   rg   r   r   anyr   r#   r%   resume_typing_for_chatr   ro   rh  )r$   r*   rK   r=   r  r  r  r  	remainingrM  r   _adapterr  s                r'   _handle_approve_commandz1GatewaySlashCommandsMixin._handle_approve_command@  s     ( 226::	
 	
 	
 	
 	
 	
 	
 	
 %$[11 	3d555'++K88834441222 %%''--//5577==??tm33333	NNINNNNN 	FF<<)<<<<< 	FFF((f+VVV 	31222 =$$V_55 	<++FN;;;MuV\]]]"QYYJ5F55V55UCCCCr)   c                  K   |j         }|                     |          }ddlm}m}  ||          sA|| j        v r)| j                            |           t          d          S t          d          S |                                	                                
                                }d|v } ||d|          }|st          d          S | j                            |j                  }	|	r|	                    |j                   t                               d|           |d	k    rt          d
|          S t          d          S )u  Handle /deny command — reject pending dangerous command(s).

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

        ``/deny`` denies the oldest; ``/deny all`` denies everything.
        r   r  zgateway.deny.stalezgateway.deny.no_pendingr  denyr  z-User denied %d dangerous command(s) via /denyr   zgateway.deny.denied_pluralr   zgateway.deny.denied_singular)rK   rL   rw  r  r  r  rV   r   rf   rg   r   r   r#   r%   r  r   ro   rh  )
r$   r*   rK   r=   r  r  r  r  r   r  s
             r'   _handle_deny_commandz.GatewaySlashCommandsMixin._handle_deny_commandz  sz      226::	
 	
 	
 	
 	
 	
 	
 	
 %$[11 	0d555'++K888-....///%%''--//5577tm((f+VVV 	0./// =$$V_55 	<++FN;;;CUKKK1991????/000r)   c                   	
K   ddl }ddlmm	m
mmm  |j                    }	
fd}|	                    d|           d{V S )u6  Handle /debug — upload debug report (summary only) and return paste URLs.

        Gateway uploads ONLY the summary report (system info + log tails),
        NOT full log files, to protect conversation privacy.  Users who need
        full log uploads should use ``hermes debug share`` from the CLI.
        r   N)_capture_dumpcollect_debug_reportupload_to_pastebin_schedule_auto_delete_GATEWAY_PRIVACY_NOTICE!_best_effort_sweep_expired_pastesc                     	              
            }  d|           }i }	  |          |d<   n(# t           $ r}t          d|          cY d }~S d }~ww xY w t          |                                                     dt          d          dg}t	          d |D                       }|                                D ]$\  }}|                    d	|d
| d|            %|                    d           |                    t          d                     |                    t          d                     |                    t          d                     d                    |          S )Nr  )	log_lines	dump_textReportzgateway.debug.upload_failedrA   r7   zgateway.debug.headerc              3  4   K   | ]}t          |          V  d S r+  )r   )r   r%  s     r'   r   z_GatewaySlashCommandsMixin._handle_debug_command.<locals>._collect_and_upload.<locals>.<genexpr>  s(      33c!ff333333r)   r@  r  z`  zgateway.debug.auto_deletezgateway.debug.full_logs_hintzgateway.debug.share_hintr   )rX   r   rq  r#  rL  rJ  r   r   )r  ry  urlsr   r   label_widthr  urlr  r  r  r  r  r  s           r'   _collect_and_uploadzLGatewaySlashCommandsMixin._handle_debug_command.<locals>._collect_and_upload  s   --///%I))C9MMMFDC!3!3F!;!;X C C C6cBBBBBBBBBC "!$t{{}}"5"5666,b!4J2K2KRPE33d33333K"jjll A A
s??????#??@@@@LLLL677888LL9::;;;LL56677799U###s   5 
AAAA)
r   hermes_cli.debugr  r  r  r  r  r  r  r  )r$   r*   r   r  r  r  r  r  r  r  r  s        @@@@@@r'   _handle_debug_commandz/GatewaySlashCommandsMixin._handle_debug_command  s       		
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 (w'))	$ 	$ 	$ 	$ 	$ 	$ 	$ 	$ 	$ 	$2 ))$0CDDDDDDDDDr)   c           
       K   ddl m}m} ddl}ddl}ddl}ddlm} ddlm}m	}	 |j
        j        }
| j        }|
|vrY	 ddlm} |                    |
j                  }|r|j        st%          d          S n# t&          $ r t%          d          cY S w xY w |            rd |	d	           S t)          t*                    j        j                                        }|d
z  }|                                st%          d          S  |            }|st%          d          S |dz  }|dz  }|dz  }|                     |j
                  }|j
        j        j        |j
        j        |j
        j        |j
        j        | |j                                                    d}|j
        j        r|j
        j        |d<   |j         r
|j         |d<   |!                    d          }|"                    |#                    |                     |$                    |           |%                    d           	 tL          j        dk    rddl'}ddl(m)} |*                    d          +                                } |j,        tL          j-        d|t]          |          t]          |          g|ddf|j/        |j/        d |             nd0                    d |D                       }d| d tc          j2        t]          |                     d!tc          j2        t]          |                     }|3                    d"          }|r(|,                    |d#d|g|j/        |j/        d$           n&|,                    d#d|g|j/        |j/        d$           nT# t&          $ rG}|%                    d           |%                    d           t%          d%|&          cY d}~S d}~ww xY w| 4                                 t%          d'          S )(us  Handle /update command — update Hermes Agent to the latest version.

        Spawns ``hermes update`` in a detached session (via ``setsid``) so it
        survives the gateway restart that ``hermes update`` may trigger. Marker
        files are written so either the current gateway process or the next one
        can notify the user when the update finishes.
        r   )r  _resolve_hermes_binNr   )
is_managedformat_managed_message)platform_registryz%gateway.update.platform_not_messagingu   ✗ zupdate Hermes Agentz.gitzgateway.update.not_git_repoz#gateway.update.hermes_cmd_not_foundz.update_pending.jsonz.update_output.txtz.update_exit_code)r%   r   r   r<   r=   r   r   r  z.tmpT)
missing_okwin32)windows_detach_popen_kwargsaW  
                    import os, subprocess, sys
                    output_path = sys.argv[1]
                    exit_code_path = sys.argv[2]
                    cmd = sys.argv[3:]
                    env = dict(os.environ)
                    env["PYTHONUNBUFFERED"] = "1"
                    with open(output_path, "wb") as f:
                        proc = subprocess.Popen(cmd, stdout=f, stderr=subprocess.STDOUT, env=env)
                        rc = proc.wait(timeout=3600)
                    with open(exit_code_path, "w") as f:
                        f.write(str(rc))
                    z-cupdatez	--gateway)stdoutstderrrA  c              3  >   K   | ]}t          j        |          V  d S r+  )r   quote)r   parts     r'   r   zCGatewaySlashCommandsMixin._handle_update_command.<locals>.<genexpr>C  s,      )S)S%+d*;*;)S)S)S)S)S)Sr)   zPYTHONUNBUFFERED=1 z update --gateway > z" 2>&1; rc=$?; printf '%s' "$rc" > setsidbash)r  r  start_new_sessionzgateway.update.start_failedrA   zgateway.update.starting)5rG  r  r  jsonshutil
subprocessr   r=  r  r  rK   r%   _UPDATE_ALLOWED_PLATFORMSgateway.platform_registryr  r#   r`   allow_update_commandr   rX   r   __file__r-  resolver  rL   r   r   r<   rQ  	isoformatr   r  with_suffix
write_textdumpsr  unlinksystextwraphermes_cli._subprocess_compatr  dedentrg   Popen
executabler   DEVNULLr   r   r  which#_schedule_update_notification_watch)r$   r*   r  r  r  r  r  r   r  r  r%   _allowedr  r%  project_rootgit_dir
hermes_cmdpending_pathoutput_pathexit_code_pathr=   pending_tmp_pendingr  r  helperhermes_cmd_str
update_cmd
setsid_binr   s                                 r'   _handle_update_commandz0GatewaySlashCommandsMixin._handle_update_command  sB      	BAAAAAAA%%%%%%HHHHHHHH <(18##BGGGGGG)--hn== FE$> FDEEEF B B B@AAAAAB :<< 	JI001FGGIIIH~~,3;;=='~~ 	42333((**
 	<:;;;#&<<"%99%(;;225<@@-3|+/|+&%1133
 
 <! 	:#(<#9GK  	5$)$4GL!#//77

7 3 3444\***...4?	=|w&&UUUUUU "  %''  !
 fK((#n*=*= $ &. 0;	 &-%-	 	 2133	 	 	 	 "%)S)S
)S)S)S!S!SW. W W+c+&6&677W W 5:KN@S@S4T4TW W  $\\(33
 $$#VT:>)1)1*.	 %     $$z2)1)1*.	 %     	= 	= 	=4000!!T!2222!<<<<<<<<<	=
 	00222*+++s0   7A6 6BB3E!N 
O&<O!O&!O&NrT  )r*   r   r   r+   )r*   r   r   r   )r=   r   r   r   )r9   r   r   r  )r(  r   r   r  r   r)  )r*   r   r   r  )r*   r  r   r   )r7   )r*   r   r  r   r   r   )6__name__
__module____qualname____doc__r(   r   r   r   r   r  staticmethodr  r'  r,  r_  rm  r  r  r  r  r  re  rq  r  r  r  r  r  r  r  r  r  rB  r[  rg  rr  rx  r  r  r  r  r  r  r;  rG  ro  r}  r  r  r  r  r  r  r   r   r)   r'   r   r   0   s       >>] ] ] ]e6 e6 e6 e6N       1
 1
 1
 1
f`7 `7 `7 `7DM  M  M  M ^ " " " \"    
 
 
 \
Y  Y  Y  Y v=+ =+ =+ =+~[
 [
 [
 [
z^? ^? ^? ^?@- - - -
 
 
 
46
 6
 6
 6
pQ& Q& Q& Q&f+, +, +, +,ZDP DP DP DPL"7 "7 "7 "7HKN KN KN KNZ12 12 12 12f/
 /
 /
 /
b$N $N $N $NLOR OR OR ORb:K :K :K :Kx#Q #Q #Q #QJvA vA vA vAp( ( ( (T8 8 8 8t4; 4; 4; 4;l= = = ="=] =] =] =]~TG TG TG TGlh9 h9 h9 h9TW@ W@ W@ W@ W@r/R /R /R /RbWN WN WN WNr_i _i _i _iB           Dd* d* d* d*L/8 /8 /8 /8b=
 =
 =
 =
~b> b> b> b>H!  !  !  ! F8D 8D 8D 8Dt$1 $1 $1 $1L*E *E *E *EXX, X, X, X, X, X,r)   r   ).r  
__future__r   r   r  r  r  loggingr	  r   r   r  rI  r   pathlibr   typingr   r   r	   r@  r
   r   
agent.i18nr   r  r   r   r   gateway.platforms.baser   r   r   gateway.sessionr   r   r=  r   utilsr   r   r   r   	getLoggerro   r   r   r)   r'   <module>r     s    # " " " " "         				 				  



              ' ' ' ' ' ' ' ' ' ' O O O O O O O O       @ @ @ @ @ @ @ @ @ @ L L L L L L L L L L < < < < < < < < % % % % % %            
	=	)	)t8, t8, t8, t8, t8, t8, t8, t8, t8, t8,r)   