
    JjX                       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	m	Z	 ddl
mZ ddlmZ ddlmZ ddlmZ dd	lmZmZ dd
lmZmZmZmZ  G d d          ZdS )u  Slash-command handlers for the interactive CLI (god-file decomposition Phase 4).

This module hosts the ``_handle_*_command`` slash-command handlers lifted out of
``cli.py``'s ``HermesCLI`` class. ``HermesCLI`` inherits ``CLICommandsMixin`` so
every ``self.<handler>`` call resolves unchanged via the MRO — behavior-neutral.

Import discipline (mirrors gateway/slash_commands.py, PR #41886):
  * Neutral, non-cyclic deps are imported at module top-level below.
  * cli.py-internal symbols (the ``_cprint``/``_ACCENT``/``save_config_value``…
    module-level helpers and constants) are imported LAZILY inside each handler
    via ``from cli import ...`` — that resolves at call time when ``cli`` is fully
    loaded, so the mixin module never imports ``cli`` at top level (no cycle).
    )annotationsN)datetime)urlparse)box)escape)Panel)display_hermes_home	is_termux)DEFAULT_BROWSER_CDP_URLis_browser_debug_readylaunch_chrome_debugmanual_chrome_debug_commandc                  f   e Zd ZdZd:dZd:dZd Zd Zd;dZd Z	d;dZ
d<dZd=dZd Zd>dZd;dZd;dZd;dZd=dZd=dZd=dZd=dZd=dZd=dZd=dZd=dZd=dZd=d Zd=d!Zd?d$Zd=d%Zd@d&Zd=d'Z d@d(Z!dAd*Z"d@d+Z#d=d,Z$dBdCd/Z%d;d0Z&d;d1Z'd;d2Z(d=d3Z)d=d4Z*d=d5Z+dBd<d6Z,dDd7Z-d:d8Z.d9S )ECLICommandsMixinzMixin holding the interactive-CLI slash-command handlers.

    All methods use only ``self`` state plus the imports above and per-method
    lazy ``from cli import ...`` lines, so they compose cleanly onto
    ``HermesCLI`` via the MRO.
    commandstrc           	        ddl m} t          | d          r| j        st	          d           dS | j        j        }|j        s/t	          d           t	          d           t	          d           dS t          j        d	t          j	                              }|
                                }t          |          d
k    r
|d
d         ng }|s0|                    |          }t	           |||                     dS |d                                         dk    rt          |          dk     rt	          d           dS |                    |          }|st	          d|            dS |                     |d
         |          }|sdS |                    ||          }	|	d         r|	                    dd          }
|	                    dd          }|
s|st	          d           n|
rt	          d|
            |r|                                }t          |          dk    rNt	          d                    |dd                              t	          dt          |          dz
   d           n+t	          d|            nt	          d|	d                     dS |                    |          }|st	          d|            dS |                     |d         |          }|sdS t          |          d
k    r|d
         nd}|                    |||          }	|	d         r|r%t	          d| d|	d          d|	d                     n!t	          d|	d          d|	d                     t	          d            | j        r'|                     d!"           t	          d#           dS dS t	          d|	d                     dS )$u  Handle /rollback — list, diff, or restore filesystem checkpoints.

        Syntax:
            /rollback                 — list checkpoints
            /rollback <N>             — restore checkpoint N (also undoes last chat turn)
            /rollback diff <N>        — preview changes since checkpoint N
            /rollback <N> <file>      — restore a single file from checkpoint N
        r   )format_checkpoint_listagentz  No active agent session.Nz  Checkpoints are not enabled.z#  Enable with: hermes --checkpointsz3  Or in config.yaml: checkpoints: { enabled: true }TERMINAL_CWD   diff   z  Usage: /rollback diff <N>z  No checkpoints found for successstat z#  No changes since this checkpoint.
P   z
  ... (z more lines, showing first 80)u     ❌ error)	file_pathu     ✅ Restored z from checkpoint restored_to: reasonu     ✅ Restored to checkpoint z2  A pre-rollback snapshot was saved automatically.F)prefillz0  Chat turn undone to match restored file state.)tools.checkpoint_managerr   hasattrr   print_checkpoint_mgrenabledosgetenvgetcwdsplitlenlist_checkpointslower_resolve_checkpoint_refr   get
splitlinesjoinrestoreconversation_history	undo_last)selfr   r   mgrcwdpartsargscheckpointstarget_hashresultr   r   
diff_linesr    s                 C/home/rurouni/.hermes/hermes-agent/hermes_cli/cli_commands_mixin.py_handle_rollback_commandz)CLICommandsMixin._handle_rollback_command/   sL    	DCCCCCtW%% 	TZ 	.///Fj({ 	23337888GHHHFi	44JJNNuQRRyy 	..s33K((c::;;;F 7==??f$$4yy1}}3444..s33K 9C99:::66tAwLLK XXc;//Fi  2zz&"--zz&"-- /D /?@@@@ +k4kk*** /%)__%6%6
z??R//!$))JssO"<"<===!"bc*oo.B"b"b"bcccc!+t++...0vg00111F **3// 	555666F2247KHH 	F  #4yy1}}DGG$	S+CC) 	. co	ooF=DYoo]cdl]mooppppaf]6KaavV^O_aabbbFGGG ( Ju---HIIIIIJ J ,6'?,,-----    c                T   ddl m}m}m}m} ddlm} |                                }t          |          dk    r|d         	                                nd}|dv r0 |            }	|	s t          d           t          d           d	S t          d
 |             d           t          dddddddddddddd 
           t          dd dd dd dd dd 
           t          |	d          D ]\  }
}|                    dd          }|dk     r| d}n|dk     r
|dz  d d!}n|dz  dz  d"d#}|                    d$          pd%}t          d|
d&d|d'         dd|                    d(d          dd|dd| 
           d	S |d)k    ret          |          d*k    rd                    |d*d	                   nd	} ||+          }|rt          d,|            d	S t          d-           d	S |d.v rt          |          d/k     r=t          d0            |d1          }	|	rt          d2|	d         d'                     d	S |d*         }	 t          |          } |            }	d|cxk    rt          |	          k    rn n|	|dz
           d'         }n"t          d3t          |	           d4           d	S n# t          $ r Y nw xY w ||          r#t          d5|            t          d6           d	S t          d7|            d	S |d8k    rpd9}t          |          d*k    r7	 t          |d*                   }n # t          $ r t          d:           Y d	S w xY w ||;          }t          d<| d=| d>           d	S t          d?|            t          d@           d	S )Auu  Handle /snapshot — lightweight state snapshots for Hermes config/state.

        Syntax:
            /snapshot                  — list recent snapshots
            /snapshot create [label]   — create a snapshot
            /snapshot restore <id>     — restore state from snapshot
            /snapshot prune [N]        — prune to N snapshots (default 20)
        r   )create_quick_snapshotlist_quick_snapshotsrestore_quick_snapshotprune_quick_snapshotsr	   r   list>   lsrJ   z  No state snapshots yet.z&  Create one: /snapshot create [label]Nz  State snapshots (z/state-snapshots/):
  #z>3IDz<35 Filesz>5Sizez>10Labelu	   ───ui   ───────────────────────────────────u   ─────u   ──────────u<   ────────────────────
total_sizei   z Bi   z.0fz KBz.1fz MBlabelr   3id
file_countcreater   )rT   z  Snapshot created: z#  No state files found to snapshot.>   rewindr5      z(  Usage: /snapshot restore <snapshot-id>limitz  Most recent: z!  Invalid snapshot number. Use 1-.z  Restored state from: z:  Restart recommended for state.db changes to take effect.z  Snapshot not found: prune   z%  Usage: /snapshot prune [keep-count])keepz	  Pruned z old snapshot(s) (keeping ).z  Unknown subcommand: z?  Usage: /snapshot [list|create [label]|restore <id>|prune [N]])hermes_cli.backuprE   rF   rG   rH   hermes_constantsr	   r-   r.   r0   r'   	enumerater2   r4   int
ValueError)r8   r   rE   rF   rG   rH   r	   r;   subcmdsnapsissizesize_strrT   snap_ididxr`   deleteds                      rA   _handle_snapshot_commandz)CLICommandsMixin._handle_snapshot_command   s/   	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	988888%(ZZ!^^q!!!^##((**E 1222>???T(;(;(=(=TTTUUUOsOOOOOOGOOOOOOgOOPPPLwLL(LLWLLxLL(LLMMM!%++ 	d 	d1uu\1--$;;"&{{{HHK''"&+6666HH"&+"4====Hg,"b1bbb!D'bbblA0F0FbbbHbbb[`bbcccc	d 	d x+.u::>>CHHU122Y'''tE++%888G =6W6677777;<<<<<,,,5zzA~~@AAA,,1555 ><E!HTN<<===AhG	'll,,..))))s5zz)))))#C!GnT2GGKc%jjKKKLLLF     %%g.. :999:::RSSSSS8w8899999wD5zzA~~uQx==DD!   ABBBFF ,+666GIgIIIIIJJJJJ 3633444STTTTTs%   A(J? ?
KK-M M M c                   ddl m} |                                }d |D             }	 ddlm}m}  |            }n# t          $ r d}d}Y nw xY w|s|st          d           dS |rGt          dt          |           d           |	                                }t          d	| d
           |r#|# |d          }t          d| d           dS dS dS )u  Handle /stop — kill all running background processes and
        background (async) delegations.

        Inspired by OpenAI Codex's separation of interrupt (stop current turn)
        from /stop (clean up background processes). See openai/codex#14602.
        r   )process_registryc                D    g | ]}|                     d           dk    |S statusrunningr2   .0ps     rA   
<listcomp>z9CLICommandsMixin._handle_stop_command.<locals>.<listcomp>   ,    HHH155??i+G+G1+G+G+GrC   )active_countinterrupt_allNz"  No running background processes.z  Stopping z background process(es)...u     ✅ Stopped z process(es).z/stopr#   u     ✅ Interrupted z background delegation(s).)
tools.process_registryrr   list_sessionstools.async_delegationr}   r~   	Exceptionr'   r.   kill_all)	r8   rr   	processesrv   r}   r~   n_asynckilledstoppeds	            rA   _handle_stop_commandz%CLICommandsMixin._handle_stop_command   sW    	<;;;;;$2244	HHiHHH	!JJJJJJJJ"lnnGG 	! 	! 	!G MMM	!  	w 	6777F 	:HGHHHIII%..00F86888999 	L}0#m7333GJwJJJKKKKK	L 	L00s   ; AAc           
     `   ddl m} ddlm}m} |                                }d |D             }d |D             } |dt          |                      |D ]g}|                    dd          d	d
         } ||                    dd                    }	 |d|                    dd           d|	 d|            h|r |dt          |                      	 ddlm	}
  |
            }n# t          $ r g }Y nw xY wd |D             }|r| |dt          |           d           |D ]]}|                    d          pdd	d         } |d|                    dd           d|                    dd           d|            ^t          | dd          } |d|rdnd            d	S )u>   Handle /agents — show background processes and agent status.r   _cprint)format_uptime_shortrr   c                D    g | ]}|                     d           dk    |S rt   rw   rx   s     rA   r{   z;CLICommandsMixin._handle_agents_command.<locals>.<listcomp>  r|   rC   c                D    g | ]}|                     d           dk    |S rt   rw   rx   s     rA   r{   z;CLICommandsMixin._handle_agents_command.<locals>.<listcomp>  s,    III!AEE(OOy,H,HA,H,H,HrC   z  Running processes: r   r   Nr   uptime_seconds    
session_id?u    · z  Recently finished: )list_async_delegationsc                D    g | ]}|                     d           dk    |S rt   rw   )ry   ds     rA   r{   z;CLICommandsMixin._handle_agents_command.<locals>.<listcomp>  s,    LLL1quuX)/K/KQ/K/K/KrC   z  Background delegations: z runninggoal<   delegation_idru   _agent_runningFz	  Agent: rv   idle)clir   r   r   rr   r   r.   r2   r   r   r   getattr)r8   r   r   rr   r   rv   finishedrz   cmdupr   delegations	running_dr   r   agent_runnings                   rA   _handle_agents_commandz'CLICommandsMixin._handle_agents_command  s   PPPPPPPP$2244	HHiHHHIIyIII6G66777 	H 	HA%%	2&&ss+C$$QUU+;Q%?%?@@BGF155s33FFFFFFGGGG 	=G;CMM;;<<<	EEEEEE0022KK 	 	 	KKK	LLLLL	 	GIYIIIJJJ   f+SbS18155#66 8 8uuXs++8 8158 8   
  &6>>DBIIFDDEEEEEs   C/ /C>=C>cmd_originalreturnNonec                
   ddl }ddl}ddl}ddlm} ddlm} ddlm} |	                    dd          } ||           |
                    dd	          }		 |                    t          |	          d	k    r|
                    |	d	                   ng           }
n# t          $ r Y dS w xY wt          |
d
d          dv }	 |r|
                    |
           dS d|
_        |                                } ||          5  |
                    |
           ddd           n# 1 swxY w Y    ||                                                    d                     dS # t(          $ r} |d|            Y d}~dS d}~ww xY w)ur  Handle /journey — the learning timeline (see `hermes journey`).

        The read-only views (default + ``list``) render Rich color, which
        patch_stdout would swallow as raw escapes; capture with forced ANSI and
        re-emit through ``_cprint``. ``delete``/``edit`` are interactive
        (confirm prompt / ``$EDITOR``) so they keep the real stdio.
        r   Nredirect_stdoutr   )register_cliz/journeyF)progadd_helpr   journey_action)deleteeditTr   z  /journey failed: )argparseioshlex
contextlibr   r   r   hermes_cli.journeyr   ArgumentParserr-   
parse_argsr.   
SystemExitr   funcforce_colorStringIOgetvaluerstripr   )r8   r   r   r   r   r   r   r   parserrestr<   interactivebufexcs                 rA   _handle_journey_commandz(CLICommandsMixin._handle_journey_command*  s,    				......333333((j5(IIV!!$**	$$SYY]]U[[a%9%9%9PRSSDD 	 	 	FF	 d$4d;;?QQ
	1 		$#D++--C %%    		$                             GCLLNN))$//00000 	1 	1 	1G/#//000000000	1sU   AB 
B*)B*E &E  D"E "D&&E )D&*3E 
F)E==Fc                N   ddl m}m}m}m} t                      r |d| d |             |            dS ddlm}  |            rL|                                 r%t          | j
                  } |d| d           dS  |d| d	|            dS  |d| d
|            dS )u   Handle /paste — explicitly check clipboard for an image.

        This is the reliable fallback for terminals where BracketedPaste
        doesn't fire for image-only clipboard content (e.g., VSCode terminal,
        Windows Terminal with WSL2).
        r   )_DIM_RSTr   _termux_example_image_pathrL   uh   Clipboard image paste is not available on Termux — use /image <path> or paste a local image path like N)has_clipboard_imageu     📎 Image #z attached from clipboardz2(>_<) Clipboard has an image but extraction failedz!(._.) No image found in clipboard)r   r   r   r   r   _is_termux_environmenthermes_cli.clipboardr   _try_attach_clipboard_imager.   _attached_images)r8   r   r   r   r   r   ns          rA   _handle_paste_commandz&CLICommandsMixin._handle_paste_commandO  s;    	HGGGGGGGGGGG!## 	G8T 8 8--//8158 8  
 F<<<<<<   	H//11 ]-..DDDDEEEEE[T[[UY[[\\\\\GFFFFFGGGGGrC   c                   ddl m}m} |                    d          }t	          |          dk    r|d                                         nd}d | j        D             }|s |d           dS |rh	 t          |          dz
  }n# t          $ r  |d	           Y dS w xY w|dk     s|t	          |          k    r |d
t	          |           d           dS n~t	          |          dz
  }|dk    rS |||         	                    d                    s/|dz  }|dk    r$ |||         	                    d                    /|dk     r |d           dS  |||         	                    d                    }|s |d           dS 	 | 
                    |            |d|dz    d           dS # t          $ r}	 |d|	            Y d}	~	dS d}	~	ww xY w)u=   Handle /copy [number] — copy assistant output to clipboard.r   )_assistant_copy_textr   r   maxsplitr   c                D    g | ]}|                     d           dk    |S )role	assistantrw   ry   ms     rA   r{   z9CLICommandsMixin._handle_copy_command.<locals>.<listcomp>o  s,    ZZZ1QUU6]]k=Y=YQ=Y=Y=YrC   z  Nothing to copy yet.Nz  Usage: /copy [number]z!  Invalid response number. Use 1-r]   contentz-  Nothing to copy in assistant responses yet.z-  Nothing to copy in that assistant response.z  Copied assistant response #z to clipboardz  Clipboard copy failed: )r   r   r   r-   r.   stripr6   re   rf   r2   _write_osc52_clipboardr   )
r8   r   r   r   r;   argr   rn   textes
             rA   _handle_copy_commandz%CLICommandsMixin._handle_copy_commandi  s}   55555555""A".."%e**q..eAhnnbZZ 9ZZZ	 	G,---F 	#hhl   1222 Qww#Y//MC	NNMMMNNN 0 i..1$C((#7#7	#8J8J98U8U#V#V(q ((#7#7	#8J8J98U8U#V#V(QwwGHHH##IcN$6$6y$A$ABB 	GCDDDF	5''---GJC!GJJJKKKKK 	5 	5 	5G333444444444	5s*   1B BB
'F3 3
G=GGc                   ddl m}m}m}m}m}m}m} d|v r.|                    dd          d         	                                nd}	|	s/t                      r
 |            nd}
 |d| d	|
 |            dS  ||	          \  }} ||          }| |d| d
| |            dS |j                                        |vr |d| d|j         |            dS | j                            |            |d|j                    |r |d| d| |            dS t                      r$ |d| d ||j                   d|            dS dS )uG   Handle /image <path> — attach a local image file for the next prompt.r   )r   _IMAGE_EXTENSIONSr   r   _resolve_attachment_path_split_path_inputr   rO   Nr   r   z/path/to/image.pngrL   z"Usage: /image <path>  e.g. /image z(>_<) File not found: z"(._.) Not a supported image file: u     📎 Attached image: z<Now type your prompt (or use --image in single-query mode): z;Tip: type your next message, or run hermes chat -q --image z "What do you see?")r   r   r   r   r   r   r   r   r-   r   r   suffixr0   namer   append)r8   r   r   r   r   r   r   r   r   raw_argshint
path_token
_remainder
image_paths                 rA   _handle_image_commandz&CLICommandsMixin._handle_image_command  s    	H  	H  	H  	H  	H  	H  	H  	H  	H  	H  	H  	H  	H  	H  	H  	H  	H  	H>A\>Q>QL&&tQ//288:::WY 	3I3K3Ke--///QeDGMMMMtMMNNNF!2!28!<!<
J--j99
GGGGZGGGHHHF""$$,===GXXXXRVXXYYYF$$Z000;*/;;<<< 	dGmmm[emgkmmnnnnn#%% 	dG  c  c  cZtZtu  vE  [F  [F  c  c  ]a  c  c  d  d  d  d  d	d 	drC   r   c                J    ddl m}m}m}m ddl}ddlm} ddlm	 ddl
m ddlm d$ fd}	 |                    |          }n$# t          $ r |                                }Y nw xY wt!          |          dk    r|d         nd}	|	dvr                                  dS |	dk    r | |dd                     dS |dd         }
|
s;t%          d|	 d           t%          d|	 d           t%          d|	 d           dS |	dk    rdnd}d                    |
          } | | d| d|             | ||	|
d                      dd!lm} dd"lm}  | |            d           _                                           | d#|            dS )%a`  Handle /tools [list|disable|enable] slash commands.

        /tools (no args) shows the tool list.
        /tools list shows enabled/disabled status per toolset.
        /tools disable/enable saves the change to config and resets
        the session so the new tool set takes effect cleanly (no
        prompt-cache breakage mid-conversation).
        r   )_ACCENTr   r   r   N)	Namespacer   )r   )tools_disable_enable_commandnsr   r   r   c                8   t          dd           |            dS  G d d          } |            } |          5   |            ddd           n# 1 swxY w Y   |                                                                D ]} |           dS )a  Run tools_disable_enable_command, routing its ANSI-colored
            print() output through _cprint when inside the interactive TUI
            so escapes aren't mangled by patch_stdout's StdoutProxy into
            garbled '?[32m...?[0m' text.

            Outside the TUI (standalone mode, tests), call straight through
            so real stdout / pytest capture works as expected.
            _appNc                      e Zd ZddZdS )MCLICommandsMixin._handle_tools_command.<locals>._run_capture.<locals>._TTYBufr   boolc                    dS )NT )r8   s    rA   isattyzTCLICommandsMixin._handle_tools_command.<locals>._run_capture.<locals>._TTYBuf.isatty  s    4rC   Nr   r   )__name__
__module____qualname__r   r   rC   rA   _TTYBufr     s(                   rC   r   )r   r   r3   )	r   r   r   liner   r   r   r8   r   s	       rA   _run_capturez<CLICommandsMixin._handle_tools_command.<locals>._run_capture  s    tVT**2,,R000
         (       '))C %% 1 1,,R0001 1 1 1 1 1 1 1 1 1 1 1 1 1 11133   s   AA"Ar   r   >   rJ   enabledisablerJ   r   )tools_actionplatformr   z(._.) Usage: /tools z <name> [name ...]z  Built-in toolset:  /tools z webz  MCP tool:          /tools z github:create_issuer  	DisablingEnabling, rO   ...)r  namesr  )_get_platform_toolsload_configz0Session reset. New tool configuration is active.)r   r   r   r   )r   r   r   r   r   r   r   r   r   r   r   r   hermes_cli.tools_configr   r-   rf   r.   
show_toolsr'   r4   r	  hermes_cli.configr  enabled_toolsetsnew_session)r8   r   r   r   r   r   r   r   r;   
subcommandr  verbrT   r	  r  r   r   r   r   s   `              @@@@rA   _handle_tools_commandz&CLICommandsMixin._handle_tools_command  s    	544444444444&&&&&&......HHHHHH	 	 	 	 	 	 	 	 	 	6	 KK$$EE 	  	  	 IIKKEEE	  "%UaU1XXR
:::OOFLGGGHHHFabb	 	GGGGHHHAAAABBBQQQQRRRF
 )I55{{:		%  73D33533T33444YYJeeTTTUUU 	@?????111111 3 3KKMM5 I I4OOOOPPPPPs   A A0/A0c                    ddl m} ddlm}  |            } |            }t	                       t	          d|            t	          d|            t	                       dS )z/Display active profile name and home directory.r   rI   )get_active_profile_namez  Profile: z  Home:    N)rc   r	   hermes_cli.profilesr  r'   )r8   r	   r  displayprofile_names        rA   _handle_profile_commandz(CLICommandsMixin._handle_profile_command  s    888888??????%%''..00*L**+++%G%%&&&rC   r   c           	     	   ddl m} ddlm} |                    d          }t          |          dk     s|d                                         s# |d            |d            |d	           d
S |d                                                                         }	 ddlm	}m
} n&# t          $ r} |d|            Y d}~d
S d}~ww xY w	  ||          }	n'# t          t          f$ r  |d| d           Y d
S w xY w	  |            }
n&# t          $ r} |d|            Y d}~d
S d}~ww xY w|
j                            |	          }|r|j        s |d| d           d
S |
                    |	          }|r|j        s |d| d            |d           d
S t'          | dd          r |d           d
S | j        s'	 ddlm}  |            | _        n# t          $ r Y nw xY w| j        s |d |                        d
S 	 | j                            | j                  }|s2d| j        dd          }| j                            | j        |           n&# t          $ r} |d|            Y d}~d
S d}~ww xY wd}	 | j                            | j                  }|r|                    d          pd}n# t          $ r Y nw xY w|s| j        dd         }| j                            | j        |          }|s |d           d
S  |d | d!| d"|j         d#            |d$           ddl}|                                d%z   }d&}|                                |k     r	 | j                            | j                  }n# t          $ r d}Y nw xY w|pi                     d'          pd&}||k    r|d(k    r |d)           |}|d*k    r< |d            |d+| d            |d,|             |d           d
| _        dS |d-k    r4|pi                     d.          pd/} |d0|             |d1           d
S |                    d2           |                                |k     	 | j                            | j        d3           n# t          $ r Y nw xY w |d4            |d5           d
S )6u  Handle ``/handoff <platform>`` — transfer this CLI session to a gateway platform.

        Flow:
          1. Validate platform name + the gateway has a home channel for it.
          2. Reject if the agent is currently running (the in-flight turn
             would race with the gateway's switch_session).
          3. Write ``handoff_state='pending'`` on this session row.
          4. Block-poll ``state.db`` for terminal state (timeout 60s).
          5. On ``completed`` → print resume hint and signal CLI exit by
             returning False (the caller honors that like ``/quit``).
          6. On ``failed`` / timeout → print error and return True so the
             user keeps their CLI session.

        Returns:
            False to signal CLI exit, True to keep going.
        r   r   format_session_db_unavailabler   r   r   z  Usage: /handoff <platform>z@  Hands the current session off to that platform's home channel.z:  The CLI session ends here; resume it later with /resume.T)load_gateway_configPlatformz!  Could not load gateway config: Nz  Unknown platform 'z'.z  Platform 'z+' is not configured/enabled in the gateway.z!  No home channel configured for r]   z6  Set one with /sethome on the destination chat first.r   FzJ  Agent is busy. Wait for the current turn to finish, then retry /handoff.)	SessionDBrL   zhandoff-   z,  Could not ensure session row in state.db: r   titlezN  Session is already in flight for handoff. Wait for it to settle, then retry.z  Queued handoff of 'u   ' → z (home: ra   z*  Waiting for the gateway to pick it up...g      N@pendingstaterv   z'  Gateway picked it up; transferring...	completedu5     ↻ Handoff complete. The session is now active on z,  Resume it on this CLI later with: /resume failedr   zunknown errorz  Handoff failed: zV  Your CLI session is intact. Try /handoff again, or /resume on the platform manually.      ?ztimed out waiting for gatewayzA  Timed out waiting for the gateway. Is `hermes gateway` running?z  Your CLI session is intact.) r   r   hermes_stater  r-   r.   r   r0   gateway.configr  r  r   rf   KeyError	platformsr2   r)   get_home_channelchat_idr   _session_dbr  get_sessionr   set_session_titlerequest_handoffr   timeget_handoff_state_should_exitsleepfail_handoff)r8   r   r   r  r;   platform_namer  r  r   r  	gw_configpcfghomer  rowplaceholder_titlesession_titleok_timedeadline
last_state	state_rowcurrenterrs                           rA   _handle_handoff_commandz(CLICommandsMixin._handle_handoff_command  s   " 	 >>>>>>""A"..u::>>q!1!1>G2333GVWWWGPQQQ4a((..00	DDDDDDDDD 	 	 	G===>>>44444		x..HHH% 	 	 	G<=<<<===44		++--II 	 	 	G===>>>44444	 "&&x00 	4< 	G]=]]]^^^4))(33 	4< 	GHHHHIIIGLMMM4 4)511 	G`aaa4  	222222#,9;;      	G:6688::;;;4	"..t??C W
 %Etrr/B$D$D! 224?DUVVV 	 	 	GH3HHIII44444	
 	"..t??C 7 # 0 0 6B 	 	 	D	 	0 OBQB/M --do}MM 	Gdeee4aaa]aaTXT]aaabbb<=== 	::<<$&
jjllX%%! ,>>tOO		 ! ! ! 			! B++G44A	G*$$i''GEFFF$
+%%`P]```aaaV}VVWWW$(!u("" B++G44G2S22333pqqqtKK/ jjllX%%4	))$/;Z[[[[ 	 	 	D	STTT/000ts    B) )
C3CCC  D ?D 
D 
D2D--D2	G 
G,+G,AI# #
J-JJ8K 
KK1N N N   R! !
R.-R.c                
   ddl m}m} |                    dd          }t	          |          dk    r|d                                         n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                                         }|sK |d           |                     d          r|                     d          | _        dS  |d           dS d| _        | j	        sddl
m}  |d |                        dS |                                rn|                     d          }t          |          }|dk     s|t	          |          k    r |d| d            |d           dS ||dz
           }	|	d         }
nddlm}  ||          }|p|}
| j	                            |
          }|s |d|             |d           dS 	 | j	                            |
          }n# t$          $ r |
}Y nw xY w|r8||
k    r2 |d|
 d| d           |}
| j	                            |
          }|r|}|
| j        k    r |d            dS | j        }| j        r1	 | j                            | j                   n# t$          $ r Y nw xY w	 | j	                            | j        d!           n# t$          $ r Y nw xY w|
| _        d"| _        d| _         ||
           | j	                            |
          }d# |pg D             }|| _        	 | j	                            |
           n# t$          $ r Y nw xY w| j        r|
| j        _        | j                                         t;          | j        d$          rt	          | j                  | j        _        t;          | j        d%          r,	 dd&lm }  |            | j        _!        n# t$          $ r Y nw xY wt;          | j        d'          r| j        "                                 	 tG          | j        d(d          }||$                    |
|pdd)d*           n# t$          $ r Y nw xY w|%                    d+          rd,|d+          dnd}t	          d- | j        D                       }| j        rJ |d.|
 | d/| d0|dk    rd1nd d2t	          | j                   d3
           | &                                 dS  |d.|
 | d4           dS )5uW   Handle /resume <session_id_or_title> — switch to a previous session mid-conversation.r   r   _sync_process_session_idNr   r   r   <>[]"'z-  Usage: /resume <number|session_id_or_title>resumer   
   r[   zA  Tip:   Use /history or `hermes sessions list` to find sessions.r  rL   z  Resume index z is out of range.z:  Use /resume with no arguments to see available sessions.rV   )_resolve_session_by_name_or_idz  Session not found: zC  Use /history or `hermes sessions list` to see available sessions.z
  Session z was compressed into z/; resuming the descendant with your transcript.z  Already on that session.resumed_otherTc                D    g | ]}|                     d           dk    |S )r   session_metarw   r   s     rA   r{   z;CLICommandsMixin._handle_resume_command.<locals>.<listcomp>  s,    SSS!155==N3R3RA3R3R3RrC   _last_flushed_db_idx_todo_store	TodoStore_invalidate_system_prompt_memory_managerFparent_session_idresetr#   r!  z "c                D    g | ]}|                     d           dk    |S r   userrw   r   s     rA   r{   z;CLICommandsMixin._handle_resume_command.<locals>.<listcomp>0  -    YYYqvRXAXAXAXAXAXrC   u     ↻ Resumed session  ( user messagerj   r  z total)u!    — no messages, starting fresh.)'r   r   rG  r-   r.   r   _show_recent_sessions_list_recent_sessions_pending_resume_sessionsr-  r'  r  isdigitre   hermes_cli.mainrQ  r.  resolve_resume_session_idr   r   r   _flush_messages_to_session_dbr6   end_session_resumed_pending_titleget_messages_as_conversationreopen_sessionreset_session_stater&   rU  tools.todo_toolrX  rV  rY  r   on_session_switchr2   _display_resumed_history)r8   r   r   rG  r;   targetr  sessionsindexselected	target_idrQ  resolvedrT  resolved_idresolved_metaold_session_idrestoredrX  _mm
title_part	msg_counts                         rA   _handle_resume_commandz'CLICommandsMixin._handle_resume_command  s2   99999999""4++%(ZZ!^^q!!! v;;!AY#&*"3"3q	S  VBZ3%6%6q	S  VBZ3%6%6q	S  VBZ3%6%6AbD\''))F 	GCDDD)))::  150J0JQS0J0T0T-GWXXXF )-% 	BBBBBBG:6688::;;;F >> 	+111;;HKKEqyyECMM11B%BBBCCCTUUU	*H IIFFFFFF55f==H *FI'33I>> 	G4F44555GYZZZF	$*DDYOOKK 	$ 	$ 	$#KKK	$ 	-;)33GAY A A[ A A A   $I ,88CCM -,''G0111F: 	
88-       	((/JJJJ 	 	 	D	 $"  +++ #@@KKSSBSSS$,!	++I6666 	 	 	D	 : 	$-DJ!J**,,,tz#9:: Q25d6O2P2P
/tz=11 999999-6Y[[DJ**    Dtz#>?? 7
44666
dj*;TBB?))!*8*>B#'	 *        9E8H8H8Q8QY4<04444WY
YYD$=YYYZZ	$ 	gG< <J < << <4=NNSS< <122< < <  
 ))+++++GeYe
eeefffffsl   %I   II3K 
K K $ L 
LL%N   
NNP! !
P.-P. 3R 
R! R!c                   ddl m} |                    dd          }t          |          dk    r|d                                         nd}|                                }|r|dv rH| j        sddlm}  |d |                        dS | 	                    d	
          s |d           dS | 
                    d|            dS )u&  Handle /sessions [list|<id_or_title>] — browse or resume previous sessions.

        Without arguments, prints the same recent-sessions table that /resume
        shows when called without a target, and tells the user how to resume.
        With an explicit subcommand or target, delegates to the resume flow so
        ``/sessions <id>`` and ``/resume <id>`` behave identically.

        The TUI ships an interactive picker overlay for this command; the
        classic CLI prints an inline list because there is no equivalent
        overlay primitive here. Without this handler the canonical name
        ``sessions`` falls through ``process_command``'s elif chain and
        prints ``Unknown command: sessions`` even though the command is
        registered in the central COMMAND_REGISTRY.
        r   r   Nr   r   >   rK   rJ   browser  rL   ru  r   z!  (._.) No previous sessions yet.z/resume )r   r   r-   r.   r   r0   r-  r'  r  rd  r  )r8   r   r   r;   r   subr  s          rA   _handle_sessions_commandz)CLICommandsMixin._handle_sessions_command;  s    	 ""4++"%e**q..eAhnnbiikk  	c555# FFFFFF>::<<>>???--Z-@@ =;<<<F 	##$4s$4$455555rC   c                l	   ddl m}m} | j        s |d           dS | j        sddlm}  |d |                        dS |                    dd          }t          |          dk    r|d         	                                nd}t          j                    }|                    d	          }t          j                    j        dd
         }	| d|	 }
|r|}nFd}| j        r| j                            | j                  }|pd}| j                            |          }| j        }| j        r1	 | j                            | j                   n# t*          $ r Y nw xY w	 | j                            | j        d           n# t*          $ r Y nw xY w	 | j                            |
t0          j                            dd          | j        | j        | j        |d|           n&# t*          $ r} |d|            Y d}~dS d}~ww xY w| j        D ]}	 | j                            |
|                    dd          |                    d          |                    d          p|                    d          |                    d          |                    d          |                    d                     # t*          $ r Y w xY w	 | j                            |
|           n# t*          $ r Y nw xY w|                      | j        |
           |
| _        || _!        d| _"        d| _#         ||
           | j        r|
| j        _        || j        _!        | j        $                                 tK          | j        d          rt          | j                  | j        _&        tK          | j        d          r,	 ddl'm(}  |            | j        _)        n# t*          $ r Y nw xY wtK          | j        d           r| j        *                                 	 tW          | j        d!d          }||,                    |
|pdd"d#           n# t*          $ r Y nw xY wt          d$ | j        D                       } |d%| d&| d'|dk    rd(nd d)            |d*|             |d+|
            dS ),u*  Handle /branch [name] — fork the current session into a new independent copy.

        Copies the full conversation history to a new session so the user can
        explore a different approach without losing the original session state.
        Inspired by Claude Code's /branch command.
        r   rF  u5     No conversation to branch — send a message first.Nr  rL   r   r   z%Y%m%d_%H%M%S   _branchbranchedHERMES_SESSION_SOURCEr   )max_iterationsreasoning_config_branched_from)r   sourcemodelmodel_configr\  z#  Failed to create branch session: r   r`  r   	tool_namer   
tool_callstool_call_id	reasoning)r   r   r   r  r  r  r  TrU  rV  rW  rY  rZ  Fr[  c                D    g | ]}|                     d           dk    |S r_  rw   r   s     rA   r{   z;CLICommandsMixin._handle_branch_command.<locals>.<listcomp>  ra  rC   u     ⑂ Branched session "z" (rc  rj   )z  Original session: z  Branch session:   )-r   r   rG  r6   r-  r'  r  r-   r.   r   r   nowstrftimeuuiduuid4hexget_session_titler   get_next_title_in_lineager   rj  r   rk  create_sessionr*   environr2   r  	max_turnsr  append_messager/  _transfer_session_yolosession_startrm  rl  rp  r&   rU  rq  rX  rV  rY  r   rr  )r8   r   r   rG  r  r;   branch_namer  timestamp_str
short_uuidnew_session_idbranch_titlecurrent_titlebaser\  r   msgrX  r~  r  s                       rA   _handle_branch_commandz'CLICommandsMixin._handle_branch_command\  s    	:9999999( 	GKLLLF 	BBBBBBG:6688::;;;F""4++*-e**q..eAhnn&&&b lnn_55Z\\%bqb)
)88J88  	L&LL !M T $ 0 B B4? S S ,HD+EEdKKL !O : 	
88-       	((*EEEE 	 	 	D		++)z~~&=uEEj&*n(,(=&7 
 #4 , 
 
 
 
  	 	 	G=!==>>>FFFFF	
 , 	 	C //-00GGI..!ggk22Ecggfoo"ww|44!$!8!8!ggk22 0        	..~|LLLL 	 	 	D	 	##DO^DDD( "  000 : 	$2DJ!'*DJ$J**,,,tz#9:: Q25d6O2P2P
/tz=11 999999-6Y[[DJ**    Dtz#>?? 7
44666
dj*;TBB?))&*;*Ar#'	 *        YYD$=YYYZZ	J J JJ J09QBJ J J	
 	
 	
 	:'8::;;;7~7788888s   0E 
EE! F 
FFAG$ $
H.HHB)J>>
K
KK+ +
K87K8?O 
O'&O'3Q 
QQc                   ddl m} |                    d          }t          |          dk    ru|d                                                                         }|dv rJd| _        d| _         |dd          rt          d	           nt          d
           t          d           dS || j	        v r| 
                    | j	        |                   | _        d| _         |d| j                  rt          d| d           nt          d| d           t          d| j        dd          t          | j                  dk    rdnd d           dS t          d|            t          dd                    | j	                                                              dS t                       t          d           t          d           t          d           t                       t          dddd           | j	                                        D ]{\  }}t          |t                    r4|                    d          p|                    dd          dd         }nt#          |          dd         }t          d|dd |            |t                       t          d!           t                       dS )"z@Handle the /personality command to set predefined personalities.r   save_config_valuer   r   >   nonedefaultneutralr   Nzagent.system_promptz,(^_^)b Personality cleared (saved to config)z((^_^) Personality cleared (session only)u7     No personality overlay — using base agent behavior.z(^_^)b Personality set to '' (saved to config)z(^_^) Personality set to '' (session only)z  "r   r  rM  z(._.) Unknown personality: z  Available: none, r  z4+--------------------------------------------------+z1|            (^o^)/ Personalities               |rL   r  <12z - (no personality overlay)descriptionsystem_prompt2   z - z  Usage: /personality <name>)r   r  r-   r.   r   r0   r  r   r'   personalities_resolve_personality_promptr4   keysitems
isinstancedictr2   r   )r8   r   r  r;   personality_namer   promptpreviews           rA   _handle_personality_commandz,CLICommandsMixin._handle_personality_command  s   ))))))		1	%%u::>>$Qx~~//5577#AAA%'"!
$$%:B?? FHIIIIDEEEOPPPPP!T%777%)%E%EdFXYiFj%k%k"!
$$%:D<NOO []8H]]]^^^^Y7GYYYZZZgT/4gs4CU?V?VY[?[?[eeacggghhhhhF4DFFGGGRDIId6H6M6M6O6O,P,PRRSSSSS GGG&'''JKKK&'''GGG>v>>>>??? $ 2 8 8 : : 3 3ffd++ /$jj77_6::oWY;Z;Z[^\^[^;_GG!&kk#2#.G14111112222GGG0111GGGGGrC   c                   ddl m} ddlm} ddlm}m}m}m}m	} |
                    d          }	t          |	          dk    r|	d                                         nd}
|
                                }|
r|dk    rS |            \  }}}|rt          d	|            d
S |rt          d| d           nt          |rd| dnd           d
S |dv r |             d
S |dk    s|                    d          rg|
t          d          d
                                         }|st          d           d
S  ||          \  }}t          |rd	| nd|dd           d
S |dk    r |d           t          d           d
S t          d|
 d           	 |                    |
          }n/# |j        |f$ r }t          d|
 d|            Y d
}~d
S d
}~ww xY w ||
           t          d|j         d           d
S )u1  Toggle, browse, or adopt a petdex mascot.

        ``/pet`` / ``/pet toggle`` → flip ``display.pet.enabled`` on/off
        ``/pet list``            → browse the petdex gallery
        ``/pet scale <n>``       → resize the pet everywhere (e.g. 0.5)
        ``/pet <slug>``          → adopt (install if needed) + make active
        ``/pet off``             → disable (alias for toggle-off)

        Writes ``display.pet.*`` to config; the CLI/TUI/desktop pet surfaces
        pick the change up on their next poll, so the pet appears shortly.
        r   store)ManifestError)_set_active_set_enabledprint_pet_galleryset_pet_scaletoggle_pet_displayr   r   r   togglez(x_x) N(^_^)b u!    is out — it'll pop in shortly.z	(-_-)zzZ z
 put away.z(-_-)zzZ Pet put away.)rJ   galleryr  allscalezscale z7(o_o) Usage: /pet scale <factor>  (e.g. /pet scale 0.5)u   (^_^) Pet scale → gr]   offFz(o_o) Fetching 'u   ' from petdex…z(x_x) Couldn't adopt 'z': )	agent.petr  agent.pet.manifestr  hermes_cli.petsr  r  r  r  r  r-   r.   r   r0   r'   
startswithinstall_petPetStoreErrordisplay_name)r8   r   r  r  r  r  r  r  r  r;   r   lowr)   r   rC  valuer  petr   s                      rA   _handle_pet_commandz$CLICommandsMixin._handle_pet_command  s    	$#####444444ssssssssssssss		1	%%"%e**q..eAhnnbiikk 		cXoo!3!3!5!5GT3 nsnn%%% ZGGGGHHHHdX2$2222@XYYYF666F'>>S^^H55>G&,,..E OPPP&u--JE3CN.3...-NE-N-N-N-NOOOF%<<L*+++F6666777	##C((CC#]3 	 	 	8388388999FFFFF	 	CK(KKKLLLLLs   F- -G9GGc                ,   ddl m} ddlm} ddlm} ddlm} |                    d          }t          |          dk    r|d         
                                nd}|sI	 t          d	          
                                }n&# t          t          f$ r t                       Y d
S w xY w|st          d           d
S d                    d |                                d
d         D                       d
d         
                                pd}|                    |          p|                    |          pd}	t          d| d           	 |                    |d          }
n%# |$ r}t          d|            Y d
}~d
S d
}~ww xY w|
st          d           d
S d!d}	 |                    |
d         |	|||          }n%# |$ r}t          d|            Y d
}~d
S d
}~ww xY w ||j                   t          d|j         d            d
S )"a  Generate ("hatch") a brand-new petdex pet from a description.

        ``/hatch <description>`` runs the full pet pipeline in-process: a base
        look, then one grounded animation row per state, sliced + normalized into
        a spritesheet, then adopted as the active mascot. Progress streams inline
        (it's ~a minute of image-model calls). In the desktop app this command
        opens the richer generate overlay instead; here we run it directly.
        r   r  )orchestrate)GenerationError)r  r   r   r   z(o_o) Describe your pet: NzA(o_o) Usage: /hatch <description>  (e.g. /hatch a tiny cyber fox)rO   c              3  >   K   | ]}|                                 V  d S N)
capitalizery   ws     rA   	<genexpr>z9CLICommandsMixin._handle_hatch_command.<locals>.<genexpr>r  s*      LL1LLLLLLrC   rZ      Petr  z(o_o) Designing 'u$   '… (a minute of image-model calls))r   z%(x_x) Couldn't generate a base look: u,   (x_x) No base draft came back — try again.eventr   detailr   r   c                    | dk    r1|                     dd          d         }t          d| d           d S | dk    rt          d           d S | d	k    rt          d
           d S d S )Nr:  :r   r   u     ┊ drawing u   …composeu     ┊ composing spritesheet…saveu     ┊ saving…)r-   r'   )r  r  r#  s      rA   	_progressz9CLICommandsMixin._handle_hatch_command.<locals>._progress  s    ~~S!,,Q/1u11122222)##677777&'((((( !rC   )
base_imageslugr  concepton_progressz(x_x) Hatch failed: r  u.    hatched and adopted — it'll pop in shortly!)r  r   r  r   r   r   )r  r  agent.pet.generater  agent.pet.generate.imagegenr  r  r  r-   r.   r   inputEOFErrorKeyboardInterruptr'   r4   slugifygenerate_base_drafts	hatch_petr  r  )r8   r   r  r  r  r  r;   r  r  r  draftsr   r  r?   s                 rA   _handle_hatch_commandz&CLICommandsMixin._handle_hatch_commandU  s    	$#####222222??????//////		1	%%&)%jj1nn%(.."""" 	 ;<<BBDD/0     	UVVVF xxLL8KLLLLLSbSQWWYYb]b}}\**MemmG.D.DMO'OOOPPP	 55g5CCFF 	 	 	?#??@@@FFFFF	  	@AAAF	) 	) 	) 	)
	 **!!9)% +  FF  	 	 	...///FFFFF	 	FK   [+[[[\\\\\sB   !!B B&%B&E) )F.FF& G G)G$$G)c           
        ddl m} ddl}ddlm fd}d }d }|                    |          }t          |          dk    rat                       t          d	           t          d
           t          d	           t                       t          d           t          d           t          d           t          d           t          d           t          d           t          d           t          d           t          d           t          d           t          d           t                        |d          }|                    d          r|                    dg           ng }	|	r
t          d           t          d           |	D ]}
|
                    dd          }t          d|
d         dd          d!d"|
d#         d$d"|d%           |
                    d&          r+t          d'd(	                    |
d&                               t          d)|
                    d*d+                      |
                    d,          rt          d-|
d,                     t                       nt          d.           t                       dS |d         
                                } ||d/d                   }|dS |dk    r |d|d0         1          }|                    d          r|                    dg           ng }	|	st          d2           dS t                       t          d3           t          d4           |	D ]h}
t          d5|
d                     t          d6|
d7                     t          d8|
                    d9d                      t          d:|
d#          d;|
                    dd           d<           t          d=|
                    d,d>                      |
                    d&          r+t          d?d(	                    |
d&                               t          d@|
                    d*d+                      |
                    dA          r0t          dB|
dA          d;|
                    dCd           d<           t                       jdS |dDv rc|dE         }|st          dF           dS |d#         p|d         }|dG         pdH	                    |dd                   } ||d&                   }|s|st          dI           dS  |dJ||pd|d7         |dK         |d         |pdL          }|                    d          rt          dM|d                     t          d:|d#                     |                    d&          r+t          d?d(	                    |d&                               t          d=|d,                     n%t          dN|                    dO                      dS |dPk    r|dE         }|st          dQ           dS |d         } ||          }|st          dR|            dS d} ||d&                   } ||dS                   }t           ||dT                             t          |                    d&          p,|                    dU          sg n|                    dU          g          }|dV         rg }n5|r|}n0|sr,fdW|D             }|D ]}||vr|                    |            |dX||d#         |dG         |d7         |dK         |d         |Y          }|                    d          r|dZ         }
t          d[|
d                     t          d:|
d#                     |
                    d&          r,t          d?d(	                    |
d&                               n5t          d\           n%t          d]|                    dO                      dS |d^v r{|dE         }|st          d_| d`           dS |d         }|dav rdbn|} ||||dck    rddnde          }|                    d          s*t          df| dg|                    dO                      dS |dck    r#t          dh|dZ         d7          d;| d<           n|dik    rNt          dj|dZ         d7          d;| d<           t          d=|dZ                             d,                      nx|dkk    r2t          dl|dZ         d7          d;| d<           t          dm           n@|                    dni           }t          do|                    d7|           d;| d<           dS t          dp|            t          dq           dS )rz3Handle the /cron command to manage scheduled tasks.r   )get_jobN)cronjobc                 8    t          j         di |           S )Nr   )jsonloads)kwargscronjob_tools    rA   	_cron_apiz8CLICommandsMixin._handle_cron_command.<locals>._cron_api  s#    :ll44V44555rC   c                    g }| D ]@}t          |pd                                          }|r||vr|                    |           A|S )Nr   )r   r   r   )values
normalizedr  r   s       rA   _normalize_skillsz@CLICommandsMixin._handle_cron_command.<locals>._normalize_skills  s`    J , ,5;B''--// ,D
22%%d+++rC   c                   d d d g g g ddd d g d}d}|t          |           k     rS| |         }|dk    r+|dz   t          |           k     r| |dz            |d<   |dz  }n|dk    r+|dz   t          |           k     r| |dz            |d	<   |dz  }n|d
k    rZ|dz   t          |           k     rD	 t          | |dz                      |d<   n # t          $ r t          d           Y d S w xY w|dz  }nu|dk    rA|dz   t          |           k     r+|d                             | |dz                       |dz  }n.|dk    r@|dz   t          |           k     r*|d                             | |dz                       |dz  }n|dk    r@|dz   t          |           k     r*|d                             | |dz                       |dz  }n|dk    rd|d<   |dz  }n|dk    rd|d<   |dz  }n|dk    r*|dz   t          |           k     r| |dz            |d<   |dz  }nP|dk    r*|dz   t          |           k     r| |dz            |d<   |dz  }n |d                             |           |dz  }|t          |           k     S|S )NF)r   deliverrepeatskills
add_skillsremove_skillsclear_skillsr  r  schedulepositionalsr   z--namer   r   r   z	--deliverr  z--repeatr  z!(._.) --repeat must be an integerz--skillr  z--add-skillr  z--remove-skillr  z--clear-skillsTr  z--allr  z--promptr  z
--scheduler  r  )r.   re   rf   r'   r   )tokensoptsri   tokens       rA   _parse_flagsz;CLICommandsMixin._handle_cron_command.<locals>._parse_flags  s    !# % ! D Ac&kk//q	H$$QV)<)<#)!a%=DLFAAk))a!ec&kk.A.A&,QUmDOFAAj((QUS[[-@-@$),VAE]););X% $ $ $ABBB#tt$ FAAi''AECKK,?,?N))&Q-888FAAm++AF0C0C&--fQUm<<<FAA...1q53v;;3F3F)00A???FAA...+/D(FAAg%%"&DKFAAj((QUS[[-@-@%+AE]DNFAAl**q1us6{{/B/B'-a!e}D$FAA'..u555FAM c&kk//N Ks   ,C C%$C%r   zF+--------------------------------------------------------------------+zD|                      (^_^) Scheduled Tasks                       |z  Commands:z    /cron listzD    /cron add "every 2h" "Check server status" [--skill blogwatcher]zA    /cron edit <job_id> --schedule "every 4h" --prompt "New task"z8    /cron edit <job_id> --skill blogwatcher --skill mapsz2    /cron edit <job_id> --remove-skill blogwatcherz&    /cron edit <job_id> --clear-skillsz    /cron pause <job_id>z    /cron resume <job_id>z    /cron run <job_id>z    /cron remove <job_id>rJ   )actionr   jobsz  Current Jobs:zA  ---------------------------------------------------------------r  r   r   job_id   r  z | r  z<15z<8r  z      Skills: r  z      prompt_previewr   next_run_atz      Next: z3  No scheduled jobs. Use '/cron add' to create one.r   r  )r  include_disabledz(._.) No scheduled jobs.zScheduled Jobs:zP--------------------------------------------------------------------------------z  ID: z  Name: r   z	  State: r#  z  Schedule: rb  r  z  Next run: zN/Az
  Skills: z
  Prompt: last_run_atz  Last run: last_status>   addrX   r  z*(._.) Usage: /cron add <schedule> <prompt>r  rO   z3(._.) Please provide a prompt or at least one skillrX   r  )r  r  r  r   r  r  r  z(^_^)b Created job: z(x_x) Failed to create job: r   r   zN(._.) Usage: /cron edit <job_id> [--schedule ...] [--prompt ...] [--skill ...]z(._.) Job not found: r  r  skillr  c                    g | ]}|v|	S r   r   )ry   r#  r  s     rA   r{   z9CLICommandsMixin._handle_cron_command.<locals>.<listcomp>Y  s$    aaa%eS`F`F`F`F`F`rC   update)r  r  r  r  r   r  r  r  jobz(^_^)b Updated job: z  Skills: nonez(x_x) Failed to update job: >   rmrunpauser   removerO  z(._.) Usage: /cron z	 <job_id>>   r'  r   r*  r*  r)  zpaused from /cron)r  r  r#   z(x_x) Failed to z job: z(^_^)b Paused job: rO  z(^_^)b Resumed job: r(  z(^_^)b Triggered job: z)  It will run on the next scheduler tick.removed_jobz(^_^)b Removed job: z(._.) Unknown cron command: z8  Available: list, add, edit, pause, resume, run, remove)r   r   r   tools.cronjob_toolsr  r-   r.   r'   r2   r4   r0   setrJ   r   )r8   r   r   r   r  r  r  r  r?   r  r&  
repeat_strr  r  r  r  r  r  r  existingfinal_skillsreplacement_skillsr  existing_skillsr#  r  removedr  r  s                              @@rA   _handle_cron_commandz%CLICommandsMixin._handle_cron_command  s   ??????	6 	6 	6 	6 	6	 	 	6	 6	 6	p S!!v;;!GGG&'''KLLL&'''GGG-   "###XYYYUVVVLMMMFGGG:;;;,----...*+++-...GGGYf---F-3ZZ	-B-BJ6::fb)))D M'(((o&&&  C!$3!7!7JcXss!3cccC
OcccT^cccdddwwx(( KItyyX/G/GIIJJJB377+;R#@#@BBCCCww}-- CAS-?AABBBGGGG KLLLGGGFAY__&&
|F122J''<FYftE{KKKF-3ZZ	-B-BJ6::fb)))D 0111GGG#$$$(OOO  .s8}..///.V..///9#'''3"7"799:::QS_QQ#8N8NQQQRRRDSWW]E%B%BDDEEE778$$ CAtyyX'?'?AABBBB377+;R#@#@BBCCC77=)) _]]);]]sww}VY?Z?Z]]]^^^F***}-K BCCCJ'9;q>H(^@sxxABB'@'@F&&tH~66F & KLLLY!~&\YH~~  F zz)$$ L?VH-=??@@@9VJ%799:::::h'' FDtyy1A'B'BDDEEE<VM%:<<====JVZZ5H5HJJKKKF}-K fggg ^FwvH 6f66777L!2!24>!B!B**4+=>>J 1 1$2G H HIIM"8<<#9#9#{U\H]H]>zbbdldpdpqxdydycz||ON# 3!# 31 3} 3aaaa?aaa' 3 3EL00$++E222Yj)H~&\YH~#	 	 	F zz)$$ 	LUm<S]<<===6S_66777778$$ ,AtyyX'?'?AABBBB*++++JVZZ5H5HJJKKKFMMM}-K AJAAABBB ^F!+/I!I!IXXzFYfV[ael[l[lDWDWrvwwwF::i(( LLLvzz'7J7JLLMMM  NF5M&,ANNVNNNOOOO8##OVE]6-BOOfOOOPPPGVE]%6%6}%E%EGGHHHH5Qve}V/DQQQQQRRRABBBB **]B77UW[[-H-HUUFUUUVVVF9Z99:::HIIIIIrC   c                b   ddl }	 |r|                    |          dd         ng }n.# t          $ r! |pd                                dd         }Y nw xY wd                    |          }	 ddlm}  ||          }n# t          $ r}d| }Y d}~nd}~ww xY w|                     |           dS )u  Handle /suggestions — review/accept/dismiss suggested automations.

        Delegates to the shared handler so CLI and gateway never drift. CLI
        origin is the local platform so an accepted job's "origin" delivery
        resolves to a configured home channel.
        r   Nr   r   rO   )handle_suggestions_commandzSuggestions command failed: )r   r-   rf   r4   hermes_cli.suggestions_cmdr6  r   _console_print)r8   r   r   r  r<   r6  outputr   s           rA   _handle_suggestions_commandz,CLICommandsMixin._handle_suggestions_command  s     		--08U[[%%abb))bFF 	- 	- 	-iR&&((,FFF	-xx	8MMMMMM//55FF 	8 	8 	87A77FFFFFF	8F#####s'   !( (AA,A> >
BBBc                   ddl 	 |r                    |          dd         ng }n.# t          $ r! |pd                                dd         }Y nw xY wd                    fd|D                       }	 ddlm}  ||          }n0# t          $ r#}|                     d|            Y d}~dS d}~ww xY w|                     |j                   t          |d	d          }|r	|| _
        dS dS )
u  Handle /blueprint — set up an automation from a blueprint template.

        Delegates to the shared handler. A bare ``/blueprint`` lists the
        catalog; ``/blueprint <name>`` name-matches a blueprint and seeds the
        agent to ask the user for each value conversationally (the result's
        ``agent_seed``); ``/blueprint <name> slot=val …`` creates the job
        directly. When a seed is returned it is stashed as a one-shot pending
        message the interactive loop runs as the next agent turn.
        r   Nr   r   rO   c              3  B   K   | ]}                     |          V  d S r  )quote)ry   tr   s     rA   r  z=CLICommandsMixin._handle_blueprint_command.<locals>.<genexpr>  s-      771A777777rC   )handle_blueprint_commandzCron blueprint command failed: 
agent_seed)r   r-   rf   r4   hermes_cli.blueprint_cmdr?  r   r8  r   r   _pending_agent_seed)	r8   r   r  r<   r?  r?   r   seedr   s	           @rA   _handle_blueprint_commandz*CLICommandsMixin._handle_blueprint_command  sY    		--08U[[%%abb))bFF 	- 	- 	-iR&&((,FFF	-xx777777777	IIIIII--d33FF 	 	 	 E! E EFFFFFFFF	 	FK(((v|T22 	, (,D$$$	, 	,s'   !) (AA9B 
B8B33B8c                    ddl }|r|                    |          dd         ng }|sdg}	 ddlm}  ||           dS # t          $ r Y dS t
          $ r}t          d|            Y d}~dS d}~ww xY w)zHandle /curator slash command.

        Delegates to hermes_cli.curator so the CLI and the `hermes curator`
        subcommand share the same handler set.
        r   Nr   ru   )cli_mainz(._.) curator: )r   r-   hermes_cli.curatorrF  r   r   r'   )r8   r   r   r  rF  r   s         rA   _handle_curator_commandz(CLICommandsMixin._handle_curator_command  s     	),4S!!!""%%" 	 ZF	+333333HV 	 	 	 DD 	+ 	+ 	+)C))*********	+s   ? 
A2	A2A--A2c                   ddl m} |                                }|                    d          r|                    d          }|                    d          r)|t          d          d                                         }	  ||          }n# t          $ r}d| }Y d}~nd}~ww xY w|rt          |           dS dS )u#  Handle the /kanban command — delegate to the shared kanban CLI.

        The string form passed here is the user's full ``/kanban ...``
        including the leading slash; we strip it and hand the remainder
        to ``kanban.run_slash`` which returns a single formatted string.
        r   )	run_slash/kanbanNz(._.) kanban error: )hermes_cli.kanbanrJ  r   r  lstripr.   r   r'   )r8   r   rJ  r   r9  r   s         rA   _handle_kanban_commandz'CLICommandsMixin._handle_kanban_command  s     	0/////yy{{??3 	$;;s##D??8$$ 	1H'..00D	2Yt__FF 	2 	2 	21C11FFFFFF	2 	&MMMMM	 	s   B 
B)B$$B)c                x    ddl m} |                                                                }t	          |          dk    r
|dd         ng }|rQ|d                                         dv r5ddlm} ddlm	}  ||j
        | fd	          }|t          |           dS dd
lm}  || |                       dS )uD   Handle /skills slash command — delegates to hermes_cli.skills_hub.r   )ChatConsoler   N>	   denyr   dropmodeapplyrejectapprover"  approvalhandle_pending_subcommandwrite_approvalc                0                         d|           S )Nr  _save_write_approvalr)   r8   s    rA   <lambda>z9CLICommandsMixin._handle_skills_command.<locals>.<lambda>  s    D,E,EhPW,X,X rC   )set_mode_fn)handle_skills_slash)r   rQ  r   r-   r.   r0   "hermes_cli.write_approval_commandsrZ  toolsr\  SKILLSr'   hermes_cli.skills_hubrc  )	r8   r   rQ  r;   r<   rZ  waoutrc  s	   `        rA   _handle_skills_commandz'CLICommandsMixin._handle_skills_command  s   ###### 		!!##JJNNuQRRyy 
	DGMMOO (T T TTTTTTT222222++	4XXXX  C c


======C/////rC   c                   ddl m} |                                                    dd          }t	          |          dk    r|d                                         nd} ||          }|rt          d           nt          d           t          | d          r| j                            |           dS t          d	           dS )
u  Handle /learn — distill a reusable skill from anything the user describes.

        Open-ended: the argument is free text describing the source(s) — a
        directory, a URL, "what we just did", pasted notes. We build a
        standards-guided prompt and inject it onto the agent's input queue; the
        live agent gathers the material with the tools it already has and
        authors the skill via ``skill_manage``. No engine, no model-tool
        footprint, works on any terminal backend.
        r   )build_learn_promptNr   r   u0   
⚡ Learning a skill from what you described...u/   
⚡ Learning a skill from this conversation..._pending_inputz-  /learn needs an active chat session to run.)	agent.learn_promptrl  r   r-   r.   r'   r&   rm  put)r8   r   rl  r;   user_requestr  s         rA   _handle_learn_commandz&CLICommandsMixin._handle_learn_command  s     	:99999 		!!$**+.u::>>uQx~~'''r  .. 	FEFFFFDEEE4)** 	C##C(((((ABBBBBrC   c                t    ddl m} ddlm} |                                                                }t          |          dk    r
|dd         ng }t           dd          rt           j        dd          nd}|ddl	m
}  |            } ||j        || fd	
          }|d}t          |           dS )uG   Handle /memory slash command — pending review + approval-gate toggle.r   rY  r[  r   Nr   _memory_store)load_on_disk_storec                0                         d|           S )Nmemoryr^  r`  s    rA   ra  z9CLICommandsMixin._handle_memory_command.<locals>.<lambda>1  s    (A(A(G(T(T rC   )memory_storerb  zWUnknown /memory subcommand. Use: pending, approve <id>, reject <id>, approval <on|off>.)rd  rZ  re  r\  r   r-   r.   r   r   tools.memory_toolrt  MEMORYr'   )	r8   r   rZ  rh  r;   r<   r  rt  ri  s	   `        rA   _handle_memory_commandz'CLICommandsMixin._handle_memory_command  s    PPPPPP......		!!##JJNNuQRRyy>EdGUY>Z>Zd
OT:::`d= =<<<<<&&((E''ItTTTT
 
 

 ;QCc




rC   	subsystemr)   c                J    ddl m}  || dt          |                     dS )zLPersist <subsystem>.write_approval to config (for /memory|/skills approval).r   r  z.write_approvalN)r   r  r   )r8   r{  r)   r  s       rA   r_  z%CLICommandsMixin._save_write_approval8  s<    ))))))Y777gGGGGGrC   c                   	
 ddl mmmmm	m
mmm	 |
                                                    d          }t          |          dk     s|d         
                                s# d            d            d           d	S |d         
                                 xj        dz  c_         j        d
t          j                                        d           dt#          j                    j        d	d                                           s d           d	S  d dd	d          t                    dk    rdnd d            d             d                                          	
 fd}t-          j        |dd           }| j        <   |                                 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, prints the result to the CLI without modifying
        the active session's conversation history.
        r   )	AIAgentrQ  _accent_hexr   _maybe_remap_for_light_mode_render_final_assistant_contentset_approval_callbackset_secret_capture_callbackset_sudo_password_callbackr   r   r   z  Usage: /background <prompt>z9  Example: /background Summarize the top HN stories todayzI  The task runs in a separate session and results display here when done.Nbg_z%H%M%Sr  r  z;  (>_<) Cannot start background task: no valid credentials.u     🔄 Background task #z started: "r   r  r   rM  z  Task ID: u?     You can continue chatting — results will appear when done.
c                     j                     j                   	  j                   n# t          $ r Y nw xY w	  dKi dd         dd                             d          dd                             d          dd                             d          dd                             d          dd                             d          d	d                             d
          dd                             d          dj        dj        ddddddddj        dj        dj	        d                    d          dj
        dj        dj        dj        dj        dj        dj        d j        } d! | _        dLfd&}|| _        |                     '          }|r|                    d(d)          nd)}|s"|r |                    d*          rd+|d*          }j        r-j                                         t/          j        d,           t3                                                        d-              d.d/ d0            d1 d2            d3d d4          t5                    d4k    rd5nd) d6                                            d-              d.d/ d0           |r	 d7d8lm}  |            }|                    d9d:          } |                    d;d<                    } |                    d=d>                    }n# t          $ r	 d:}d<}d>}Y nw xY w             }	|	                    t?           |j         ?          d-| d@| dA dBdC||tB          j"        dD#                                E                     n dF           j$        r=tJ          j&        '                    dG           tJ          j&        (                                 nj# t          $ r]}
j        r-j                                         t/          j        d,           t3                        dH dI|
            Y d }
~
nd }
~
ww xY w	  d             d             d            n# t          $ r Y nw xY wj)        *                    d            j+        sd)_,        j        r-                    d7J           d S d S # 	  d             d             d            n# t          $ r Y nw xY wj)        *                    d            j+        sd)_,        j        r-                    d7J           w w xY w)MNr  api_keyruntimebase_urlproviderapi_modeacp_commandr   acp_argsr<   
max_tokensr  r  
quiet_modeTverbose_loggingFr   r  r   
session_dbr  service_tierrequest_overridesproviders_allowedproviders_ignoredproviders_orderprovider_sortprovider_require_parametersprovider_data_collectionopenrouter_min_coding_scorefallback_modelc                     d S r  r   )_a_kws     rA   ra  zUCLICommandsMixin._handle_background_command.<locals>.run_background.<locals>.<lambda>  s     rC   r   r   r   r   c                l    j         s)| _        j        rj                                         d S d S d S r  )r   _spinner_textr   
invalidate)r   r8   s    rA   _bg_thinkingzYCLICommandsMixin._handle_background_command.<locals>.run_background.<locals>._bg_thinking  sN    . 3-1*9 3 I00222223 33 3rC   )user_messagetask_idfinal_responser   r   zError: g?rK  rL  ux   ────────────────────────────────────────[/]u     ✅ Background task #z	 completez  Prompt: "r   r  rM  r   )get_active_skinresponse_labelu
   ⚕ Hermesresponse_borderz#CD7F32banner_textz#FFF8DC)rT  z bold]z (background #z)[/]left)r      )r!  title_alignborder_stylestyler   paddingwidthz  (No response generated)u     ❌ Background task #z	 failed: )min_intervalr   )r   r   r   r   )._sudo_password_callback_approval_callback_secret_capture_callbackr   r2   r  r  r-  r  r  _providers_only_providers_ignore_providers_order_provider_sort_provider_require_params_provider_data_collection_openrouter_min_coding_score_fallback_model	_print_fnthinking_callbackrun_conversationr   r  r1  r4  r'   r.   hermes_cli.skin_enginer  get_branding	get_colorr   final_response_markdownrich_boxHORIZONTALS_scrollback_box_widthbell_on_completesysstdoutwriteflush_background_taskspopr   r  _invalidate)bg_agentr  r?   responser  _skinrT   _resp_color
_resp_text_chat_consoler   r~  rQ  r  r   r  r  r  r8   r  r  r  r  task_num
turn_routes              rA   run_backgroundzCCLICommandsMixin._handle_background_command.<locals>.run_background\  s   &&t'CDDD!!$"9:::++D,IJJJJ   o5"7   $W--&y155i@@@ (	266zBBB (	266zBBB	
 (	266zBBB !+9 5 9 9) D D D (	266v>>>  *)488FFF $(>> &*%:%:  $t %*E  'w #U  $//  &*%:%:!" "&!2!2#$ '1nn5H&I&I&I%& '+&:&:'( '+&<&<)* %)$9$9+, #'"5"5-. 150M0M/0 .2-K-K12 150Q0Q34 $(#7#75: &=%<"3 3 3 3 3 3 .:*!22!'# 3  
 @FM6::&6;;;2 ;F ;vzz'/B/B ;:::H
 9 %I((***Jt$$$##$G$G$G
$G$G$GHHHE(EEEFFFYvcrc{YS[[2=M=MEESUYYYZZZ##$G$G$G
$G$G$GHHH 9	/JJJJJJ / 1 1 % 2 23C\ R R&A&A%//RcenBoBo&p&p%@%@Q^`iAjAj%k%k

$ / / / ,&/%.


/
 %0KMMM!''77tGcdddX+XXUXX(XXX$*%0($0 &"88::	) 	) 	) 	 	 	 	 G7888 ( 'J$$T***J$$&&& J J J9 %I((***Jt$$$H(HHQHHIIIIIIIIJ..t444))$/////5555    D&**7D999* ,)+D&9 5$$!$444445 5..t444))$/////5555    D&**7D999* ,)+D&9 5$$!$44445s   4 
A AJ P &A$M 
P MP MB=P T 
R&AQ>9T >RT !R) )
R65R6U?!T'&U?'
T41U?3T44AU?Tzbg-task-)rt  daemonr   )r   r~  rQ  r  r   r  r  r  r  r  r   r-   r.   _background_task_counterr   r  r  r  r  r  _ensure_runtime_credentials_resolve_turn_agent_config	threadingThreadr  start)r8   r   r;   r  threadr~  rQ  r  r   r  r  r  r  r  r  r  r  r  s   `    @@@@@@@@@@@@@rA   _handle_background_commandz+CLICommandsMixin._handle_background_command=  s    	Q  	Q  	Q  	Q  	Q  	Q  	Q  	Q  	Q  	Q  	Q  	Q  	Q  	Q  	Q  	Q  	Q  	Q  	Q  	Q  	Q  	Q		!!1!--u::>>q!1!1>G3444GOPPPG_```Fq!!%%*%%0R//99RRDJLL<LRaR<PRR //11 	GQRRRFs8sssWZ[aWbWbegWgWgeemosssttt'g''(((RSSS44V<<
v	5 v	5 v	5 v	5 v	5 v	5 v	5 v	5 v	5 v	5 v	5 v	5 v	5 v	5 v	5 v	5 v	5 v	5p !K_V]K_K_```*0w'rC   c                   ddl m}m}m}m}m}m} 	 ddlm}m	}	 n(# t          $ r}
 |d|
 |            Y d}
~
dS d}
~
ww xY w |            }|s9 |d            |d| d|             |d| d	 |	             |            dS  |d
| d| dt          |           d           |D ]}t          |                    dg                     }|                    d          pd| d} |                                d |             d|d         ddt          |           d| d	           |                    dg           D ]0} |                                dt          |           d           1 |d| d|            dS )u  In-session ``/bundles`` — show installed skill bundles.

        Mirrors ``hermes bundles list`` but renders inside the running
        CLI so users can discover what's available without dropping out
        of their session. Bundles are loaded via ``/<bundle-name>``.
        r   )rQ  _BOLDr   r   r  r   )list_bundles_bundles_dirz%[1;31mBundle subsystem unavailable: Nz  No skill bundles installed.rL   zGCreate one with: hermes bundles create <name> --skill <s1> --skill <s2>zDirectory: u   
  ▣ zSkill Bundlesrb  z installed):r  r  zLoad z skillsz
    [bold z]/r  z<20z[/] [dim]-[/] z [dim](z skills)[/]u           [dim]· r  z
  z;Invoke a bundle with /<slug>. Manage with `hermes bundles`.)r   rQ  r  r   r   r  r   agent.skill_bundlesr  r  r   r.   r2   r'   _escape)r8   r   rQ  r  r   r   r  r   r  r  r   bundlesinfoskill_countdescrj   s                   rA   _handle_bundles_commandz(CLICommandsMixin._handle_bundles_command  s    	MLLLLLLLLLLLLLLL	FFFFFFFFF 	 	 	GJsJDJJKKKFFFFF	 ,.. 	G3444G:T : :37: :   G@@@,,..@$@@AAAFQ5QQtQQs7||QQQRRR 	H 	HDdhhx4455K88M**J.Jk.J.J.JDKMML[[]] L Ld6lD L L$T]]L L3>L L L   XXh++ H H##$Fwqzz$F$F$FGGGGH34 3 3,03 3	
 	
 	
 	
 	
s    
A ;A c                   ddl }|                                                    dd          }t          |          dk    r,|d                                                                         nd}t
          }t          j                            dd                                          }|	                    d          r	|                                                    dd          }t          |          dk    r|d                                         n|}t          d	|v r|nd
|           }	|	j        dvr8t                       t          d|	j        pd d           t                       dS 	 |	j        p|	j        dv rdnd}
n?# t          $ r2 t                       t          d|            t                       Y dS w xY w|	j        s0t                       t          d|            t                       dS |	j        }|	j        	                    d          r|	                                }n+|	                    dddd                                          }	 ddlm}  |             n# t*          $ r Y nw xY wt                       t-          |d          }|rt          d|
            nI||k    r-t          d           t/          |
|                                          }|j        rst5          d          D ]+}t-          |d          rd} nt7          j        d           ,|rt          d|
            nt          d|
 d            t          d!           nt          d"           |j        }|rt          d#|            |                                }t=          |
|          }|r"t          d$           t          d#|            n%t          d%           nt          d&|
 d'|            |s-t                       t          d(           t                       dS |t          j        d<   	 dd)lm}  |d*           n# t*          $ r Y nw xY wt                       t          d+           t          d,|            t                       tA          | d-          r| j!        "                    d.           dS dS |d/k    r|rt          j        #                    dd           	 dd0lm}m$}  |d*            |             n# t*          $ r Y nw xY wt                       t          d1           t          d2           t                       tA          | d-          r| j!        "                    d3           dS dS t                       t          d4           t                       dS |dk    r/t                       |rt          d5           t          d,|            d6}
	 tK          |&                    d7d          d8                             d9          d                   }
n# t          tN          f$ r Y nw xY w	 ddl(}|(                    |j)        |j*                  }|+                    d           |,                    d:|
f           |-                                 t          d;           n# t\          t*          f$ r t          d<           Y nw xY w	 dd=lm/}  |            }n# t*          $ r d}Y nw xY w|&t          d>|0                                 d?           n}	 dd@lm1}  |            }n# t*          $ r dA}Y nw xY w|dBk    r.t          dC           t          dD           t          dE           n%|dFk    rt          dG           nt          dH           t                       t          dI           t          dJ           t                       dS t                       t          dK           t                       t          dL           t          dM           t          dN           t                       dS )OuY   Handle /browser connect|disconnect|status — manage live Chromium-family CDP connection.r   Nr   ru   BROWSER_CDP_URLr   connectr   z://zhttp://>   wswsshttphttpsu'      ⚠ Unsupported browser url scheme: z	(missing)z( (expected one of: http, https, ws, wss)>   r  r  i  r   u$      ⚠ Invalid port in browser url: u$      ⚠ Missing host in browser url: z/devtools/browser/)pathparamsqueryfragment)cleanup_all_browsersg      ?)timeoutu<      ✓ Chromium-family browser is already listening on port uZ      Chromium-family browser isn't running with remote debugging — attempting to launch...rP  Tr&  u>      ✓ Chromium-family browser launched and listening on port u!      ⚠ Browser launched but port z isn't responding yetuL        Try again in a few seconds — the debug instance may still be startingu6      ⚠ Could not auto-launch a Chromium-family browserz     z/     Launch a Chromium-family browser manually:zN     No supported Chromium-family browser executable found in this environmentu      ⚠ Port z is not reachable at uj   Browser not connected — start a Chromium-family browser with remote debugging and retry /browser connect)_ensure_cdp_supervisorr  u>   🌐 Browser connected to live Chromium-family browser via CDPz   Endpoint: rm  a  [System note: The user invoked /browser connect and connected your browser tools to a Chromium-family dev/debug browser via Chrome DevTools Protocol. Your browser_navigate, browser_snapshot, browser_click, and other browser tools now control that CDP browser. The command itself is a signal that using browser tools for their current browser-related request is expected; do not wait for separate permission just because CDP is connected. This is typically a Hermes-managed isolated debug profile, not the user's main everyday browser. It is still user-visible and may contain pages, logged-in sessions, or cookies in that debug profile, so avoid destructive actions, closing tabs, or navigating away unless the user's task calls for it.]
disconnect)r  _stop_cdp_supervisoru;   🌐 Browser disconnected from live Chromium-family browserzL   Browser tools reverted to default mode (local headless or cloud provider)z[System note: The user has disconnected the browser tools from their live Chromium-family browser. Browser tools are back to default mode (headless local browser or cloud provider).]zWBrowser is not connected to a live Chromium-family browser (already using default mode)u?   🌐 Browser: connected to live Chromium-family browser via CDPi$  r  rI  rK  z	127.0.0.1u      Status: ✓ reachableu9      Status: ⚠ not reachable (browser may not be running))_get_cloud_provideru   🌐 Browser: z (cloud))_get_browser_engineauto
lightpandauB   🌐 Browser: local Lightpanda (agent-browser --engine lightpanda)u;      ⚡ Lightpanda: faster navigation, no screenshot supportzB   Automatic Chromium fallback for screenshots and failed commandschromeuE   🌐 Browser: local headless Chromium (agent-browser --engine chrome)u5   🌐 Browser: local headless Chromium (agent-browser)uI      /browser connect      — connect to your live Chromium-family browseru.      /browser disconnect   — revert to defaultz)Usage: /browser connect|disconnect|statuszR   connect      Connect browser tools to your live Chromium-family browser sessionz1   disconnect   Revert to default browser backendz)   status       Show current browser mode)2r  r   r-   r.   r0   r   r*   r  r2   r  r   schemer'   portrf   hostnamer  geturl_replacetools.browser_toolr  r   r   r   systemlaunchedranger1  r4  r   r   r  r&   rm  ro  r  r  re   rsplit
IndexErrorsocketAF_INETSOCK_STREAM
settimeoutr  closeOSErrorr  provider_namer  )r8   r   _platr;   r  _DEFAULT_CDPrB  connect_partscdp_url
parsed_cdp_port_hostr  _already_open_launch_wait_hintsys_name
chrome_cmdr  r  r  rj   r  r  r  engines                              rA   _handle_browser_commandz(CLICommandsMixin._handle_browser_command  s	       		!!$***-e**q..eAhnn$$&&&h.*..!2B77==??>>)$$ C	IIKK--dA66M25m2D2Dq2H2HmA&,,...lG!Ug-=-=''CVWCVCVWWJ (FFF>j>O>^S^ > > >   "a:3DHX3X3XCC^`   FWFFGGG	
 & FWFFGGG'E))*>?? $++--$--	 .  
 &(( CCCCCC$$&&&&    GGG 37CHHHM L\UZ\\]]]]L((rsss-eU\\^^DD# p!&r ( (1'3GGG ",0M!E
3$ nf_dffgggg^%^^^___lmmmmRSSS#LE /oeoo...$||~~H!<UH!M!MJ! pOPPP2j223333nooooJUJJJJKKK    C  D  D  D,3BJ()EEEEEE&&y1111   GGGRSSS+'++,,,GGG t-.. #'']
 
 
 
 
  L   
0$777]]]]]]]]((333((****    DSTTTdeee4!122 '++n      opppH__GGG )WWXXX/g//000sA 6 6r : @ @ E Ea HIIEE"J/   DW!MMMfnf6HIIALLOOOII{E2333GGIII45555+ W W WUVVVVVW$FFFFFF2244HH  $ $ $#HHH$ 'M8+A+A+C+CMMMNNNN(JJJJJJ!4!4!6!6$ ( ( (!'(--bccc[\\\bcccc8++effffUVVVGGG]^^^BCCCGGGGG GGG=>>>GGGfgggEFFF=>>>GGGGGs   .F 8F?>F?I, ,
I98I99Q 
QQ/T 
TT.AX1 1YY	A3Z= = [ [ $[5 5\\0] ]]c                
   ddl m}m}m} |pd                                                    dd          }t          |          dk    r|d                                         nd}|                                 }| |d| d|            dS |                                }|r|dk    r" |d|	                                            dS |d	k    rB |d|	                                             |d|
                                            dS |                    d
          rO|t          d
          d                                         }	|	s |d           dS |                     |	           dS |dk    r?|                    d          }
|
 |d| d|            n |d|
j                    dS |dk    rN|                                }
|
 |d| d|            n$ |d|
j                     |d| d|            dS |dv rI|                                }|                                 |r |d           n |d| d|            dS |dk    s|                    d          r|t          d          d                                         }|s |d           dS |                    dd          }	 t%          |d                   }n# t&          $ r  |d           Y dS w xY wt          |          dk    r|d                                         nd}	 |                    ||           n-# t*          t&          f$ r} |d|            Y d}~dS d}~ww xY w|rd| dnd} |d| | d            dS |d!k    r3|                                r |d"           n |d| d#|            dS dd$lm}  ||          \  }}|p|}	 |                    ||                                s|nd%          }
n&# t&          $ r} |d&|            Y d}~dS d}~ww xY w |d'|
j         d(|
j                    |
                                rM |d| d)|            |
j                                                                        D ]} |d*|             |d| d+|
                                rd,nd d-|            	 | j         !                    |
j                   dS # tD          $ r Y dS w xY w).zQDispatch /goal subcommands: set / draft / show / status / pause / resume / clear.r   r   r   r   r   Nr   rL   &Goals unavailable (no active session).ru   showdraftz2  Usage: /goal draft <objective in plain language>r)  zuser-pausedr   zNo goal set.u     ⏸ Goal paused: rO  zNo goal to resume.u     ▶ Goal resumed: z`Send any message (or press Enter on an empty prompt is a no-op; type 'continue' to kick it off).>   donestopclearu     ✓ Goal cleared.zNo active goal.waitzwait z"  Usage: /goal wait <pid> [reason]z2  /goal wait: <pid> must be an integer process id.z  /goal wait: rb  r  u     ⏳ Goal parked on pid z. Loop pauses until it exits.unwaitu1     ▶ Wait barrier cleared — goal loop resumes.zNo wait barrier set.)parse_contractcontract  Invalid goal:      ⊙ Goal set (-turn budget): zCompletion contract:r   z9After each turn, a judge model checks if the goal is donez against the contract abovez. Hermes keeps working until it is, you pause/clear it, or the budget is exhausted. Use /goal status, /goal show, /goal pause, /goal resume, /goal clear.)#r   r   r   r   r   r-   r.   _get_goal_managerr0   status_linerender_contractr  _handle_goal_draftr)  r   rO  has_goalr+  re   rf   wait_onRuntimeErrorstop_waitinghermes_cli.goalsr.  r-  is_emptyr  has_contractr0  render_blockr3   rm  ro  r   )r8   r   r   r   r   r;   r   r9   r0   	objectiver#  hadwait_argwtokenspidr#   r   rtxtr.  headliner0  	goal_textr   s                          rA   _handle_goal_commandz%CLICommandsMixin._handle_goal_command  s   ++++++++++!!##))$22"%e**q..eAhnnb$$&&;GKKKTKKLLLF		  	ex''G,**,,---F F??G,**,,---G0,,..00111F G$$ 	CLLMM*0022I LMMM##I...FGII]I33E}5T55t556666:ej::;;;FHJJLLE};T;;T;;<<<<;uz;;<<<J J JCGJ J   F---,,..CIIKKK :-....8T88$88999F
 F??e..w77?3v;;<<(..00H <===nnT1--G'!*oo   LMMM ,/w<<!+;+;WQZ%%'''FC//// *-   .../// &,3>>>>>DGXXTXXXYYYF H!! ?KLLLL=T==t==>>>F 	433333+^C00(O		GGI@Q@Q@S@S0]Y]G^^EE 	 	 	G,s,,---FFFFF	 	O5?OO5:OOPPP 	'G999499:::3355@@BB ' 't&&&&f f f050B0B0D0DL,,"f f `df f	
 	
 	
	##EJ///// 	 	 	DD	sT   K K76K7*M M,M''M,-P 
P/P**P/S: :
TTr@  c                h   ddl m}m}m} ddlm} |                                 }| |d| d|            dS  |d| d|            	  ||          }nK# t          $ r>}ddl}	|		                    t                                        d|           d}Y d}~nd}~ww xY w	 |                    ||	          }
n&# t          $ r} |d
|            Y d}~dS d}~ww xY w |d|
j         d|
j                    |
                                r_ |d| d|            |
j                                                                        D ]} |d|             |d| d|            n |d| d|            	 | j                            |
j                   dS # t          $ r Y dS w xY w)zDraft a structured completion contract from a plain objective and
        set it as the active goal. Falls back to a bare goal if the aux model
        can't produce a contract.r   r%  )draft_contractNrL   r&  u   Drafting completion contract…zgoal draft failed: %sr/  r1  r2  r3  zDrafted completion contract:r   zTighten any field by re-setting the goal with inline lines (e.g. verify: <command>), then /goal resume. Use /goal show to review.ut   Couldn't draft a contract (aux model unavailable) — running as a free-form goal. The per-turn judge still applies.)r   r   r   r   r<  rJ  r4  r   logging	getLoggerr   debugr-  rf   r  r   r>  r0  r?  r3   rm  ro  )r8   r@  r   r   r   rJ  r9   r0  r   _loggingr#  r   s               rA   r7  z#CLICommandsMixin._handle_goal_draftP  s    	,+++++++++333333$$&&;GKKKTKKLLLF@T@@$@@AAA	%~i00HH 	 	 	&&&&x((../FLLLHHHHHH	
	GGIG99EE 	 	 	G,s,,---FFFFF	 	O5?OO5:OOPPP 	GAAA4AABBB3355@@BB ' 't&&&&G3T 3 3,03 3    GXT X XQUX X  	##EJ///// 	 	 	DD	sB   A 
B "4BB $B< <
CCCF# #
F10F1c                   ddl m}m}m} |pd                                                    dd          }t          |          dk    r/d                    |dd                                                   nd}|                                 }| |d| d	|            dS |	                                s |d| d
|            dS |sB |d|
                                             |d|                                            dS |                    dd          }|d                                         }	t          |          dk    r|d                                         nd}
|	dk    r|
s |d           dS 	 t          |
                                d                   }n# t          $ r  |d           Y dS w xY w	 |                    |          }n-# t           t"          f$ r} |d|            Y d}~dS d}~ww xY w |d| d|            dS |	dk    rl	 |                                }n&# t"          $ r} |d|            Y d}~dS d}~ww xY w|r |d| d|dk    rdnd d           n |d| d|            dS 	 |                    |          }n-# t          t"          f$ r} |d|            Y d}~dS d}~ww xY w|j        rt          |j        j                  nd} |d| d|            dS )u  Dispatch /subgoal subcommands.

        Forms:
          /subgoal                              show current subgoals
          /subgoal <text>                       append a criterion
          /subgoal remove <n>                   drop subgoal n (1-based)
          /subgoal clear                        wipe all subgoals

        Subgoals are extra criteria the user adds mid-loop. They get
        appended to both the judge prompt (verdict must consider them)
        and the continuation prompt (agent sees them) on the next turn
        boundary. No special kick — the running turn finishes, the next
        judge call includes them.
        r   r%  r   Nr   r   rO   rL   r&  z*No active goal. Set one with /goal <text>.r*  z  Usage: /subgoal remove <n>z:  /subgoal remove: <n> must be an integer (1-based index).z  /subgoal remove: u     ✓ Removed subgoal r"   r+  z  /subgoal clear: u     ✓ Cleared z subgoalrj   r]   zNo subgoals to clear.z  /subgoal: u     ✓ Added subgoal )r   r   r   r   r   r-   r.   r4   r4  r8  r5  render_subgoalsr0   re   rf   remove_subgoalr  r:  clear_subgoalsadd_subgoalr#  subgoals)r8   r   r   r   r   r;   r   r9   r  r  r   rn   r3  r   prevr   s                   rA   _handle_subgoal_commandz(CLICommandsMixin._handle_subgoal_command~  s    	,+++++++++!!##))$22-0ZZ!^^chhuQRRy!!'')))$$&&;GKKKTKKLLLF||~~ 	GOOOOOPPPF  	G,**,,---G0,,..00111F4##ay  $'KK!OOvay   8 6777$**,,q/**   TUUU,,S11-   3c33444 G=S==G==>>>F7??))++   2S22333  @RRRdaiissRRRRSSSS>T>>>>???F	??3''DDL) 	 	 	G(3(()))FFFFF	 *-9c#)$%%%4s44d4455555sZ   'F* *GGG H.HH$H9 9
IIIJ& &K7KKc                   ddl m}m} 	 ddlm}m}m} n # t          $ r t          d           Y dS w xY w|	                                
                    d          }t          |          dk     s|d         	                                s |            } |            }	t          d	|            t          d
           |	D ]R}
|
d         |k    rdnd}|
d         dk    rd|
d          dnd}t          d| d|
d          | d|
d                     St          d           t          dt                       d           dS |d         	                                                                }d  |            D             }||vrFt          d|            t          dd                    t          |                                dS  ||           |                                  |d|          rt          d| d            nt          d|            t          d!           |                                 rt          d"           dS dS )#u8   Handle /skin [name] — show or change the display skin.r   )r   r  )
list_skinsset_active_skinget_active_skin_namezSkin engine not available.Nr   r   r   z
  Current skin: z  Available skins:r   u    ●rL   r  r`  rb  r  r   z   rO   u    — r  z
  Usage: /skin <name>z$  Custom skins: drop a YAML file in z/skins/
c                    h | ]
}|d          S )r   r   )ry   rj   s     rA   	<setcomp>z8CLICommandsMixin._handle_skin_command.<locals>.<setcomp>  s    5551QvY555rC   z  Unknown skin: z  Available: r  zdisplay.skinz  Skin set to: z (saved)z8  Note: banner colors will update on next session start.z  Prompt + TUI colors updated.)r   r   r  r  rX  rY  rZ  ImportErrorr'   r   r-   r.   r	   r0   r4   sortedr]  _apply_tui_skin_style)r8   r   r   r  rX  rY  rZ  r;   rB  skinsrj   markerr  new_skin	availables                  rA   _handle_skin_commandz%CLICommandsMixin._handle_skin_command  s   22222222	``````````` 	 	 	.///FF	 		!!1!--u::>>q!1!1>**,,GJLLE0w00111&''' Q Q#$V9#7#7T01(v0E0E,ak,,,,2OFOOQvYOOOQ}=MOOPPPP+,,,Y9L9N9NYYYZZZF8>>##))++55

555	9$$/X//000@$))F9,=,=">">@@AAAF!!! ^X66 	06H6667777.H..///HIII%%'' 	4233333	4 	4s   
 22r   initial_textc                   ddl }ddl}ddl}ddl}|j                            d          p|j                            d          }|s|j        dk    rdnd}d}|                    d	d
          \  }}		  |j        |dd          5 }
|
	                    |           |r|
	                    |           ddd           n# 1 swxY w Y   	 |
                    g |                    |          |	           n?# t          $ r2 |
                    | d|                    |	           d           Y nw xY wt          |	dd          5 }
|
                                }ddd           n# 1 swxY w Y   	  |j        |	           n6# t"          $ r Y n*w xY w# 	  |j        |	           w # t"          $ r Y w w xY wxY wd |                                D             }d                    |                                          S )aw  Open ``$VISUAL``/``$EDITOR`` on a temp markdown file and return the
        saved buffer (comment lines starting with ``#!`` stripped).

        Returns the composed prompt text, or an empty string if the editor
        could not be launched or the buffer was left empty. Factored out so
        the read-back/strip logic is unit-testable without spawning an editor.
        r   NVISUALEDITORntnotepadnanozv#! Compose your prompt below. Lines starting with '#!' are ignored.
#! Save and quit to send; leave empty to cancel.

z.mdhermes_prompt_)r   prefixr  zutf-8)encodingrO   T)shellrc                <    g | ]}|                     d           |S )z#!)r  )ry   lns     rA   r{   z7CLICommandsMixin._compose_in_editor.<locals>.<listcomp>	  s)    JJJbmmD6I6IJJJJrC   r   )r*   r   
subprocesstempfiler  r2   r   mkstempfdopenr  callr-   r   r=  openreadunlinkr  r3   r4   r   )r8   re  r*   r   rs  rt  editorheaderfdr  fhrawliness                rA   _compose_in_editorz#CLICommandsMixin._compose_in_editor  s    				))ERZ^^H-E-E 	>"$'T//YYvFC 	 ##59I#JJD	2sW555 +    +HH\***+ + + + + + + + + + + + + + +M <%++f"5"5 <t <==== M M M 6 ? ?EKK,=,= ? ?tLLLLLM dC'222  bggii                             	$   	$    KJcnn..JJJyy%%'''s   3F -B?3F ?CF CF ,C8 7F 89D41F 3D44F 	E*F *E..F 1E.2F 6F 
FFF:F*)F:*
F74F:6F77F:c                d   ddl m}m}m} d}|pd                                                    dd          }t          |          dk    r|d         }	 |                     |          }n+# t          $ r} |d| d| |            Y d}~dS d}~ww xY w|s |d| d|            dS || _	        dS )	uw  Handle /prompt — compose the next prompt in $EDITOR and send it.

        Opens the user's editor on a temporary markdown file (optionally
        seeded with text passed after the command), then queues the saved
        buffer as the next agent turn via the one-shot ``_pending_agent_seed``
        the interactive loop already consumes (same path as /blueprint).
        r   r%  r   Nr   rL   z(>_<) Could not open editor: u$   (._.) Empty prompt — nothing sent.)
r   r   r   r   r   r-   r.   r  r   rB  )	r8   r   r   r   r   initialr;   composedr   s	            rA   _handle_prompt_compose_commandz/CLICommandsMixin._handle_prompt_compose_command!	  s    	,+++++++++#**,,224;;u::>>AhG	..w77HH 	 	 	GGGGCGGGHHHFFFFF	  	GIII4IIJJJF $,   s   A) )
B3BBc                t   ddl m}m} ddlm} ddlm} d}	 |pd                                                    dd          }t          |          dk    r,|d                                         
                                }n# t          $ r d}Y nw xY w |            pi }|                    d          pi                     d	          pi }	t          |	                    d
d                    }
|	                    d          pg d}|dv r<|
rdnd} |d|j         d|j         d| dd                    |                      dS |dv rd}n|dv rd}n|dk    r|
 }n |d           dS  |d|          r4|r|j         d|j         n|j         d|j         } |d|            dS  |d           dS )u   Toggle or inspect ``display.runtime_footer.enabled`` from the CLI.

        Usage:
            /footer           → toggle
            /footer on|off    → explicit
            /footer status    → show current state
        r   r   r  r
  Colorsr   Nr   r  runtime_footerr)   Ffields)r  context_pctr:   >   r   ru   ONOFFrL   zRuntime footer:rO   z
  Fields: r  >   1ontruer   T>   0r  falser  z   Usage: /footer [on|off|status]zdisplay.runtime_footer.enabledz  Runtime footer: z6  Failed to save runtime_footer setting to config.yaml)r   r   r  r  r  hermes_cli.colorsr  r   r-   r.   r0   r   r2   r   BOLDRESETr4   GREENDIM)r8   r   r   r  r  _Colorsr   r;   cfg
footer_cfgrB  r  r#  	new_states                 rA   _handle_footer_commandz'CLICommandsMixin._handle_footer_command>	  s    	32222222111111777777 	!'R..0066tQ??E5zzA~~Ahnn&&,,.. 	 	 	CCC	 kmm!rwwy))/R445EFFL"
z~~i7788))L-L-L-L/!!#.DDEG1W\ 1 1'- 1 1% 1 1!YYv..1 1   F///II444IIBYY#IIG6777F=yII 	N7@ 87=33GM3337777  G00011111GLMMMMMs   A)B BBc                   ddl m}m} ddlm} d}	 |pd                                                    dd          }t          |          dk    r,|d                                                                         }n# t          $ r d}Y nw xY wt          t          | dd                    }|d	v r&|rd
nd} |d|j         d|j         d|            dS |dv rd}	n|dv rd}	n|dk    r| }	n |d           dS |	| _         |d|	          r4|	r|j         d
|j         n|j         d|j         } |d|            dS  |d           dS )u  Toggle or inspect ``display.timestamps`` from the CLI.

        When on, submitted and streamed message labels carry an ``[HH:MM]``
        suffix and ``/history`` prefixes each turn with its time (for turns
        that carry a stored timestamp).

        Usage:
            /timestamps           → toggle
            /timestamps on|off    → explicit
            /timestamps status    → show current state
        r   r  r  r   Nr   show_timestampsF>   r   ru   r  r  rL   zMessage timestamps:rO   >   r  r  r  r   T>   r  r  r  r  z$  Usage: /timestamps [on|off|status]zdisplay.timestampsz  Message timestamps: z2  Failed to save timestamps setting to config.yaml)r   r   r  r  r  r   r-   r.   r0   r   r   r   r  r  r  r  r  )
r8   r   r   r  r  r   r;   rB  r#  r  s
             rA   _handle_timestamps_commandz+CLICommandsMixin._handle_timestamps_commands	  s    	32222222777777	!'R..0066tQ??E5zzA~~Ahnn&&,,.. 	 	 	CCC	 wt%6>>??/!!#.DDEGQQQ'-QQ%QQRRRF///II444IIBYY#IIG:;;;F(19== 	J7@ 87=33GM3337777  G4U4455555GHIIIIIs   A)A< <B
Bc           
        ddl m}m}m}m}m}m} |                                                    d          }t          |          dk     r| j
        }	|	d}
n0|	                    d          d	u rd
}
n|	                    dd          }
| j        rdnd}t          | dd	          rdnd} |d| d|
 |             |d| d| d| d|             |d| d|            dS |d                                                                         }|dv r\d| _        | j        r|                                 | j        _         |dd            |d| d|             |d| d|            dS |dv rKd	| _        | j        r|                                 | j        _         |dd	            |d| d|            dS |dv rOd| _         |d d            |d| d!|             |d| d"|            | j        s |d| d#|            dS |d$v r&d	| _         |d d	            |d| d%|            dS  ||          }|7 |d| d&| |             |d| d'|             |d| d(|            dS || _
        d| _         |d)|          r |d| d*| d+|            dS  |d| d*| d,|            dS )-uB  Handle /reasoning — manage effort level and display toggle.

        Usage:
            /reasoning              Show current effort level and display state
            /reasoning <level>      Set reasoning effort (none, minimal, low, medium, high, xhigh)
            /reasoning show|on      Show model thinking/reasoning in output
            /reasoning hide|off     Hide model thinking/reasoning from output
            /reasoning full         Show complete thinking (no 10-line clamp)
            /reasoning clamp        Collapse long thinking to the first 10 lines
        r   )r   r   r   r   _parse_reasoning_configr  r   r   r   Nzmedium (default)r)   Fznone (disabled)effortmediumu   on ✓r  reasoning_fullfullzclamped to 10 linesrL   zReasoning effort:  zReasoning display: rb  r  zKUsage: /reasoning <none|minimal|low|medium|high|xhigh|show|hide|full|clamp>>   r  r'  Tzdisplay.show_reasoningu!   ✓ Reasoning display: ON (saved)z>  Model thinking will be shown during and after each response.>   r  hideu"   ✓ Reasoning display: OFF (saved)>   r  r  zdisplay.reasoning_fullu#   ✓ Reasoning display: FULL (saved)z;  The post-response recap box will print complete thinking.uC     Note: reasoning display is OFF — run /reasoning show to see it.>   clampshortcollapseu2   ✓ Reasoning display: CLAMPED to 10 lines (saved)(._.) Unknown argument: z5Valid levels: none, minimal, low, medium, high, xhighzDisplay:      show, hidezagent.reasoning_effortu   ✓ Reasoning effort set to 'r  r  )r   r   r   r   r   r  r  r   r-   r.   r  r2   show_reasoningr   r0   r   _current_reasoning_callbackreasoning_callbackr  )r8   r   r   r   r   r   r  r  r;   rcleveldisplay_state
full_stater   parseds                  rA   _handle_reasoning_commandz*CLICommandsMixin._handle_reasoning_command	  sk    	a```````````````		!!1!--u::>>&Bz*	""e++)x22(,(;FHHM#*41A5#I#IdOdJGBBBUBDBBCCCGYYY]YYjYYSWYYZZZGpppjnppqqqFAhnn$$&& .  "&Dz S040P0P0R0R
-6===GIII4IIJJJGccc]accdddF/!!"'Dz S040P0P0R0R
-6>>>GJJJDJJKKKF /!!"&D6===GKKKTKKLLLG```Z^``aaa& nlTllfjllmmmF000"'D6>>>GZZZTXZZ[[[F )(-->GBBBsBDBBCCCGZZZTXZZ[[[G===t==>>>F &
5s;; 	\G]]]s]]W[]]^^^^^GZZZsZZTXZZ[[[[[rC   c                "   ddl m}m}m}m}m} |                                                    d          }t          |          dk     s0|d                                         	                                dk    r\ |d| d| j
         |            | j
        d	k    rd
}n| j
        dk    rd}nd} |d| d| |             |d| d|            dS |d                                         	                                }	|	dvr& |d| d|	 |             |d| d|            dS |	| _
         |d|	          r<|	d	k    rd}
n|	dk    rd}
nd}
 |d| d|	 d|             |d| |
 |            dS  |d| d|	 d|            dS )u  Handle /busy — control what Enter does while Hermes is working.

        Usage:
            /busy               Show current busy input mode
            /busy status        Show current busy input mode
            /busy queue         Queue input for the next turn instead of interrupting
            /busy steer         Inject Enter mid-run via /steer (after next tool call)
            /busy interrupt     Interrupt the current run on Enter (default)
        r   r   r   r   r   r  r   r   r   ru   rL   zBusy input mode: queuezqueues for next turnsteerz.steers into current run (after next tool call)zinterrupts current runzEnter while busy: z+Usage: /busy [queue|steer|interrupt|status]N>   r  r  	interruptr  zdisplay.busy_input_modez6Enter will queue follow-up input while Hermes is busy.zNEnter will steer your message into the current run (after the next tool call).z:Enter will interrupt the current run while Hermes is busy.u   ✓ Busy input mode set to 'r  r  )r   r   r   r   r   r  r   r-   r.   r0   busy_input_mode)r8   r   r   r   r   r   r  r;   	_behaviorr   behaviors              rA   _handle_busy_commandz%CLICommandsMixin._handle_busy_command	  sb    	HGGGGGGGGGGGGG		!!1!--u::>>U1X^^--3355AAGOOO43GOOOPPP#w..2		%00L		4	GBBBBDBBCCCGPPP$PPQQQFAhnn$$&&555GBBBsBDBBCCCGPPP$PPQQQF"6<< 
	[g~~SkWG\\\c\\VZ\\]]]G//x///00000GYYYcYYSWYYZZZZZrC   c           
        ddl m}m}m}m}m} |                                 s |d           dS 	 ddlm} t          | dd          }t          |dd          pt          | dd          }	 ||	          rdnd	}
n# t          $ r d
}
Y nw xY w|                                                    d          }t          |          dk     s0|d                                                                         dk    r7| j        dk    rdnd} |d| |
 d| |             |d| d|            dS |d                                                                         }|dv rd| _        d}d}n6|dv rd| _        d}d}n& |d| d| |             |d| d|            dS d| _         |d|          r |d| d|
 d| d|            dS  |d| d|
 d| d|            dS )uU   Handle /fast — toggle fast mode (OpenAI Priority Processing / Anthropic Fast Mode).r   r  zv  (._.) /fast is only available for models that support fast mode (OpenAI Priority Processing or Anthropic Fast Mode).N)_is_anthropic_fast_modelr   r  zAnthropic Fast ModezPriority Processingz	Fast moder   r   r   ru   priorityfastnormalrL   r"   z!Usage: /fast [normal|fast|status]>   r  r  FAST>   r  r  NORMALr  zagent.service_tieru   ✓ z set to z (saved to config)z (session only))r   r   r   r   r   r  _fast_command_availablehermes_cli.modelsr  r   r   r   r-   r.   r0   r  r   )r8   r   r   r   r   r   r  r  r   r  feature_namer;   ru   r   saved_valuerT   s                   rA   _handle_fast_commandz%CLICommandsMixin._handle_fast_command 
  s   GGGGGGGGGGGGGG++-- 	G  M  N  N  NF	'BBBBBBD'400EE7D11QWT7D5Q5QE4L4LU4S4Sn00YnLL 	' 	' 	'&LLL	' 		!!1!--u::>>U1X^^--3355AA#0J>>VVHFG@@,@@&@$@@AAAGFFFFFGGGFAhnn$$&&.   *D KEE%%% $D"KEEGBBBsBDBBCCCGFFFFFGGGF
1;?? 	ZG[[[l[[E[[UY[[\\\\\GXXXlXXEXXRVXXYYYYYs   AA: :B	B	c                    ddl m} ddlm} d |                                dd         D             }d|v }d|v o| } |d	d
||d          } ||           dS )u  Handle /debug — upload debug report + logs and print share URLs.

        Accepts optional destination words after the command:

        - ``/debug``        → upload to the public paste service (default)
        - ``/debug nous``   → upload to Nous-internal storage (private, staff-only)
        - ``/debug local``  → render the report to stdout, no upload

        ``nous`` and ``local`` are mutually exclusive; if both are given,
        ``local`` wins (it never touches the network).
        r   )run_debug_share)SimpleNamespacec                6    h | ]}|                                 S r   )r0   r  s     rA   r\  z9CLICommandsMixin._handle_debug_command.<locals>.<setcomp>[
  s     ===q===rC   r   Nlocalnous      T)r  expirer  r  yes)hermes_cli.debugr  typesr  r-   )r8   r   r  r  wordsr  r  r<   s           rA   _handle_debug_commandz&CLICommandsMixin._handle_debug_commandL
  s     	544444))))))==L$6$6$8$8$<===5 ,u9 au4T
 
 
 	rC   c                   ddl m}m}  |            rt          d |d                      dS ddg}|                     dd	|
          }|t          d           dS |                     ||          }|dk    rt          d           dS t                       t          d           t                       dg| _        dS )u  Handle /update — update Hermes Agent to the latest version.

        In the classic CLI this exits the session and relaunches as
        ``hermes update`` so the user sees update output directly and gets
        the new version on next launch.

        Returns ``True`` when the update was confirmed (caller should trigger
        app exit so the relaunch is deferred to the main thread after
        prompt_toolkit cleans up terminal modes).  Returns ``False`` / falsy
        when cancelled.
        r   )
is_managedformat_managed_messageu     ✗ zupdate Hermes AgentF)oncez
Update Nowz0exit the current session and update Hermes Agent)cancelCancelzkeep the current sessionu   ⚕  Update Hermes Agentz;This will exit the current session and run `hermes update`.)r!  r  choicesNu     🟡 /update cancelled.r  u     ⚕ Launching update...r%  T)r  r  r  r'   _prompt_text_input_modal_normalize_slash_confirm_choice_pending_relaunch)r8   r  r  r  r  choices         rA   _handle_update_commandz'CLICommandsMixin._handle_update_commandf
  s
    	IHHHHHHH:<< 	J112GHHJJKKK5 W<
 ++,P , 
 

 ;-...555c7CCV-...5)*** #+trC   c                h   ddl m} |                                                    d          }t	          |          dk    r,|d                                                                         nd}|dk    r|                                  dS |dk    r|                                  dS |dk    r|                                  dS |d	k    r| 	                                 dS |dk    r3| j
        r|                                  dS |                                  dS  |d
|             |d           dS )z*Handle /voice [on|off|tts|status] command.r   r   r   r   r   r  r  ttsru   zUnknown voice subcommand: z!Usage: /voice [on|off|tts|status]N)r   r   r   r-   r.   r0   _enable_voice_mode_disable_voice_mode_toggle_voice_tts_show_voice_status_voice_mode)r8   r   r   r;   r  s        rA   _handle_voice_commandz&CLICommandsMixin._handle_voice_command
  sf   %%q%1114UaU1X^^%%++---R
##%%%%%5  $$&&&&&5  ""$$$$$8####%%%%%2 *((*****'')))))G===>>>G788888rC   N)r   r   )r   r   r   r   )r   r   )r   r   )r   r   r   r   )r{  r   r)   r   )r   r   r   r   )r@  r   r   r   )r   )re  r   r   r   r   )/r   r   r   __doc__rB   rp   r   r   r   r   r   r   r  r  rD  r  r  r  r  r  r  r4  r:  rD  rH  rO  rj  rq  rz  r_  r  r  r#  rH  r7  rV  rd  r  r  r  r  r  r  r  r  r  r  r   rC   rA   r   r   '   s        \. \. \. \.|UU UU UU UUnL L LB#F #F #FJ#1 #1 #1 #1JH H H4%5 %5 %5 %5Nd d d d2NQ NQ NQ NQ`  U U U Un\g \g \g \g|6 6 6 6BO9 O9 O9 O9b, , , ,\8M 8M 8M 8MtB] B] B] B]HtJ tJ tJ tJl$ $ $ $*, , , ,<+ + + +,   *0 0 0 0*C C C C4   8H H H H
Y Y Y Yv%
 %
 %
 %
NM M M M^@ @ @ @D, , , ,\J6 J6 J6 J6X)4 )4 )4 )4V*( *( *( *( *(X, , , ,:3N 3N 3N 3Nj0J 0J 0J 0JdN\ N\ N\ N\`)[ )[ )[ )[V*Z *Z *Z *ZX    42 2 2 2h9 9 9 9 9 9rC   r   )r  
__future__r   r  r*   r  r  r1  r  r   urllib.parser   richr   r  rich.markupr   r  
rich.panelr   rc   r	   r
   r   hermes_cli.browser_connectr   r   r   r   r   r   rC   rA   <module>r     sF    # " " " " "  				 



             ! ! ! ! ! !             ) ) ) ) ) )       U U U U U U U U           I*9 I*9 I*9 I*9 I*9 I*9 I*9 I*9 I*9 I*9rC   