
    epjA8                       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 ddlmZmZmZ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)extract_api_content_sidecar)DEFAULT_BROWSER_CDP_URLdiscover_local_cdp_urlfind_free_debug_portis_browser_debug_readylaunch_chrome_debuglocal_port_in_usemanual_chrome_debug_commandc                     e Zd ZdZdKdZdKdZdLd	ZdMdZdKdZd Z	d Z
dNdZd ZdNdZdOdZdPdZd ZdQdZdNdZdNdZdNdZdPdZdPdZdPdZdPd ZdPd!ZdPd"ZdPd#ZdPd$ZdPd%ZdPd&ZdPd'ZdPd(Z dRd+Z!dPd,Z"dSd-Z#dPd.Z$dSd/Z%dTd1Z&dSd2Z'dPd3Z(dUdVd6Z)dNd7Z*dNd8Z+dWd:Z,dXd<Z-dYd=Z.dNd>Z/dNd?Z0dNd@Z1dPdAZ2dPdBZ3dPdCZ4dPdDZ5dUdOdEZ6dZdFZ7dKdGZ8dKdHZ9d[dIZ:dJS )\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agent  No active agent session.Nz  Checkpoints are not enabled.#  Enable with: hermes --checkpoints3  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 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/thesage/.hermes/hermes-agent/hermes_cli/cli_commands_mixin.py_handle_rollback_commandz)CLICommandsMixin._handle_rollback_command3   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                   ddl }	 |                    |          dd         }n,# t          $ r |                                dd         }Y nw xY wd}d}g }|D ]I}|                                }|dv rd}|dv rd	}$|d
v rd}+|dk    rd}4|                    |           Jt          j        dt          j                              }	|dk    r|                     |	|           dS ddl	m
}
  |
|	||pd          }|                    d          s(t          d|                    dd                      dS |                    dd          }|                    dd          }|                    dg           }|                    d          s|s|s|st          d           dS dddd|         }|r(t          d| d           |                     |           |rh|d v rdt          d!           |dd"         D ]}t          d#|            t          |          d"k    r#t          d$t          |          d"z
   d%           |s|sdS |                                }t          d           t          |          d&k    rU|                     d'                    |dd&                              t          d(t          |          d&z
   d)           dS |                     |           dS )*u  Handle /diff — show git changes in the working directory.

        Syntax:
            /diff                  — unstaged changes + untracked files
            /diff staged           — staged changes (git diff --cached)
            /diff all              — staged + unstaged + untracked (vs HEAD)
            /diff session          — everything Hermes changed (checkpoint baseline)
            /diff [mode] --stat    — summary only (changed files + counts)
            /diff [mode] <path...> — restrict to specific paths
        r   Nr   Fworking)z--statr"   T)stagedz--stagedcachedz--cachedrN   )all--allheadrP   sessionr   )collect_working_diff)modepathsr!     r'   Could not generate diffr"   r#   r   	untrackedemptyz  No changes.UnstagedStagedzAll (vs HEAD))rM   rN   rP   
  :)rM   rP   z
  Untracked:   z    + z    ... and z more  r$   r&   u/    more lines — run /diff --stat for a summary))shlexr5   
ValueErrorr8   appendr2   r3   r4   _print_session_difftools.working_diffrT   r:   r/   _print_diff_textr6   r;   r<   )r@   r   ra   rC   	stat_onlyrU   rV   arglowrB   rT   rG   r"   r   rY   labelrelrH   s                     rI   _handle_diff_commandz%CLICommandsMixin._handle_diff_command   s    		(KK((,EE 	( 	( 	(MMOOABB'EEE	( 	 	" 	"C))++C((( 		DDD000	!! S!!!!i	449$$S)444F;;;;;;%%cEMTJJJzz)$$ 	Gvzz'+DEEGGHHHFzz&"%%zz&"%%JJ{B//	::g 	t 	D 	 	/"""F&(?SSTXY 	(////"""!!$''' 	A!333"### "~ & &nsnn%%%%9~~""?S^^b%8???@@@ 	D 	F__&&
b			z??S  !!$))Jtt,<"="=>>>2C
OOc1 2 2 2    
 !!$'''''s   $ &AArB   rg   boolc                   t          | d          r| j        st          d           dS | j        j        }|j        s>t          d           t          d           t          d           t          d           dS |                    |          }|                    d          s(t          d	|                    d
d                      dS |                    dd          }|                    dd          }|                    d          s|s|st          d           dS |r|                     d|            |s|sdS |                                }t          d           t          |          dk    rU|                     d
                    |dd                              t          dt          |          dz
   d           dS |                     |           dS )z>Print the cumulative checkpoint-baseline diff (/diff session).r   r   Nz>  Checkpoints are not enabled, so there's no session baseline.r   r   u5     (Plain /diff still works — it uses git directly.)r!   rW   r'   rX   r"   r#   r   rZ   u9     No changes — Hermes hasn't edited any files here yet.r$   r`   r&   u7    more lines — run /diff session --stat for a summary))r.   r   r/   r0   r1   session_diffr:   rf   r;   r6   r<   )r@   rB   rg   rA   rG   r"   r   rH   s           rI   rd   z$CLICommandsMixin._print_session_diff   s   tW%% 	TZ 	.///Fj({ 	RSSS7888GHHHIJJJF!!#&&zz)$$ 	Gvzz'+DEEGGHHHFzz&"%%zz&"%%::g 	t 	D 	MNNNF 	/!!+t++... 	D 	F__&&
b			z??S  !!$))Jtt,<"="=>>>:C
OOc1 : : :    
 !!$'''''rK   textreturnNonec                    t          | dd          }|7	 ddlm} |                     ||                     dS # t          $ r Y nw xY wt          |           dS )zRender diff/stat text with color when a rich console is present.

        Falls back to plain print when the console isn't available (e.g. unit
        tests instantiating the mixin standalone).
        consoleNr   )_rich_text_from_ansi)getattrcliru   r/   	Exception)r@   rp   rt   ru   s       rI   rf   z!CLICommandsMixin._print_diff_text  s     $	40044444422488999   ds   $; 
AA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>   lsr~   z  No state snapshots yet.z&  Create one: /snapshot create [label]Nz  State snapshots (z/state-snapshots/):
rW   #z>3IDz<35 Filesz>5Sizez>10Labelu	   ───ui   ───────────────────────────────────u   ─────u   ──────────u<   ────────────────────
total_sizei   z Bi   .0fz KBz.1fz MBrj   r#   3id
file_countcreater    )rj   z  Snapshot created: z#  No state files found to snapshot.>   rewindr=      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: pruner_   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.backuprz   r{   r|   r}   hermes_constantsr	   r5   r6   r8   r/   	enumerater:   r<   intrb   )r@   r   rz   r{   r|   r}   r	   rC   subcmdsnapsissizesize_strrj   snap_ididxr   deleteds                      rI   _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r:   .0ps     rI   
<listcomp>z9CLICommandsMixin._handle_stop_command.<locals>.<listcomp>x  ,    HHH155??i+G+G1+G+G+GrK   )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_registryr   list_sessionstools.async_delegationr   r   rx   r/   r6   kill_all)	r@   r   	processesr   r   r   n_asynckilledstoppeds	            rI   _handle_stop_commandz%CLICommandsMixin._handle_stop_commandn  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           	     l   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 ]a}|                    d          pdd	d         }|                    dd          }d|                    dd           d| d| }|dk    r"|                    d          }|
|d|ddz  }n+|dv r'|                    d          }||dk    r
|d |dd!z  } ||           t          |                    d"          pg           D ]\  }}t          |t                    s|                    d#          }|rd$| nd%}d&|d'z    d(|                    d)d           d*| }|                    d+          }|
|d,|dd-z  } ||           ct          | d.d/          } |d0|rd1nd2            d	S )3u>   Handle /agents — show background processes and agent status.r   _cprint)format_uptime_shortr   c                D    g | ]}|                     d           dk    |S r   r   r   s     rI   r   z;CLICommandsMixin._handle_agents_command.<locals>.<listcomp>  r   rK   c                D    g | ]}|                     d           dk    |S r   r   r   s     rI   r   z;CLICommandsMixin._handle_agents_command.<locals>.<listcomp>  s,    III!AEE(OOy,H,HA,H,H,HrK   z  Running processes: r   r#   Nr%   uptime_seconds    
session_id?u    · z  Recently finished: )list_async_delegationsc                @    g | ]}|                     d           dv |S )r   )r   stallingr   )r   ds     rI   r   z;CLICommandsMixin._handle_agents_command.<locals>.<listcomp>  s8     
 
 
uuX"999 999rK   z  Background delegations: z runninggoal<   r   delegation_idr   stalled_after_quiet_secondsu    · no progress r   u   s — interrupting)r   seconds_since_progressu
    · quiet r   children_activitycurrent_toolzin zbetween turnsu         └ child r   r*   	api_callsu    api calls · seconds_since_activityu    · last activity zs ago_agent_runningFz	  Agent: r   idle)rw   r   r   r   r   r   r6   r:   r   r   rx   r   
isinstancedictrv   )r@   r   r   r   r   r   finishedr   cmdupr   delegations	running_dr   r   r   linequietr   childtooldoingpartr   agent_runnings                            rI   _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	
 
"
 
 
	  !	"GIYIIIJJJ  " "f+SbS1x--*155#66 * ** *#'* * 
 Z''EE"?@@E(LuLLLL |++EE":;;E(Ub[[ 9U 9 9 9 99 )!%%0C*D*D*J K K " "HAu%eT22 !  99^44D,0EL$LLLoEN1q5 N N 99[#66N NFKN N  !99%=>>D' DT D D D DDGDMMMM"  &6>>DBIIFDDEEEEEs   C/ /C>=C>cmd_originalc                
   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iora   
contextlibr   rw   r   hermes_cli.journeyr   ArgumentParserr5   
parse_argsr6   
SystemExitrv   funcforce_colorStringIOgetvaluerstriprx   )r@   r   r   r   ra   r   r   r   parserrestrD   interactivebufexcs                 rI   _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_pathrW   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)rw   r   r   r   r  _is_termux_environmenthermes_cli.clipboardr  _try_attach_clipboard_imager6   _attached_images)r@   r   r   r   r  r  ns          rI   _handle_paste_commandz&CLICommandsMixin._handle_paste_command  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GrK   c                f   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l
m}	m}
  |	            r)|                     |            |d|dz    d           dS  |
|          r |d|dz    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	assistantr   r   ms     rI   r   z9CLICommandsMixin._handle_copy_command.<locals>.<listcomp>  s,    ZZZ1QUU6]]k=Y=YQ=Y=Y=YrK   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.)is_remote_shell_sessionwrite_clipboard_textz  Copied assistant response #z' via OSC 52 (terminal support required)z to clipboardz  Clipboard copy failed: )rw   r
  r   r5   r6   stripr>   r   rb   r:   r  r  r  _write_osc52_clipboardrx   )r@   r   r
  r   rC   rh   r  r   rp   r  r  es               rI   _handle_copy_commandz%CLICommandsMixin._handle_copy_command  sQ   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        '&(( 	 ++D1112C!G 2 2 2   ##D)) NaNNNOOO ''---G.a . . .      	5 	5 	5G333444444444	5s6   1B BB
9H H $'H 
H0H++H0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  r   Nr   r#   z/path/to/image.pngrW   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?")rw   r   r  r   r   r  r  r  r5   r  r  suffixr8   namer  rc   )r@   r   r   r  r   r   r  r  r  raw_argshint
path_token
_remainder
image_paths                 rI   _handle_image_commandz&CLICommandsMixin._handle_image_commandM  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rK   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'  rq   rr   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>._TTYBufrq   rm   c                    dS )NT )r@   s    rI   isattyzTCLICommandsMixin._handle_tools_command.<locals>._run_capture.<locals>._TTYBuf.isatty  s    4rK   Nrq   rm   )__name__
__module____qualname__r0  r/  rK   rI   _TTYBufr-    s(                   rK   r5  )rv   r   r;   )	r)  r5  r   r   r   r   r   r@   r(  s	       rI   _run_capturez<CLICommandsMixin._handle_tools_command.<locals>._run_capturev  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#   >   r~   enabledisabler~   rw   )tools_actionplatformr    z(._.) Usage: /tools z <name> [name ...]z  Built-in toolset:  /tools z webz  MCP tool:          /tools z github:create_issuer8  	DisablingEnabling, r   ...)r9  namesr:  )_get_platform_toolsload_configz0Session reset. New tool configuration is active.)r)  r'  rq   rr   )rw   r&  r   r   r   ra   r   r'  r   r   r   r   hermes_cli.tools_configr(  r5   rb   r6   
show_toolsr/   r<   r@  hermes_cli.configrB  enabled_toolsetsnew_session)r@   r   r&  r   r   ra   r'  r6  rC   
subcommandr?  verbrj   r@  rB  r   r   r   r(  s   `              @@@@rI   _handle_tools_commandz&CLICommandsMixin._handle_tools_commandf  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}m}  |d |d                    }|j        d         }|j        d         }t	                       t	          d|            t	          d|            t	                       d	S )
z/Display active profile name and home directory.r   CommandContextexecute_commandprofilerw   surfacehomez  Profile: z  Home:    N)hermes_cli.slash_execrM  rN  datar/   )r@   rM  rN  replyprofile_namedisplays         rI   _handle_profile_commandz(CLICommandsMixin._handle_profile_command  s    IIIIIIII	>>%+H+H+HIIz),*V$*L**+++%G%%&&&rK   c           	     N
   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        sod}	 ddlm} |
j                            |j                  }|r|j        rd  |            D             }||v }n# t          $ r d}Y nw xY w|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                     d0          pd1} |d2|             |d3           d
S |!                    d4           |                                |k     	 | j        "                    | j        d5           n# t          $ r Y nw xY w |d6            |d7           d
S )8u  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'.F)relay_platform_identitiesc                    h | ]\  }}|S r/  r/  )r   r   _s      rI   	<setcomp>z;CLICommandsMixin._handle_handoff_command.<locals>.<setcomp>  s    IIITQqIIIrK   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   zJ  Agent is busy. Wait for the current turn to finish, then retry /handoff.)	SessionDBrW   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: r   z*  Waiting for the gateway to pick it up...g      N@pendingstater   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.)#rw   r   hermes_stater[  r5   r6   r  r8   gateway.configr\  r]  rx   rb   KeyError	platformsr:   r1   gateway.relayr^  RELAYget_home_channelchat_idrv   _session_dbrb  get_sessionr   set_session_titlerequest_handoffr  timeget_handoff_state_should_exitsleepfail_handoff)r@   r   r   r[  rC   platform_namer\  r]  r   r:  	gw_configpcfgrelay_frontsr^  	relay_cfgfrontedrR  rb  rowplaceholder_titlesession_titleok_timedeadline
last_state	state_rowcurrenterrs                               rI   _handle_handoff_commandz(CLICommandsMixin._handle_handoff_command  sl   " 	 >>>>>>""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< 	 !L%CCCCCC%/33HNCC	 <!2 <II-F-F-H-HIIIG#0G#;L % % %$% a}aaabbbt))(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AF" "F10F1'H= =
I
	I
-AK 
K$KK$*8L# #
L0/L0O/ /O>=O> S? ?
TT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        r8	 | j                            | 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             }|| _        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        #                                 	 tI          | 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        rI |d0|
 | d1| d2|dk    rd3nd d4t	          | j                   d5
           | '                                 n |d0|
 | d6           | (                    |           | )                    |           dS )7uW   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.rZ  rW   z  Resume index z is out of range.z:  Use /resume with no arguments to see available sessions.r   )_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.r>   resumed_otherTc                D    g | ]}|                     d           dk    |S r  session_metar   r  s     rI   r   z;CLICommandsMixin._handle_resume_command.<locals>.<listcomp>  s,    XXX!f8W8WA8W8W8WrK   c                D    g | ]}|                     d           dk    |S r  r   r  s     rI   r   z;CLICommandsMixin._handle_resume_command.<locals>.<listcomp>  s3     (
 (
 (
!%%-->2Q2QA2Q2Q2QrK   _last_flushed_db_idx_todo_store	TodoStore_invalidate_system_prompt_memory_managerFparent_session_idresetr+   rd  z "c                n    g | ]2}|                     d           dk    |                     d          0|3S )r  userdisplay_kindr   r  s     rI   r   z;CLICommandsMixin._handle_resume_command.<locals>.<listcomp>  sB    zzzqAEE&MMU[D[D[dedidijxdydyD[D[D[D[rK   u     ↻ Resumed session  ( user messager   r=  z total)u!    — no messages, starting fresh.)*rw   r   r  r5   r6   r  _show_recent_sessions_list_recent_sessions_pending_resume_sessionsrr  rj  r[  isdigitr   hermes_cli.mainr  rs  resolve_resume_session_idrx   r   r   _flush_messages_to_session_dbr>   end_session_resumed_pending_titleget_resume_conversations_resume_display_historyreopen_sessionreset_session_stater.   r  tools.todo_toolr  r  r  rv   on_session_switchr:   _display_resumed_history_restore_session_cwd_restore_session_yolo)r@   r   r   r  rC   targetr[  sessionsindexselected	target_idr  resolvedr  resolved_idresolved_metaold_session_idmodel_historydisplay_historyrestoredr  _mm
title_part	msg_counts                           rI   _handle_resume_commandz'CLICommandsMixin._handle_resume_commandl  s   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-)-)B 9        	((/JJJJ 	 	 	D	 $"  +++ *.)9)R)R*
 *
& YX 3XXX$,!(
 (
'-2(
 (
 (
$
	++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
zzD$@zzz{{	$ 	gG< <J < << <4=NNSS< <122< < <  
 ))++++GeYe
eeefff 	!!,/// 	""<00000sl   %I   II3&K 
K'&K'+ L 
LLN 
N*)N*#P> >
Q
Q=3R1 1
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#   >   r   r~   browserZ  rW   r  r   z!  (._.) No previous sessions yet.z/resume )rw   r   r5   r6   r  r8   rr  rj  r[  r  r  )r@   r   r   rC   rh   subr[  s          rI   _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5rK   c           	     n   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        r8	 | j                            | 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           n# t*          $ r Y n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   r  u5     No conversation to branch — send a message first.NrZ  rW   r   r#   z%Y%m%d_%H%M%S   r`  branchr  branchedHERMES_SESSION_SOURCErw   )max_iterationsreasoning_config_branched_from)r   sourcemodelmodel_configr  z#  Failed to create branch session: c                t   g | ]}|                     d d          |                     d          |                     d          p|                     d          |                     d          |                     d          |                     d          t          |          |                     d          d	S )
r  r  r  	tool_namer  
tool_callstool_call_id	reasoning	timestamp)r  r  r  r  r  r  api_contentr  )r:   r   )r   msgs     rI   r   z;CLICommandsMixin._handle_branch_command.<locals>.<listcomp>  s         !$ 7 7#&779#5#5%(WW[%9%9%LSWWV__&)ggl&;&;(+(?(?%(WW[%9%9 (C3'G'G%(WW[%9%9   rK   i  )
chunk_rowsTr  r  r  r  r  Fr  c                D    g | ]}|                     d           dk    |S )r  r  r   r  s     rI   r   z;CLICommandsMixin._handle_branch_command.<locals>.<listcomp>  s-    YYYqvRXAXAXAXAXAXrK   u     ⑂ Branched session "z" (r  r   )z  Original session: z  Branch session:   )-rw   r   r  r>   rr  rj  r[  r5   r6   r  r   nowstrftimeuuiduuid4hexget_session_titler   get_next_title_in_lineager   r  rx   r  create_sessionr2   environr:   r  	max_turnsr  append_messages_batchrt  _transfer_session_yolosession_startr  r  r  r.   r  r  r  r  r  rv   r  )r@   r   r   r  r[  rC   branch_namer  timestamp_str
short_uuidnew_session_idbranch_titlecurrent_titlebaser  r  r  r  r  s                      rI   _handle_branch_commandz'CLICommandsMixin._handle_branch_commandI  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-)-)B 9        	((*EEEE 	 	 	D		++)z~~&=uEEj&*n(,(=&7 
 #4 , 
 
 
 
  	 	 	G=!==>>>FFFFF		22   $8    % 3    (  	 	 	D		..~|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5H		H,H? ?
III, ,
I98I9 M 
M('M(3O 
OO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>  r  z(._.) Unknown personality: z  Available: none, r=  z4+--------------------------------------------------+z1|            (^o^)/ Personalities               |rW   r  <12z - (no personality overlay)descriptionsystem_prompt2   z - z  Usage: /personality <name>)rw   r  r5   r6   r  r8   r	  r   r/   personalities_resolve_personality_promptr<   keysitemsr   r   r:   r   )r@   r   r  rC   personality_namer  promptpreviews           rI   _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GGGGGrK   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.)r~   galleryr  rP   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  r5   r6   r  r8   r/   
startswithinstall_petPetStoreErrordisplay_name)r@   r   r  r  r  r  r  r  r  rC   rh   ri   r1   r  r  valuer  petr   s                      rI   _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)r   c              3  >   K   | ]}|                                 V  d S N)
capitalizer   ws     rI   	<genexpr>z9CLICommandsMixin._handle_hatch_command.<locals>.<genexpr>l  s*      LL1LLLLLLrK   r      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   detailrq   rr   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   r   u     ┊ drawing u   …composeu     ┊ composing spritesheet…saveu     ┊ saving…)r5   r/   )r7  r8  rf  s      rI   	_progressz9CLICommandsMixin._handle_hatch_command.<locals>._progressz  s    ~~S!,,Q/1u11122222)##677777&'((((( !rK   )
base_imageslugr(  concepton_progressz(x_x) Hatch failed: r  u.    hatched and adopted — it'll pop in shortly!)r7  r   r8  r   rq   rr   )r"  r  agent.pet.generater-  agent.pet.generate.imagegenr.  r$  r  r5   r6   r  inputEOFErrorKeyboardInterruptr/   r<   slugifygenerate_base_drafts	hatch_petr>  r(  )r@   r   r  r-  r.  r  rC   r?  r(  r>  draftsr   r<  rG   s                 rI   _handle_hatch_commandz&CLICommandsMixin._handle_hatch_commandO  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    rI   	_cron_apiz8CLICommandsMixin._handle_cron_command.<locals>._cron_api  s#    :ll44V44555rK   c                    g }| D ]@}t          |pd                                          }|r||vr|                    |           A|S )Nr#   )r   r  rc   )values
normalizedr)  rp   s       rI   _normalize_skillsz@CLICommandsMixin._handle_cron_command.<locals>._normalize_skills  s`    J , ,5;B''--// ,D
22%%d+++rK   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_skillsrP   r  schedulepositionalsr   z--namer   r  r    z	--deliverrY  z--repeatrZ  z!(._.) --repeat must be an integerz--skillr[  z--add-skillr\  z--remove-skillr]  z--clear-skillsTr^  rQ   rP   z--promptr  z
--scheduler_  r`  )r6   r   rb   r/   rc   )tokensoptsr   tokens       rI   _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>r~   )actionr!   jobsz  Current Jobs:zA  ---------------------------------------------------------------rZ  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    rP   )re  include_disabledz(._.) No scheduled jobs.zScheduled Jobs:zP--------------------------------------------------------------------------------z  ID: z  Name: r  z	  State: rf  z  Schedule: r  r  z  Next run: zN/Az
  Skills: z
  Prompt: last_run_atz  Last run: last_status>   addr   r`  z*(._.) Usage: /cron add <schedule> <prompt>r  r   z3(._.) Please provide a prompt or at least one skillr   rY  )re  r_  r  r  rY  rZ  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/  )r   ro  r]  s     rI   r   z9CLICommandsMixin._handle_cron_command.<locals>.<listcomp>S  s$    aaa%eS`F`F`F`F`F`rK   update)re  rg  r_  r  r  rY  rZ  r[  jobz(^_^)b Updated job: z  Skills: nonez(x_x) Failed to update job: >   rmrunpauser   remover  z(._.) Usage: /cron z	 <job_id>>   rs  r   rv  rv  ru  zpaused from /cron)re  rg  r+   z(x_x) Failed to z job: z(^_^)b Paused job: r  z(^_^)b Resumed job: rt  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)rw   rL  ra   tools.cronjob_toolsrM  r5   r6   r/   r:   r<   r8   setr~   rc   )r@   r   rL  ra   rS  rW  rd  ra  rG   rf  rr  
repeat_strrH  rb  r`  r_  r  r[  rg  existingfinal_skillsreplacement_skillsr\  existing_skillsro  re  removedrR  r]  s                              @@rI   _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IrK   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#   r   )handle_suggestions_commandzSuggestions command failed: )ra   r5   rb   r<   hermes_cli.suggestions_cmdr  rx   _console_print)r@   r   ra   ra  rD   r  outputr  s           rI   _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#   r   c              3  B   K   | ]}                     |          V  d S r0  )quote)r   tra   s     rI   r4  z=CLICommandsMixin._handle_blueprint_command.<locals>.<genexpr>  s-      771A777777rK   )handle_blueprint_commandzCron blueprint command failed: 
agent_seed)ra   r5   rb   r<   hermes_cli.blueprint_cmdr  rx   r  rp   rv   _pending_agent_seed)	r@   r   ra  rD   r  rG   r  seedra   s	           @rI   _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   r   )cli_mainz(._.) curator: )ra   r5   hermes_cli.curatorr  r   rx   r/   )r@   r   ra   ra  r  r   s         rI   _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.kanbanr  r  r%  lstripr6   rx   r/   )r@   r   r  r   r  r   s         rI   _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   droprU   applyrejectapprovere  approvalhandle_pending_subcommandwrite_approvalc                0                         d|           S )Nr[  _save_write_approvalr1   r@   s    rI   <lambda>z9CLICommandsMixin._handle_skills_command.<locals>.<lambda>  s    D,E,EhPW,X,X rK   )set_mode_fn)handle_skills_slash)rw   r  r  r5   r6   r8   "hermes_cli.write_approval_commandsr  toolsr  SKILLSr/   hermes_cli.skills_hubr  )	r@   r   r  rC   rD   r  waoutr  s	   `        rI   _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/////rK   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_promptr  r  r5   r6   r/   r.   r  put)r@   r   r  rC   user_requestr  s         rI   _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BrK   c                   ddl m} |                                                    dd          }t	          |          dk    r|d                                         nd} ||          }d|v rt          d           nt          d	           t          | d
          r| j                            |           dS t          d           dS )u  Handle /init — generate or update AGENTS.md from a project scan.

        Mirrors /learn: build a guidance-laden prompt and inject it onto the
        agent's input queue as a normal user turn. The live agent scans the
        project with its own read-only tools and writes/updates AGENTS.md via
        ``write_file``. No engine, no model-tool footprint, works on any
        terminal backend, and preserves prompt-cache invariants (no system
        prompt or history mutation).
        r   )build_init_prompt_for_cwdNr   r#   )extrazUPDATE the existing AGENTS.mdu.   
⚡ Updating AGENTS.md from a project scan...u0   
⚡ Generating AGENTS.md from a project scan...r  z,  /init needs an active chat session to run.)	hermes_cli.init_commandr  r  r5   r6   r/   r.   r  r  )r@   r   r  rC   r  r  s         rI   _handle_init_commandz%CLICommandsMixin._handle_init_command  s     	FEEEEE 		!!$**$'JJNNa   ''e444*c11CDDDDEFFF4)** 	B##C(((((@AAAAArK   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   r  r  r   Nr   _memory_store)load_on_disk_storec                0                         d|           S )Nmemoryr  r  s    rI   r  z9CLICommandsMixin._handle_memory_command.<locals>.<lambda>E  s    (A(A(G(T(T rK   )memory_storer  zWUnknown /memory subcommand. Use: pending, approve <id>, reject <id>, approval <on|off>.)r  r  r  r  r  r5   r6   rv   r   tools.memory_toolr  MEMORYr/   )	r@   r   r  r  rC   rD   r  r  r  s	   `        rI   _handle_memory_commandz'CLICommandsMixin._handle_memory_command0  s    PPPPPP......		!!##JJNNuQRRyy>EdGUY>Z>Zd
OT:::`d= =<<<<<&&((E''ItTTTT
 
 

 ;QCc




rK   	subsystemr1   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)rw   r  rm   )r@   r  r1   r  s       rI   r  z%CLICommandsMixin._save_write_approvalL  s<    ))))))Y777gGGGGGrK   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   )	AIAgentr  _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#   r  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_argsrD   
max_tokensr  rF  
quiet_modeTverbose_loggingFr   r:  rw   
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 r0  r/  )_a_kws     rI   r  zUCLICommandsMixin._handle_background_command.<locals>.run_background.<locals>.<lambda>  s     rK   rp   r   rq   rr   c                l    j         s)| _        j        rj                                         d S d S d S r0  )r   _spinner_textr+  
invalidate)rp   r@   s    rI   _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 3rK   )user_messagetask_idfinal_responser#   r'   zError: g?r  r  ux   ────────────────────────────────────────[/]u     ✅ Background task #z	 completez  Prompt: "r   r>  r  r   )get_active_skinresponse_labelu
   ⚕ Hermesresponse_borderz#CD7F32banner_textz#FFF8DC)rU   z bold]z (background #z)[/]left)r      )rd  title_alignborder_stylestyler   paddingwidthz  (No response generated)u     ❌ Background task #z	 failed: )min_intervalr/  rp   r   rq   rr   )._sudo_password_callback_approval_callback_secret_capture_callbackrx   r:   r  rF  rr  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  rv  ry  r/   r6   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  rG   responser  _skinrj   _resp_color
_resp_text_chat_consoler  r  r  r  r   r  r  r  r@   r  r  r  r  task_num
turn_routes              rI   run_backgroundzCCLICommandsMixin._handle_background_command.<locals>.run_backgroundp  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-)r  daemonr  )rw   r  r  r  r   r  r  r  r  r  r  r5   r6   _background_task_counterr   r  r  r  r  r  _ensure_runtime_credentials_resolve_turn_agent_config	threadingThreadr  start)r@   r   rC   r*  threadr  r  r  r   r  r  r  r  r  r  r  r(  r)  s   `    @@@@@@@@@@@@@rI   _handle_background_commandz+CLICommandsMixin._handle_background_commandQ  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'rK   c                J   ddl m}m}m}m}m}m} ddlm}m	}	  |	d |d                    }
d|
j
        v r |d|
j
        d          |            d	S |
j
        d         }|s< |d
            |d| d|             |d| d|
j
        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   )r  _BOLDr   r   r  r   rL  bundlesrw   rP  r'   z%[1;31mBundle subsystem unavailable: Nz  No skill bundles installed.rW   zGCreate one with: hermes bundles create <name> --skill <s1> --skill <s2>zDirectory: diru   
  ▣ zSkill Bundlesr  z installed):r[  r  zLoad z skillsz
    [bold z]/r>  z<20z[/] [dim]-[/] z [dim](z skills)[/]u           [dim]· r  r]   z;Invoke a bundle with /<slug>. Manage with `hermes bundles`.)rw   r  r5  r   r   r  r   rS  rM  rN  rT  r6   r:   r/   _escape)r@   r   r  r5  r   r   r  r   rM  rN  rU  r6  infoskill_countdescr   s                   rI   _handle_bundles_commandz(CLICommandsMixin._handle_bundles_command  s    	MLLLLLLLLLLLLLLLIIIIIIII	>>%+H+H+HIIej  GZuz'?RZTXZZ[[[F*Y' 	G3444G:T : :37: :   GCCC%*U*;CTCCDDD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	
 	
 	
 	
 	
rK   c                r   ddl }|                                                    dd          }t          |          dk    r,|d                                                                         nd}t
          }t          j                            dd                                          }|	                    d          rr|                                                    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                       ||k    }|rt-          |
d          }|du}|r|}nt/          |d          }|rt          d|            n|rx|
}t1          |
          r6t3          |
          }t          d|
 d           t          d| d           nt          d           t5          ||                                          }|j        rwt;          d          D ]/}t-          |d          }|r|}d } nt=          j        d!           0|rt          d"|            nt          d#| d$           t          d%           nt          d&           |j         }|rt          d'|            |                                }tC          ||          }|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                       tG          | d0          r| j$        %                    d1           dS dS |d2k    r|rt          j        &                    dd           	 dd3lm}m'}  |d-            |             n# t*          $ r Y nw xY wt                       t          d4           t          d5           t                       tG          | d0          r| j$        %                    d6           dS dS t                       t          d7           t                       dS |dk    r/t                       |rt          d8           t          d/|            d9}
	 tQ          |)                    d:d          d;                             d<          d                   }
n# t          tT          f$ r Y nw xY w	 ddl+}|+                    |j,        |j-                  }|.                    d           |/                    d=|
f           |0                                 t          d>           n# tb          t*          f$ r t          d?           Y nw xY w	 dd@lm2}  |            }n# t*          $ r d}Y nw xY w|&t          dA|3                                 dB           n}	 ddClm4}  |            }n# t*          $ r dD}Y nw xY w|dEk    r.t          dF           t          dG           t          dH           n%|dIk    rt          dJ           nt          dK           t                       t          dL           t          dM           t                       dS t                       t          dN           t                       t          dO           t          dP           t          dQ           t                       dS )RuY   Handle /browser connect|disconnect|status — manage live Chromium-family CDP connection.r   Nr   r   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)>   rA  rC  i  r%   u$      ⚠ Invalid port in browser url: u$      ⚠ Missing host in browser url: z/devtools/browser/)pathparamsqueryfragment)cleanup_all_browsersg      ?)timeoutu7      ✓ Chromium-family browser is already listening at u      ⚠ Port z< is occupied by another application that isn't a CDP browseruK        (an IDE debugger or dev server may be using it) — launching on port z instead...uZ      Chromium-family browser isn't running with remote debugging — attempting to launch...r  Tri  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 environmentz 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: r  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)rH  _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^   r  r  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)5r:  r  r5   r6   r8   r   r2   r  r:   r%  r   schemer/   portrb   hostnamerD  geturl_replacetools.browser_toolrH  rx   r   r   r   r   r   systemlaunchedrangerv  ry  r   r   rJ  r.   r  r  r   rL  r   rsplit
IndexErrorsocketAF_INETSOCK_STREAM
settimeoutr?  closeOSErrorrM  provider_namerN  )r@   r   _platrC   r  _DEFAULT_CDPr  connect_partscdp_url
parsed_cdp_port_hostrH  _is_default_found_already_open_launch_port_launch_wait_hintsys_name
chrome_cmdrJ  rL  r]  r   rM  r  rN  engines                                 rI   _handle_browser_commandz(CLICommandsMixin._handle_browser_command  s{
       		!!$***-e**q..eAhnn$$&&&h.*..!2B77==??>>)$$ Y	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 "\1K M/sCCC &d 2 %$G 6w L L L +LYPWYYZZZZ )L$$U++ 
x#7#>#>Ljujjj   fr   
 vwww-lELLNNKK# p!&r ( (!7c!R!R!R! "&,G,0M!E
3$ nm_kmmnnnne,eeeffflmmmmRSSS#LE /oeoo...$||~~H!<\8!T!TJ! 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"R4 4
S SU6 6
VVAZ Z.-Z.2A3\& & ]	]	] ]-,]-^* *^98^9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   rW   &Goals unavailable (no active session).r   showdraftz2  Usage: /goal draft <objective in plain language>ru  zuser-pausedr   zNo goal set.u     ⏸ Goal paused: r  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: r  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.)#rw   r   r   r   r  r5   r6   _get_goal_managerr8   status_linerender_contractr%  _handle_goal_draftru  r   r  has_goalr}  r   rb   wait_onRuntimeErrorstop_waitinghermes_cli.goalsr  ry  is_emptyr  has_contractr  render_blockr;   r  r  rx   )r@   r   r   r   r   rC   rh   rA   r8   	objectiverf  hadwait_argwtokenspidr+   r   rtxtr  headliner  	goal_textr   s                          rI   _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   rw  )draft_contractNrW   rx  u   Drafting completion contract…zgoal draft failed: %sr  r  r  r  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.)rw   r   r   r   r  r  r  rx   logging	getLoggerr2  debugry  rb   r  r   r  r  r  r;   r  r  )r@   r  r   r   r   r  rA   r  r   _loggingrf  r   s               rI   r  z#CLICommandsMixin._handle_goal_draft{	  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   rw  r#   Nr    r   r   rW   rx  z*No active goal. Set one with /goal <text>.rv  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 subgoalr   r   zNo subgoals to clear.z  /subgoal: u     ✓ Added subgoal )rw   r   r   r   r  r5   r6   r<   r  r  r  render_subgoalsr8   r   rb   remove_subgoalr\  r  clear_subgoalsadd_subgoalrf  subgoals)r@   r   r   r   r   rC   rh   rA   ra  rI  r   r   r  r   prevrp   s                   rI   _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    ●rW   r  r  r  r  r#   z   r   u    — r  z
  Usage: /skin <name>z$  Custom skins: drop a YAML file in z/skins/
c                    h | ]
}|d          S )r  r/  )r   r   s     rI   ra  z8CLICommandsMixin._handle_skin_command.<locals>.<setcomp>
  s    5551QvY555rK   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.)rw   r&  r  r  r  r  r  ImportErrorr/   r  r5   r6   r	   r8   r<   sortedr  _apply_tui_skin_style)r@   r   r&  r  r  r  r  rC   r  skinsr   markerr  new_skin	availables                  rI   _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  prefixr3  zutf-8)encodingr   T)shellrc                <    g | ]}|                     d           |S )z#!)r%  )r   lns     rI   r   z7CLICommandsMixin._compose_in_editor.<locals>.<listcomp>I
  s)    JJJbmmD6I6IJJJJrK   r$   )r2   ra   
subprocesstempfiler  r:   r  mkstempfdopenr  callr5   rx   r  openreadunlinkrb  r;   r<   r  )r@   r  r2   ra   r  r  editorheaderfdrD  fhrawliness                rI   _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   rw  r#   Nr   rW   z(>_<) Could not open editor: u$   (._.) Empty prompt — nothing sent.)
rw   r   r   r   r  r5   r6   r  rx   r  )	r@   r   r   r   r   initialrC   composedr   s	            rI   _handle_prompt_compose_commandz/CLICommandsMixin._handle_prompt_compose_commandL
  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           
     @   ddl m}m} ddlm} ddlm}m}m}m	}m
}	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
k    r |d           dS  |	|rt#          | dd          nt#          | dd                    }|dk    r |||          }|                    d          \  }}}|                    d          \  }}}|r|j        n|j        } |d|j         | d|j         | | |j         |r&d|j         d|                                 |j         ndz              dS ||k    r |d |||                      dS |r|| _        |                     |           n|                     |           d| _        t!          |          | _        d| _         ||t!          |                     |r|j         d|j         n|j         d|j         } |t!          |          |          }dD ]}||v r|                    ||d          } n  |d|            dS )u  Toggle or inspect focus view — the reduced-output display mode.

        Usage:
            /focus            → toggle
            /focus on|off     → explicit
            /focus status     → show current state

        Focus view is a DISPLAY-ONLY mode.  It composes with the existing
        ``/verbose`` tool-progress machinery rather than adding a second
        suppression mechanism: turning it on snaps ``tool_progress_mode`` to
        ``"off"`` (the same value ``/verbose off`` uses, honoured by
        ``agent/tool_executor.py`` and ``_on_tool_progress``) after stashing
        whatever mode the user had, and turning it off restores that mode
        verbatim.  On top of that it adds the two things ``/verbose off``
        lacks: a per-turn hidden-line count with a recovery hint, and a
        persistent ``focus`` segment in the status bar.

        Nothing here touches conversation history, the system prompt, or any
        request payload — the model sees an identical turn either way.
        r   r   r  Colors)FOCUS_CONFIG_KEYFOCUS_TOOL_PROGRESS_MODEformat_focus_statusformat_focus_toggle_messagenormalize_tool_progress_moderesolve_focus_argr#   Nr   _focus_view_enabledFusagez  Usage: /focus [on|off|status]_focus_saved_tool_progresstool_progress_moderP   r   r$   r^   rW   r1   disabled)r1   r  )rw   r   r  hermes_cli.colorsr  hermes_cli.focus_viewr  r  r  r  r  r  r  r5   r6   rx   rm   rv   	partitionGREENDIMBOLDRESETr  _set_tool_progress_moder  _focus_hidden_linesreplace)r@   r   r   r  _Colorsr  r  r  r  r  r  rh   rC   r  re  r  restore_modebodyrR   r`  tailrj   r   state_colorrf  messagewords                              rI   _handle_focus_commandz&CLICommandsMixin._handle_focus_commandi
  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%:EBBCC**388WG5666F 43<GD6===3U;;
 
 X&&w==D NN400MD!T!^^C00NE1d+2C'--KG6W\ 65 6 67= 66 $6&-m6 6HLTDDDtzz||DW]DDDRTV  
 FWGM44WlKKMMNNNF 	3 /;D+(()ABBBB((666.2D+#'<< #$ *DLL999 9? 9w}44W]444K8888 	 .-d6llLII+ 	 	Dw!//$q99  	Ws   AA: :B	B	rU   c                    ddl m}  ||          }|| _        t          | dd          }|	 ||_        dS # t          $ r Y dS w xY wdS )u-  Set the live tool-progress mode on both the CLI and the agent.

        Extracted so ``/focus`` and ``/verbose`` share one write path — the
        agent copy is what ``agent/tool_executor.py`` gates on, and forgetting
        it means the new mode only takes effect after an agent rebuild.
        r   )r  r   N)r  r  r  rv   rx   )r@   rU   r  rV  r   s        rI   r  z(CLICommandsMixin._set_tool_progress_mode
  s     	GFFFFF11$77
",gt,,+5(((    s   6 
AAfunction_namec                    t          | dd          sdS ddlm} t          | dd          }t          | dd          } ||||          sdS || _        t	          t          | dd                    d	z   | _        dS )
a
  Count one tool line that focus view is suppressing this turn.

        Counted against the mode the user had BEFORE focus snapped things to
        "off", so a user who already ran ``/verbose off`` is never told that
        focus hid lines it did not hide.
        r  FNr   )would_display_tool_liner  _focus_last_counted_toolr  r   )rv   r  r  r  r   r  )r@   r  r  savedlasts        rI   _note_focus_hidden_linez(CLICommandsMixin._note_focus_hidden_line
  s     t2E:: 	FAAAAAA:DAAt7>>&&umTBB 	F(5%#&wt5JA'N'N#O#ORS#S   rK   c                   t          t          | dd          pd          }d| _        d| _        t          | dd          sdS ddlm}  ||          }|sdS 	 ddlm}m}m	}  |d| | |            dS # t          $ r Y dS w xY w)	z<Print the dim post-turn recovery line and reset the counter.r  r   Nr  F)format_hidden_linerw  rW   )r   rv   r  r  r  r  rw   r   r   r   rx   )r@   countr  r   r   r   r   s          rI   _emit_focus_recovery_linez*CLICommandsMixin._emit_focus_recovery_line
  s    GD"7;;@qAA#$ (,%t2E:: 	F<<<<<<!!%(( 	F	//////////G++t+T++,,,,, 	 	 	DD	s   A6 6
BBc                    ddl m} ddlm} |pd                                                    dd          }t          |          dk    r|d         nd} ||          } |d|j                    dS )zAShow or persist the profile-wide dangerous-command approval mode.r   r   )run_approval_mode_commandr#   Nr   rW   )rw   r   hermes_cli.approval_moder  r  r5   r6   r  )r@   r   r   r  rC   	requestedrG   s          rI   _handle_approvals_commandz*CLICommandsMixin._handle_approvals_command  s    FFFFFF#**,,224;; #E

QE!HHD	**955%V^%%&&&&&rK   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  rA  r  r#   Nr   rW  runtime_footerr1   Ffields)r  context_pctrB   >   r   r   ONOFFrW   zRuntime footer:r   z
  Fields: r=  >   1ontruer7  T>   0r!  falser8  z   Usage: /footer [on|off|status]zdisplay.runtime_footer.enabledz  Runtime footer: z6  Failed to save runtime_footer setting to config.yaml)rw   r   r  rE  rB  r  r  r  r5   r6   r8   rx   r:   rm   r  r  r<   r  r  )r@   r   r   r  rB  r  rh   rC   cfg
footer_cfgr  r  rf  	new_states                 rI   _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   r   r  r  rW   zMessage timestamps:r   >   r  r  r  r7  T>   r  r!  r  r8  z$  Usage: /timestamps [on|off|status]zdisplay.timestampsz  Message timestamps: z2  Failed to save timestamps setting to config.yaml)rw   r   r  r  r  r  r5   r6   r8   rx   rm   rv   r  r  r  r  r  )
r@   r   r   r  r  rh   rC   r  rf  r  s
             rI   _handle_timestamps_commandz+CLICommandsMixin._handle_timestamps_command@  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}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 }|sd|v rd                    d |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  ||          }|H |d| d*| |             |d| d+|             |d| d,|             |d| d-|            dS || _        d| _        |rX |d.|          rL|                    d/          }t+          |t,                    si }||d/<   ||d0<    |d| d1| d2|            dS |r |d| d1| d3|            dS  |d| d1| d4|            dS )5u  Handle /reasoning — manage effort level and display toggle.

        Usage:
            /reasoning              Show current effort level and display state
            /reasoning <level>      Set effort for this session only (none, minimal, low, medium, high, xhigh, max, ultra)
            /reasoning <level> --global  Persist reasoning effort to config.yaml
            /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   )
CLI_CONFIGr&  r   r   r   _parse_reasoning_configr  r   r  r    Nzmedium (default)r1   Fznone (disabled)effortmediumu   on ✓r!  reasoning_fullfullzclamped to 10 linesrW   zReasoning effort:  zReasoning display: r  r  z`Usage: /reasoning <none|minimal|low|medium|high|xhigh|max|ultra|show|hide|full|clamp> [--global]--global	--sessionr   c              3  "   K   | ]
}|d v|V  dS )r"  r#  Nr/  r   rc  s     rI   r4  z=CLICommandsMixin._handle_reasoning_command.<locals>.<genexpr>  s:         999 9999 rK   >   r  ry  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)>   rP   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: zAValid levels: none, minimal, low, medium, high, xhigh, max, ultrazDisplay:      show, hidez<Scope:        session-scoped by default, --global to persistzagent.reasoning_effortr   reasoning_effortu   ✓ Reasoning effort set to 'r  z$' (session only; config save failed)u,   ' (this session — use --global to persist))rw   r  r&  r   r   r   r  r  r  r5   r6   r  r:   show_reasoningrv   r8   r<   r   _current_reasoning_callbackreasoning_callbackr   r   r   )r@   r   r  r&  r   r   r   r  r  rC   rcleveldisplay_state
full_staterh   
arg_tokensexplicit_globalparsed	agent_cfgs                      rI   _handle_reasoning_commandz*CLICommandsMixin._handle_reasoning_commandr  s    	mlllllllllllllllll		!!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  F  F  F  @D  F  F  G  G  GFAhnn$$&&YY[[
 %
2 	kZ77((  #-    C .  "&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fff`dffgggG===t==>>>Gaaa[_aabbbF &
 
	x001I3OO 
	x"w//Ii.. 0	&/
7#,/I()G]]]s]]W[]]^^^^^ 	xGnnnsnnhlnnoooooGvvvsvvptvvwwwwwrK   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     Redirect the current run on Enter (default)
        r   r&  r   r   r   r  r   r  r    r   rW   zBusy input mode: queuezqueues for next turnsteerz.steers into current run (after next tool call)z!redirects current run immediatelyz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).zQEnter will redirect the current run while Hermes is busy; /stop still cancels it.u   ✓ Busy input mode set to 'r  r  )rw   r&  r   r   r   r  r  r5   r6   r8   busy_input_mode)r@   r   r&  r   r   r   r  rC   	_behaviorrh   behaviors              rI   _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		?	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nG\\\c\\VZ\\]]]G//x///00000GYYYcYYSWYYZZZZZrK   c                   ddl m}m}m}m}m} ddlm}m} |}	| j	        
                    d          pi 
                    d|          }
|                                                    d          }t          |          dk     s0|d                                                                         d	k    r< |d
| d|
 |             |d
| dd                    |	           d|            dS |d                                                                         }||	vr< |d
| d| |             |d
| dd                    |	           d|            dS || j	                            di           d<    |d|          r' |d
| d| d|             |d
| d|            dS  |d
| d| d|            dS )uj  Handle /indicator — pick the TUI busy-indicator style.

        Usage:
            /indicator              Show the current busy-indicator style
            /indicator status       Show the current busy-indicator style
            /indicator kaomoji      Animated kaomoji faces (default)
            /indicator emoji        Emoji spinner
            /indicator unicode      Braille spinner
            /indicator ascii        Plain ASCII spinner

        Persists to ``display.tui_status_indicator`` — the same config key the
        TUI reads — so the change is picked up the next time the TUI renders.
        r   r:  )DEFAULT_INDICATOR_STYLEINDICATOR_STYLESrW  tui_status_indicatorr   r  r    r   rW   zBusy-indicator style: zUsage: /indicator [|r  Nz(._.) Unknown indicator style: zdisplay.tui_status_indicatoru!   ✓ Busy-indicator style set to 'r  z2The TUI picks up the new style on its next render.r  )rw   r&  r   r   r   r  r   rC  rD  configr:   r  r5   r6   r8   r<   
setdefault)r@   r   r&  r   r   r   r  rC  rD  stylesr  rC   rh   s                rI   _handle_indicator_commandz*CLICommandsMixin._handle_indicator_command   sl    	HGGGGGGGGGGGGGNNNNNNNN![__Y''-2223IKbcc 	 		!!1!--u::>>U1X^^--3355AAGGGGGGGHHHGKKK#((62B2BKKTKKLLLFAhnn$$&&fGIIIcI4IIJJJGKKK#((62B2BKKTKKLLLFHKy"--.DE;SAA 	`Gaaa3aa[_aabbbGWWWQUWWXXXXXG^^^3^^X\^^_____rK   c           
     n   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 }d                    d |D                       }|dv rd| _        d}d}n6|dv rd| _        d}d}n& |d| d| |             |d| d|            dS d| _        |r% |d|          r |d| d|
 d| d |            dS |r |d| d|
 d| d!|            dS  |d| d|
 d| d"|            dS )#u   Handle /fast — toggle fast mode (OpenAI Priority Processing / Anthropic Fast Mode).

        Session-scoped by default; ``--global`` persists agent.service_tier
        to config.yaml (parity with /model and /reasoning).
        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    r   priorityfastnormalrW   r*   z,Usage: /fast [normal|fast|status] [--global]r"  r   c              3  "   K   | ]
}|d v|V  dS r%  r/  r&  s     rI   r4  z8CLICommandsMixin._handle_fast_command.<locals>.<genexpr>E  s:       
 
555 5555
 
rK   >   r  rN  FAST>   r!  rO  NORMALr+  zagent.service_tieru   ✓ z set to z (saved to config)z# (session only; config save failed)u+    (this session — use --global to persist))rw   r&  r   r   r   r  _fast_command_availablehermes_cli.modelsrL  rv   rx   r  r5   r6   r8   r  r<   r   )r@   r   r&  r   r   r   r  rL  r   r  feature_namerC   r   r4  r5  rh   saved_valuerj   s                     rI   _handle_fast_commandz%CLICommandsMixin._handle_fast_command(  st    	H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QQQ4QQRRRF1X^^%%++--3355
$
2hh 
 
)
 
 
 
 

 .   *D KEE%%% $D"KEEGBBBsBDBBCCCGQQQ4QQRRRF
 	v001E{SS 	vG[[[l[[E[[UY[[\\\\\ 	vGllllllEllfjllmmmmmGtttlttEttnrttuuuuus   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/  )r8   r2  s     rI   ra  z9CLICommandsMixin._handle_debug_command.<locals>.<setcomp>n  s     ===q===rK   r   Nlocalnous      T)r  expirer\  r]  yes)hermes_cli.debugrY  typesrZ  r5   )r@   r   rY  rZ  wordsr\  r]  rD   s           rI   _handle_debug_commandz&CLICommandsMixin._handle_debug_command_  s     	544444))))))==L$6$6$8$8$<===5 ,u9 au4T
 
 
 	rK   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`.)rd  r8  choicesNu     🟡 /update cancelled.ri  u     ⚕ Launching update...rq  T)rE  rg  rh  r/   _prompt_text_input_modal_normalize_slash_confirm_choice_pending_relaunch)r@   rg  rh  rl  r  choices         rI   _handle_update_commandz'CLICommandsMixin._handle_update_commandy  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)*** #+trK   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!  ttsr   zUnknown voice subcommand: z!Usage: /voice [on|off|tts|status]N)rw   r   r  r5   r6   r8   _enable_voice_mode_disable_voice_mode_toggle_voice_tts_show_voice_status_voice_moder@   r   r   rC   rH  s        rI   _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8rK   c                    ddl m} |                                                    d          }t	          |          dk    r,|d                                                                         nd}|dk    r/|                     d          r|                     d           dS dS |d	k    r-|                     d           |                     d
           dS |dv r|dk    rmt          | dd
          r-|                     d           |                     d
           dS |                     d          r|                     d           dS dS | 
                                 dS  |d|             |d           dS )u2  Handle /wake [on|off|status] — the 'Hey Hermes' hotword listener.

        The toggle IS the config: an explicit on/off (or bare toggle) also
        writes ``wake_word.enabled`` to config.yaml so the choice persists
        across sessions. Startup auto-arm (_maybe_start_wake_word) only reads.
        r   r   r   r  r#   r  T)announcer!  F)r#   r   _wake_word_activezUnknown wake subcommand: zUsage: /wake [on|off|status]N)rw   r   r  r5   r6   r8   _start_wake_word_listener_persist_wake_word_enabled_stop_wake_word_listenerrv   _show_wake_word_statusry  s        rI   _handle_wake_commandz%CLICommandsMixin._handle_wake_command  s    	 %%q%1114UaU1X^^%%++---R
--t-<< 6//555556 65  ))4)888++E22222>))R4!4e<< :1141@@@33E:::::33T3BB :33D99999: : ++-----G<
<<===G233333rK   c           	     <   ddl m}m}m}m} 	 ddlm} t           |                                d                    |k    rdS n# t          $ r Y nw xY w |d|          r; || d|rdnd d	t          |                                           d
|            dS dS )zJSave ``wake_word.enabled`` so the /wake toggle sticks for future sessions.r   )r   r   r   r  )load_wake_word_configr1   Nzwake_word.enabledz
Wake word r  z in config (wake_word.enabled: r   )rw   r   r   r   r  tools.wake_wordr  rm   r:   rx   r   r8   )r@   r1   r   r   r   r  r  s          rI   r  z+CLICommandsMixin._persist_wake_word_enabled  s.   >>>>>>>>>>>>	======))++//	::;;wFF G 	 	 	D	0':: 	KGt J JG'Kyy J J+.w<<+=+=+?+?J JCGJ J K K K K K	K 	Ks   4A 
AAN)r   r   )rB   r   rg   rm   r  )r   r   rq   rr   )r   r   )r   r   )r   r   rq   rm   )r  r   r1   rm   )r   r   rq   rr   )r  r   rq   rr   )r#   )r  r   rq   r   )rU   r   rq   rr   )r  r   rq   rr   )rq   rr   r1  )r1   rm   );r2  r3  r4  __doc__rJ   rl   rd   rf   r   r   r   r   r  r  r$  rJ  rX  r  r  r  r  r  r+  rJ  r  r  r  r  r  r  r  r  r  r  r3  r<  ru  r  r  r  r  r  r  r  r  r  r  r  r  r  r8  rA  rJ  rW  re  rq  rz  r  r  r/  rK   rI   r   r   +   s        \. \. \. \.|L( L( L( L(\&( &( &( &(P    UU UU UU UUnL L LB@F @F @FD#1 #1 #1 #1JH H H4;5 ;5 ;5 ;5zd d d d2NQ NQ NQ NQ`  g g g gRz1 z1 z1 z1x6 6 6 6B\9 \9 \9 \9|, , , ,\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B B B B4   8H H H H
Y Y Y Yv&
 &
 &
 &
Pc c c cJ@ @ @ @D, , , ,\J6 J6 J6 J6X)4 )4 )4 )4V*( *( *( *( *(X, , , ,:_  _  _  _ B   $T T T T$   &' ' ' '3N 3N 3N 3Nj0J 0J 0J 0Jdax ax ax axF)[ )[ )[ )[V&` &` &` &`P5v 5v 5v 5vn    42 2 2 2h9 9 9 904 4 4 4>K K K K K KrK   r   )#r  
__future__r   rO  r2   r  r/  rv  r  r   urllib.parser   richr   r  rich.markupr   r8  
rich.panelr   r   r	   r
   r  agent.turn_contextr   hermes_cli.browser_connectr   r   r   r   r   r   r   r   r/  rK   rI   <module>r     s    # " " " " "  				 



             ! ! ! ! ! !             ) ) ) ) ) )       U U U U U U U U : : : : : :                 F3K F3K F3K F3K F3K F3K F3K F3K F3K F3KrK   