
    sj                       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dQdZdQdZdRd	ZdSdZdQdZdQdZ	dQdZ
d Zd ZdTdZd ZdTdZdUdZdVdZd ZdWdZdTdZdTdZdTdZdTdZdVd ZdVd!ZdVd"ZdVd#ZdVd$ZdVd%ZdVd&ZdVd'ZdVd(Z dVd)Z!dVd*Z"dVd+Z#dXd.Z$dVd/Z%dYd0Z&dVd1Z'dYd2Z(dYd3Z)dYd4Z*dZd6Z+dYd7Z,dYd8Z-dVd9Z.d[d\d<Z/dTd=Z0dTd>Z1d]d@Z2d^dBZ3d_dCZ4dTdDZ5dTdEZ6dTdFZ7dVdGZ8dVdHZ9dVdIZ:dVdJZ;d[dUdKZ<d`dLZ=dQdMZ>dQdNZ?dadOZ@dPS )b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 }d}g }|D ]0}	|	                                dv rd}|                    |	           1|}|sv|                    |          }
|
sD|                                }|r.t	          d| d           t	           ||d                     dS 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}|                    |||| o|           }|d         r|r%t	          d | d!|d"          d#|d$                     n!t	          d%|d"          d#|d$                     |                    d&          pg }|rkd'                    |dd(                   }t          |          d(k    rd)t          |          d(z
   d*nd}t	          d+| |            t	          d,           t	          d-           | j        r'|                     d.           t	          d/           dS dS t	          d|d                     dS )0up  Handle /rollback — list, diff, or restore filesystem checkpoints.

        Syntax:
            /rollback                 — list checkpoints
            /rollback <N>             — restore checkpoint N, preserving user
                                        hand-edits (also undoes last chat turn)
            /rollback <N> --all       — classic full restore (may overwrite
                                        files you edited after Hermes did)
            /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   F)--allz--forceTz  No checkpoints for u    — showing all directories.zall directories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_pathsafeu     ✅ Restored z from checkpoint restored_to: reasonu     ✅ Restored to checkpoint skipped_user_edits,    z (+z more)u     ↷ Kept your hand-edits: z/  Use /rollback <N> --all to restore those too.z2  A pre-rollback snapshot was saved automatically.)prefillz0  Chat turn undone to match restored file state.)tools.checkpoint_managerr   hasattrr   print_checkpoint_mgrenabledosgetenvgetcwdsplitlenlowerappendlist_checkpointslist_all_checkpoints_resolve_checkpoint_refr    get
splitlinesjoinrestoreconversation_history	undo_last)selfr   r   mgrcwdpartsargsrestore_allfilteredacheckpointsall_checkpointstarget_hashresultr#   r    
diff_linesr)   skippedshownmores                        A/home/agent/.hermes/hermes-agent/hermes_cli/cli_commands_mixin.py_handle_rollback_commandz)CLICommandsMixin._handle_rollback_command3   s    	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  	# 	#Awwyy000""""" 	 ..s33K "%":":"<"<" T#TTTUUU00BSTTUUUF((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$		 2]  
 
 ) 	. 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jj!566<"G I		'"1"+..9<W9I9I5S\\A-5555rBUBDBBCCCGHHH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--cachedr\   )allr   headr^   sessionr   )collect_working_diff)modepathsr"     r(   Could not generate diffr#   r$   r    	untrackedemptyz  No changes.UnstagedStagedzAll (vs HEAD))r[   r\   r^   
  :)r[   r^   z
  Untracked:   z    + z    ... and z more  r%   r'   u/    more lines — run /diff --stat for a summary))shlexr:   
ValueErrorr<   r=   r7   r8   r9   _print_session_difftools.working_diffra   rA   r4   _print_diff_textr;   rB   rC   )rG   r   rn   rJ   	stat_onlyrb   rc   arglowrI   ra   rR   r#   r    rf   labelrelrS   s                     rW   _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rI   rs   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"   rd   r(   re   r#   r$   r    rg   u9     No changes — Hermes hasn't edited any files here yet.r%   rm   r'   u7    more lines — run /diff session --stat for a summary))r3   r   r4   r5   r6   session_diffrA   rr   rB   r;   rC   )rG   rI   rs   rH   rR   r#   r    rS   s           rW   rp   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 : : :    
 !!$'''''rY   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clir   r4   	Exception)rG   r|   r   r   s       rW   rr   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/):
rd   #z>3IDz<35 Filesz>5Sizez>10Labelu	   ───ui   ───────────────────────────────────u   ─────u   ──────────u<   ────────────────────
total_sizei   z Bi   .0fz KBz.1fz MBrv   r$   3id
file_countcreater!   )rv   z  Snapshot created: z#  No state files found to snapshot.>   rewindrD      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: prunerl   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.backupr   r   r   r   hermes_constantsr	   r:   r;   r<   r4   	enumeraterA   rC   intro   )rG   r   r   r   r   r   r	   rJ   subcmdsnapsissizesize_strrv   snap_ididxr   deleteds                      rW   _handle_snapshot_commandz)CLICommandsMixin._handle_snapshot_command8  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}m} |                                dd         }d}d|v r_|                    d          }|dz   t          |          k    rt          d           dS ||dz            }|d|         ||dz   d         z   }|r|d         n |            pd}|s| d	}	  |||          }t          d
| d|            t          d           dS # t          t          f$ r}	t          d|	            Y d}	~	dS d}	~	ww xY w)u/  Handle /export — export a profile to a shareable .tar.gz archive.

        Syntax:
            /export                       — export the active profile
            /export <profile>             — export a named profile
            /export [profile] -o <path>   — choose the output path
        r   )export_profileget_active_profile_namer   Nz-oz-  Usage: /export [profile] [-o output.tar.gz]r!   defaultz.tar.gzu     ✓ Exported 'z' to zM  Share it: the other user runs /import or `hermes profile import <archive>`.	  Error: )	hermes_cli.profilesr   r   r:   indexr;   r4   ro   FileNotFoundError)
rG   r   r   r   rJ   outputr   namerR   es
             rW   _handle_export_commandz'CLICommandsMixin._handle_export_command  sr    	POOOOOOO#5==++d##CQw#e**$$EFFF37^F$3$K%a/1E NuQxx'>'>'@'@'MI 	&%%%F	##^D&11F8T8888999abbbbb-. 	# 	# 	#/a//"""""""""	#s   (0C D+DDc                   ddl m}m}m} |                                dd         }d}d|v r_|                    d          }|dz   t          |          k    rt          d           dS ||dz            }|d|         ||dz   d         z   }|st          d           dS d                    |          }	  |||	          }	n7# t          t          t          f$ r}
t          d
|
            Y d}
~
dS d}
~
ww xY w|	j        }t          d| d|	            	  ||          s ||          }|rt          d|            n# t          $ r Y nw xY wt          d|            dS )u   Handle /import — import a shared profile archive as a new profile.

        Syntax:
            /import <archive.tar.gz> [--name <name>]
        r   )check_alias_collisioncreate_wrapper_scriptimport_profiler   N--namez1  Usage: /import <archive.tar.gz> [--name <name>]r!   r   r   r   u     ✓ Imported profile 'z' at z  Wrapper created: z  Use it: hermes -p )r   r   r   r   r:   r   r;   r4   rC   ro   FileExistsErrorr   r   r   )rG   r   r   r   r   rJ   r   r   archiveprofile_dirr   importedwrapper_paths                rW   _handle_import_commandz'CLICommandsMixin._handle_import_command  s   	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 #u++h''CQw#e**$$IJJJq>D$3$K%a/1E 	EFFFF((5//	(.t<<<KKO->? 	 	 	/a//"""FFFFF	 #EEEEEFFF	((22 @44X>> @>>>??? 	 	 	D	/X//00000s*   5C C7C22C7*E 
EE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rA   .0ps     rW   
<listcomp>z9CLICommandsMixin._handle_stop_command.<locals>.<listcomp>  ,    HHH155??i+G+G1+G+G+GrY   )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   r   r4   r;   kill_all)	rG   r   	processesr   r   r   n_asynckilledstoppeds	            rW   _handle_stop_commandz%CLICommandsMixin._handle_stop_command  sW    	<;;;;;$2244	HHiHHH	!JJJJJJJJ"lnnGG 	! 	! 	!G MMM	!  	w 	6777F 	:HGHHHIII%..00F86888999 	L}0#m7333GJwJJJKKKKK	L 	L00s   ; AAc           	     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     rW   r   z;CLICommandsMixin._handle_agents_command.<locals>.<listcomp>   r   rY   c                D    g | ]}|                     d           dk    |S r   r   r   s     rW   r   z;CLICommandsMixin._handle_agents_command.<locals>.<listcomp>  s,    III!AEE(OOy,H,HA,H,H,HrY   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     rW   r   z;CLICommandsMixin._handle_agents_command.<locals>.<listcomp>  s8     
 
 
uuX"999 999rY   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)r   r   r   r   r   r   r;   rA   r   r   r   r   
isinstancedictr   )rG   r   r   r   r   r   finishedr   cmdupr   delegations	running_dr   r   r   linequietr   childtooldoingpartr   agent_runnings                            rW   _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iorn   
contextlibr	  r   r   hermes_cli.journeyr
  ArgumentParserr:   
parse_argsr;   
SystemExitr   funcforce_colorStringIOgetvaluerstripr   )rG   r  r  r  rn   r	  r   r
  parserrestrK   interactivebufexcs                 rW   _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_pathrd   uh   Clipboard image paste is not available on Termux — use /image <path> or paste a local image path like N)has_clipboard_imageu     📎 Image #z attached from clipboardz2(>_<) Clipboard has an image but extraction failedz!(._.) No image found in clipboard)r   r#  r$  r   r%  _is_termux_environmenthermes_cli.clipboardr&  _try_attach_clipboard_imager;   _attached_images)rG   r#  r$  r   r%  r&  ns          rW   _handle_paste_commandz&CLICommandsMixin._handle_paste_commanda  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GrY   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     rW   r   z9CLICommandsMixin._handle_copy_command.<locals>.<listcomp>  s,    ZZZ1QUU6]]k=Y=YQ=Y=Y=YrY   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: )r   r.  r   r:   r;   striprE   r   ro   rA   r(  r7  r8  _write_osc52_clipboardr   )rG   r  r.  r   rJ   rt   r3  r   r|   r7  r8  r   s               rW   _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.pngrd   z"Usage: /image <path>  e.g. /image z(>_<) File not found: z"(._.) Not a supported image file: u     📎 Attached image: z<Now type your prompt (or use --image in single-query mode): z;Tip: type your next message, or run hermes chat -q --image z "What do you see?")r   r#  r=  r$  r   r>  r?  r%  r:   r9  r'  suffixr<   r   r*  r=   )rG   r  r#  r=  r$  r   r>  r?  r%  raw_argshint
path_token
_remainder
image_paths                 rW   _handle_image_commandz&CLICommandsMixin._handle_image_command  s    	H  	H  	H  	H  	H  	H  	H  	H  	H  	H  	H  	H  	H  	H  	H  	H  	H  	H>A\>Q>QL&&tQ//288:::WY 	3I3K3Ke--///QeDGMMMMtMMNNNF!2!28!<!<
J--j99
GGGGZGGGHHHF""$$,===GXXXXRVXXYYYF$$Z000;*/;;<<< 	dGmmm[emgkmmnnnnn#%% 	dG  c  c  cZtZtu  vE  [F  [F  c  c  ]a  c  c  d  d  d  d  d	d 	drY   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nsrI  r}   r~   c                8   t          dd           |            dS  G d d          } |            } |          5   |            ddd           n# 1 swxY w Y   |                                                                D ]} |           dS )a  Run tools_disable_enable_command, routing its ANSI-colored
            print() output through _cprint when inside the interactive TUI
            so escapes aren't mangled by patch_stdout's StdoutProxy into
            garbled '?[32m...?[0m' text.

            Outside the TUI (standalone mode, tests), call straight through
            so real stdout / pytest capture works as expected.
            _appNc                      e Zd ZddZdS )MCLICommandsMixin._handle_tools_command.<locals>._run_capture.<locals>._TTYBufr}   ry   c                    dS )NT )rG   s    rW   isattyzTCLICommandsMixin._handle_tools_command.<locals>._run_capture.<locals>._TTYBuf.isatty  s    4rY   Nr}   ry   )__name__
__module____qualname__rR  rQ  rY   rW   _TTYBufrO    s(                   rY   rW  )r   r  rB   )	rK  rW  r  r   r  r   r	  rG   rJ  s	       rW   _run_capturez<CLICommandsMixin._handle_tools_command.<locals>._run_capture  s    tVT**2,,R000
         (       '))C %% 1 1,,R0001 1 1 1 1 1 1 1 1 1 1 1 1 1 11133   s   AA"Ar   r$   >   r   enabledisabler   r   )tools_actionplatformr!   z(._.) Usage: /tools z <name> [name ...]z  Built-in toolset:  /tools z webz  MCP tool:          /tools z github:create_issuerZ  	DisablingEnablingr/   r   ...)r[  namesr\  )_get_platform_toolsload_configz0Session reset. New tool configuration is active.)rK  rI  r}   r~   )r   rH  r#  r$  r   rn   r  rI  r  r	  r  r  hermes_cli.tools_configrJ  r:   ro   r;   
show_toolsr4   rC   ra  hermes_cli.configrc  enabled_toolsetsnew_session)rG   r   rH  r#  r$  rn   rI  rX  rJ   
subcommandr`  verbrv   ra  rc  r  r   r	  rJ  s   `              @@@@rW   _handle_tools_commandz&CLICommandsMixin._handle_tools_command  s    	544444444444&&&&&&......HHHHHH	 	 	 	 	 	 	 	 	 	6	 KK$$EE 	  	  	 IIKKEEE	  "%UaU1XXR
:::OOFLGGGHHHFabb	 	GGGGHHHAAAABBBQQQQRRRF
 )I55{{:		%  73D33533T33444YYJeeTTTUUU 	@?????111111 3 3KKMM5 I I4OOOOPPPPPs   A A0/A0c                    ddl m}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profiler   surfacehomez  Profile: z  Home:    N)hermes_cli.slash_execrn  ro  datar4   )rG   rn  ro  replyprofile_namedisplays         rW   _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%%&&&rY   c           	     
   ddl m} ddlm} |                    d          }t          |          dk     s|d                                         s# |d            |d            |d	           d
S |d                                                                         }	 ddlm	}m
} n&# t          $ r} |d|            Y d}~d
S d}~ww xY w	  ||          }	n'# t          t          f$ r  |d| d           Y d
S w xY w	  |            }
n&# t          $ r} |d|            Y d}~d
S d}~ww xY w|
j                            |	          }|r|j        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/l m } |!                    | j                   d
| _"        dS |d0k    r4|pi                     d1          pd2} |d3|             |d4           d
S |#                    d5           |                                |k     /	 | j        $                    | j        d6           n# t          $ r Y nw xY w |d7            |d8           d
S )9u  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 rQ  rQ  )r   r   _s      rW   	<setcomp>z;CLICommandsMixin._handle_handoff_command.<locals>.<setcomp>m  s    IIITQqIIIrY   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.)	SessionDBrd   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 )_handed_off_session_idsfailedr(   zunknown errorz  Handoff failed: zV  Your CLI session is intact. Try /handoff again, or /resume on the platform manually.      ?ztimed out waiting for gatewayzA  Timed out waiting for the gateway. Is `hermes gateway` running?z  Your CLI session is intact.)%r   r   hermes_stater|  r:   r;   r9  r<   gateway.configr}  r~  r   ro   KeyError	platformsrA   r6   gateway.relayr  RELAYget_home_channelchat_idr   _session_dbr  get_sessionr   set_session_titlerequest_handoffr   timeget_handoff_stater  add_should_exitsleepfail_handoff)rG   r  r   r|  rJ   platform_namer}  r~  r   r\  	gw_configpcfgrelay_frontsr  	relay_cfgfrontedrs  r  rowplaceholder_titlesession_titleok_timedeadline
last_state	state_rowcurrentr  errs                                rW   _handle_handoff_commandz(CLICommandsMixin._handle_handoff_command.  s   " 	 >>>>>>""A"..u::>>q!1!1>G2333GVWWWGPQQQ4a((..00	DDDDDDDDD 	 	 	G===>>>44444		x..HHH% 	 	 	G<=<<<===44		++--II 	 	 	G===>>>44444	 "&&x00 	4< 	 !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 877777'++DO<<<$(!u("" B++G44G2S22333pqqqtKK? jjllX%%D	))$/;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>> T 
T,+T,c                Z   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}dd/l'm( t	          fd0| j        D                       }| j        rI |d1|
 | d2| d3|dk    rd4nd d5t	          | j                   d6
           | )                                 n |d1|
 | d7           | *                    |           | +                    |           | ,                    |           dS )8uW   Handle /resume <session_id_or_title> — switch to a previous session mid-conversation.r   r   _sync_process_session_idNr   r$   r!   <>[]"'z-  Usage: /resume <number|session_id_or_title>resumer   
   r   zA  Tip:   Use /history or `hermes sessions list` to find sessions.r{  rd   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: zD  Use /sessions 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.rE   resumed_otherTc                D    g | ]}|                     d           dk    |S r2  session_metar   r4  s     rW   r   z;CLICommandsMixin._handle_resume_command.<locals>.<listcomp>V  s,    XXX!f8W8WA8W8W8WrY   c                D    g | ]}|                     d           dk    |S r  r   r4  s     rW   r   z;CLICommandsMixin._handle_resume_command.<locals>.<listcomp>X  s3     (
 (
 (
!%%-->2Q2QA2Q2Q2QrY   _last_flushed_db_idx_todo_store	TodoStore_invalidate_system_prompt_memory_managerFparent_session_idresetr-   r  z ")is_user_originated_turnc                *    g | ]} |          |S rQ  rQ  )r   r5  r  s     rW   r   z;CLICommandsMixin._handle_resume_command.<locals>.<listcomp>  s+    ___qD[D[\]D^D^____rY   u     ↻ Resumed session  ( user messager   r/   z total)u!    — no messages, starting fresh.)-r   r   r  r:   r;   r9  _show_recent_sessions_list_recent_sessions_pending_resume_sessionsr  r  r|  isdigitr   hermes_cli.mainr  r  resolve_resume_session_idr   r   r   _flush_messages_to_session_dbrE   end_session_resumed_pending_titleget_resume_conversations_resume_display_historyreopen_sessionreset_session_stater3   r  tools.todo_toolr  r  r  r   on_session_switchrA   agent.context_compressorr  _display_resumed_history_restore_session_cwd_restore_session_yolo_restore_session_model)rG   r  r   r  rJ   targetr|  sessionsr   selected	target_idr  resolvedr  resolved_idresolved_metaold_session_idmodel_historydisplay_historyrestoredr  _mm
title_part	msg_countr  s                           @rW   _handle_resume_commandz'CLICommandsMixin._handle_resume_command  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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
DDDDDD ____D$@___``	$ 	gG< <J < << <4=NNSS< <122< < <  
 ))++++GeYe
eeefff 	!!,/// 	""<000
 	##L11111sl   &I II4&K 
K('K(, L 
LLN 
N+*N+$P? ?
QQ>3R2 2
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   browser{  rd   r  r   z!  (._.) No previous sessions yet.z/resume )r   r   r:   r;   r9  r<   r  r  r|  r  r  )rG   r  r   rJ   rt   subr|  s          rW   _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5rY   c           	     z	   ddl }ddl}|                    dd          }t          |          dk    r|d                                         nd}|                                }|r|dv r{|j        }|r1t          d|d                     t          d	|d
                     nt          d           |rt          d           t          d           nt          d           dS |dv r|st          d           dS t          |          dk    r,|d                                                                         nd}d|v pd|                                v }	ddl	m
}
 |j        }|
                    |d          }|r2t          |                    d          pd          fd|D             }|
                    ||	|          }||
                    ||	          z  }|r?|D ]}t          d|            t          dt          |           d|	rdnd d           nt          d           d |D             }|rDt          d t          |           d!           |D ]!}t          d"|j         d#|j                    "dS |d$v r|st          d           dS 	 |                    g d%d&d&d'd(d)|*          }|j        dk    r|j                                        nd}n# t*          $ r d}Y nw xY w|r*|                                D ]}t          d|            nt          d+           dS |d,v rd|st          d-           dS t          |          dk    r|d                                         nd}dd.lm} 	 t3           |                                d/d&                    }n# t*          $ r d&}Y nw xY w|                    |||0          }|sdS 	 t7          j        |d                    n)# t:          $ r}t          d1|            Y d}~nd}~ww xY w|d         t6          j        d2<   ddl}||_        |                     |j!        |           t          d3|d                     t          d	|d
                     t          d4           dS t          d5|            t          d6           dS )7u  Handle /worktree — inspect, create, or reclaim isolated git worktrees.

        Syntax:
            /worktree                  — show the active worktree (if any)
            /worktree new [name]       — create a worktree and move this session into it
            /worktree list             — list worktrees under the repo's .worktrees/
            /worktree prune [--dry-run] — reclaim safe trees + merged branches

        Inspired by Copilot CLI's ``/worktree new``: start isolated work in a
        fresh worktree without leaving the session. Creating one retargets the
        terminal/file tools (``TERMINAL_CWD`` + process cwd) at the new tree;
        the launcher's exit cleanup applies (kept only when it has unpushed
        commits, same as ``hermes -w``).

        ``prune`` is the same attended reclaim as ``hermes worktree prune``
        (hermes_cli/worktree_gc.py): never deletes tracked changes, unique
        unpushed commits, or in-use trees; archives untracked-only scratch.
        r   Nr!   r   r$   >   showr   z  Active worktree: pathz
  Branch: branchz&  No active worktree for this session.uC     /worktree new [name] — create one and move this session into ituB     /worktree prune      — reclaim stale trees and merged branchesz  (not inside a git repository)>   gccleanr   z  Not inside a git repository.z	--dry-runz-n)worktree_gcF)
with_sizesc                *    g | ]}|j         k    |S rQ  )r  )r   recordactive_paths     rW   r   z=CLICommandsMixin._handle_worktree_command.<locals>.<listcomp>  s0          %{k11 111rY   )dry_runrecords)r  rd   z action(s) planneddoner   uB     Nothing to reclaim — remaining trees/branches carry real work.c                L    g | ]!}|j         d k    rd|j        vd|j        v|"S )r   kanbanzin use)verdictr-   )r   r   s     rW   r   z=CLICommandsMixin._handle_worktree_command.<locals>.<listcomp>  sH       !>V++FM11hfm6S6S 6S6S6SrY   z  Preserved z tree(s) with real work:r   r,   >   r   r   )gitworktreer   Tutf-8replacer  )capture_outputr|   encodingerrorstimeoutrI   z  Could not list worktrees.>   r  newr   u;     ❌ /worktree new requires being inside a git repository.rb  worktree_sync)	repo_root	sync_baser   u/     ⚠ Created worktree but could not enter it: r   u     ✅ Worktree ready: z6  Terminal and file tools now operate in the worktree.z   Unknown /worktree subcommand: z&  Usage: /worktree [new [name] | list])"
subprocessr   r:   r;   r<   _git_repo_root_active_worktreer4   r9  
hermes_clir  audit_worktreesr   rA   reclaim_worktreesreclaim_branchesr   r-   run
returncodestdoutr   rB   rf  rc  ry   _setup_worktreer7   chdirOSErrorenvironatexitregister_cleanup_worktree)rG   r  r  _clirJ   r  r  activer  r  r  tree_recordsactionsr   keptr   rR   outr   rc  r  wt_infor   r#  r  s                           @rW   _handle_worktree_commandz)CLICommandsMixin._handle_worktree_command  s4   & 	""4++"%e**q..eAhnnb''))	 	c///*F @<F6N<<===56(#3556666>??? 9[\\\Z[[[[7888F*** 6777/25zzA~~58>>##))+++2D!T)ATTZZ\\-AG......*F&66yU6SSL  "&**V"4"4":;;       )5      "337L 4  G {33Iw3OOOG \# ' 'D+t++&&&&W3w<<WW4TIIfWWWXXXXZ[[[ %1  D
  AHSYYHHHIII" A AF?????@@@@F.   6777#///#'dW$bi (  
 06/@A/E/Efm))+++2    5NN,, ' 'D+t++&&&&' 3444F*** STTT'*5zzA~~58>>###4D555555! !2!2?D!I!IJJ		 ! ! ! 			!**#yt +  G  M)))) M M MKKKLLLLLLLLM)0BJ~& MMM$+D!OOD2G<<<<76?<<===2wx022333JKKKF666777677777s=   AK" "K10K1?+N+ +N:9N:O5 5
P?PP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.Nr{  rd   r   r$   z%Y%m%d_%H%M%S   r  r  r  branchedHERMES_SESSION_SOURCEr   )max_iterationsreasoning_config_branched_from)r   sourcemodelmodel_configr  z#  Failed to create branch session: c                   g | ]}|                     d d          |                     d          |                     d          p|                     d          |                     d          |                     d          |                     d          |                     d          |                     d	          |                     d
          t          |          |                     d          dS )r2  userr6  	tool_namer   
tool_callstool_call_id	reasoningreasoning_detailscodex_reasoning_itemscodex_message_items	timestamp)r2  r6  r:  r;  r<  r=  r>  r?  r@  api_contentrA  )rA   r   )r   msgs     rW   r   z;CLICommandsMixin._handle_branch_command.<locals>.<listcomp>  s       "  !$ 7 7#&779#5#5%(WW[%9%9%LSWWV__&)ggl&;&;(+(?(?%(WW[%9%9-0WW5H-I-I149P1Q1Q/2ww7L/M/M (C3'G'G%(WW[%9%9   rY   i  )
chunk_rowsTr  r  r  r  r  Fr  c                D    g | ]}|                     d           dk    |S )r2  r9  r   r4  s     rW   r   z;CLICommandsMixin._handle_branch_command.<locals>.<listcomp>  s-    YYYqvRXAXAXAXAXAXrY   u     ⑂ Branched session "z" (r  r   )z  Original session: z  Branch session:   )-r   r   r  rE   r  r  r|  r:   r;   r9  r   nowstrftimeuuiduuid4hexget_session_titler   get_next_title_in_lineager   r  r   r  create_sessionr7   r"  rA   r6  	max_turnsr3  append_messages_batchr  _transfer_session_yolosession_startr  r  r  r3   r  r  r  r  r  r   r  )rG   r  r   r  r|  rJ   branch_namerG  timestamp_str
short_uuidnew_session_idbranch_titlecurrent_titlebaser  r   r  r  r  s                      rW   _handle_branch_commandz'CLICommandsMixin._handle_branch_commandN  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}m}m}m}m} |                    d          }t          |          dk    r|d                                         }	  ||t          | dd                    \  }	}
nq# t          $ rd t          d|                                            t          dd	                    | j                                                              Y dS w xY w ||	          }|	s	 dd
lm}m}  | | |            ddd                    | _        n# t(          $ r
 d| _        Y nw xY wd| _        |rt          d           nt          d           t          d           dS |
| _        d| _        |rt          d|	 d           nt          d|	 d           t          d|
dd          t          |
          dk    rdnd d           dS 	 ddlm}  | |                                d          pi                     dd                    }n# t(          $ r d}Y nw xY wt                       t          d           t          d           t          d           t                       |sdnd }t          d!| d"d#d$           | j                                        D ]0\  }	}|	|k    rdnd }t          d!| |	d#d% ||                      1t                       t          d&           t                       dS )'u   Handle the /personality command to set predefined personalities.

        All resolution/persistence goes through hermes_cli.personality —
        the single owner of personality state on every surface.
        r   )describe_personalitynormalize_personality_namepersist_personalityprompt_textresolve_personalityr   r/  configNz(._.) Unknown personality: z  Available: none, r/   )cfg_getread_raw_configr   system_promptr$   )r   z,(^_^)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  )rc  rx  personalityz4+--------------------------------------------------+z1|            (^o^)/ Personalities               |z *rd   r   none<12z - (no personality overlay)z - z+  Usage: /personality <name>   (* = active))hermes_cli.personalityr\  r]  r^  r_  r`  r:   r;   r9  r   ro   r4   r<   rC   personalitieskeysrf  rb  rc  rd  r   r   rA   items)rG   r   r\  r]  r^  r_  r`  rJ   personality_namer   personality_promptsavedrb  rc  r  markerprompts                    rW   _handle_personality_commandz,CLICommandsMixin._handle_personality_command  s    	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 		1	%%u::>>$Qx~~//+>+>$gdHd&C&C, ,(((    N4D4J4J4L4LNNOOORDIId6H6M6M6O6O,P,PRRSSS
 ('--E i,JJJJJJJJ)4 1 17OUWXXX* *D&& ! , , ,)+D&&&,!
 FHIIIIDEEEOPPPPP%7"!
 OQQQQRRRRMtMMMNNNg/4gsCU?V?VY[?[?[eeacggghhhhh======44$_&&**955;@@PRSS     GGG&'''JKKK&'''GGG!(2TTdFEfEfEEEEFFF $ 2 8 8 : : O Of!%dM&M$MMM/C/CF/K/KMMNNNNGGG?@@@GGGGGs8   A3 3A*C! C!2-D   D43D4AH H.-H.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  r^   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.petrv  agent.pet.manifestrw  hermes_cli.petsrx  ry  rz  r{  r|  r:   r;   r9  r<   r4   
startswithinstall_petPetStoreErrordisplay_name)rG   r   rv  rw  rx  ry  rz  r{  r|  rJ   rt   ru   r6   r   r  valuer  petr   s                      rW   _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}|st          | d	d
          }t          |          r  |d          pd
                                }nI	 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   ru  )orchestrate)GenerationError)rx  r   r/  r$   _prompt_text_inputNz(o_o) Describe your pet: zA(o_o) Usage: /hatch <description>  (e.g. /hatch a tiny cyber fox)r   c              3  >   K   | ]}|                                 V  d S N)
capitalizer   ws     rW   	<genexpr>z9CLICommandsMixin._handle_hatch_command.<locals>.<genexpr>  s*      LL1LLLLLLrY   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   detailr}   r~   c                    | dk    r1|                     dd          d         }t          d| d           d S | dk    rt          d           d S | d	k    rt          d
           d S d S )Nr  rk   r   r   u     ┊ drawing u   …composeu     ┊ composing spritesheet…saveu     ┊ saving…)r:   r4   )r  r  r  s      rW   	_progressz9CLICommandsMixin._handle_hatch_command.<locals>._progress  s    ~~S!,,Q/1u11122222)##677777&'((((( !rY   )
base_imageslugr  concepton_progressz(x_x) Hatch failed: r~  u.    hatched and adopted — it'll pop in shortly!)r  r   r  r   r}   r~   )r  rv  agent.pet.generater  agent.pet.generate.imagegenr  r  rx  r:   r;   r9  r   callableinputEOFErrorKeyboardInterruptr4   rC   slugifygenerate_base_drafts	hatch_petr  r  )rG   r   rv  r  r  rx  rJ   r  prompt_helperr  r  draftsr   r  rR   s                  rW   _handle_hatch_commandz&CLICommandsMixin._handle_hatch_commandv  s    	$#####222222??????//////		1	%%&)%jj1nn%(.."""" 	 $D*>EEM&& (=)DEEKRRTT#$?@@FFHHGG "34   GGGFF  	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   !!C C&%C&F) )G.GG& H H)H$$H)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 )NrQ  )jsonloads)kwargscronjob_tools    rW   	_cron_apiz8CLICommandsMixin._handle_cron_command.<locals>._cron_api  s#    :ll44V44555rY   c                    g }| D ]@}t          |pd                                          }|r||vr|                    |           A|S )Nr$   )r   r9  r=   )values
normalizedr  r|   s       rW   _normalize_skillsz@CLICommandsMixin._handle_cron_command.<locals>._normalize_skills  s`    J , ,5;B''--// ,D
22%%d+++rY   c                   d d d g g g ddd d g d}d}|t          |           k     rS| |         }|dk    r+|dz   t          |           k     r| |dz            |d<   |dz  }n|dk    r+|dz   t          |           k     r| |dz            |d	<   |dz  }n|d
k    rZ|dz   t          |           k     rD	 t          | |dz                      |d<   n # t          $ r t          d           Y d S w xY w|dz  }nu|dk    rA|dz   t          |           k     r+|d                             | |dz                       |dz  }n.|dk    r@|dz   t          |           k     r*|d                             | |dz                       |dz  }n|dk    r@|dz   t          |           k     r*|d                             | |dz                       |dz  }n|dk    rd|d<   |dz  }n|dk    rd|d<   |dz  }n|dk    r*|dz   t          |           k     r| |dz            |d<   |dz  }nP|dk    r*|dz   t          |           k     r| |dz            |d<   |dz  }n |d                             |           |dz  }|t          |           k     S|S )NF)r   deliverrepeatskills
add_skillsremove_skillsclear_skillsr^   rr  schedulepositionalsr   r   r   r   r!   z	--deliverr  z--repeatr  z!(._.) --repeat must be an integerz--skillr  z--add-skillr  z--remove-skillr  z--clear-skillsTr  r   r^   z--promptrr  z
--scheduler  r  )r;   r   ro   r4   r=   )tokensoptsr   tokens       rW   _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  ---------------------------------------------------------------r  r   r   job_id   ri  z | r  z<15z<8r  z      Skills: r/   z      prompt_previewr$   next_run_atz      Next: z3  No scheduled jobs. Use '/cron add' to create one.r!   r^   )r  include_disabledz(._.) No scheduled jobs.zScheduled Jobs:zP--------------------------------------------------------------------------------z  ID: z  Name: r   z	  State: r  z  Schedule: r  rF  z  Next run: zN/Az
  Skills: z
  Prompt: last_run_atz  Last run: last_status>   r  r   r  z*(._.) Usage: /cron add <schedule> <prompt>rr  r   z3(._.) Please provide a prompt or at least one skillr   r  )r  r  rr  r   r  r  r  z(^_^)b Created job: z(x_x) Failed to create job: r(   r  zN(._.) Usage: /cron edit <job_id> [--schedule ...] [--prompt ...] [--skill ...]z(._.) Job not found: r  r  skillr  c                    g | ]}|v|	S rQ  rQ  )r   r  r  s     rW   r   z9CLICommandsMixin._handle_cron_command.<locals>.<listcomp>  s$    aaa%eS`F`F`F`F`F`rY   update)r  r  r  rr  r   r  r  r  jobz(^_^)b Updated job: z  Skills: nonez(x_x) Failed to update job: >   rmr  pauser  remover  z(._.) Usage: /cron z	 <job_id>>   r  r  r  r  r  zpaused from /cron)r  r  r-   z(x_x) Failed to z job: z(^_^)b Paused job: r  z(^_^)b Resumed job: r  z(^_^)b Triggered job: z)  It will run on the next scheduler tick.removed_jobz(^_^)b Removed job: z(._.) Unknown cron command: z8  Available: list, add, edit, pause, resume, run, remove)r   r  rn   tools.cronjob_toolsr  r:   r;   r4   rA   rC   r<   setr   r=   )rG   r   r  rn   r  r  r  r  rR   r  r  
repeat_strri  r  r  r  rr  r  r  existingfinal_skillsreplacement_skillsr  existing_skillsr  r  removedr  r  s                              @@rW   _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IrY   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: )rn   r:   ro   rC   hermes_cli.suggestions_cmdr  r   _console_print)rG   r   rn   r  rK   r  r   r   s           rW   _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 r  )quote)r   trn   s     rW   r  z=CLICommandsMixin._handle_blueprint_command.<locals>.<genexpr>  s-      771A777777rY   )handle_blueprint_commandzCron blueprint command failed: 
agent_seed)rn   r:   ro   rC   hermes_cli.blueprint_cmdr  r   r  r|   r   _pending_agent_seed)	rG   r   r  rK   r  rR   r   seedrn   s	           @rW   _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: )rn   r:   hermes_cli.curatorr  r  r   r4   )rG   r   rn   r  r  r   s         rW   _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/r  Nz(._.) kanban error: )hermes_cli.kanbanr  r9  r  lstripr;   r   r4   )rG   r   r  r  r   r   s         rW   _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    droprb   applyrejectapprover  approvalhandle_pending_subcommandwrite_approvalc                0                         d|           S )Nr  _save_write_approvalr6   rG   s    rW   <lambda>z9CLICommandsMixin._handle_skills_command.<locals>.<lambda>'  s    D,E,EhPW,X,X rY   )set_mode_fn)handle_skills_slash)r   r  r9  r:   r;   r<   "hermes_cli.write_approval_commandsr  toolsr  SKILLSr4   hermes_cli.skills_hubr  )	rG   r   r  rJ   rK   r  war+  r  s	   `        rW   _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/////rY   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  r9  r:   r;   r4   r3   r  put)rG   r   r  rJ   user_requestrC  s         rW   _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BrY   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  r9  r:   r;   r4   r3   r  r  )rG   r   r  rJ   r  rC  s         rW   _handle_init_commandz%CLICommandsMixin._handle_init_commandI  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ArY   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    rW   r  z9CLICommandsMixin._handle_memory_command.<locals>.<lambda>x  s    (A(A(G(T(T rY   )memory_storer  zWUnknown /memory subcommand. Use: pending, approve <id>, reject <id>, approval <on|off>.)r  r  r  r  r9  r:   r;   r   r   tools.memory_toolr#  MEMORYr4   )	rG   r   r  r  rJ   rK   rv  r#  r+  s	   `        rW   _handle_memory_commandz'CLICommandsMixin._handle_memory_commandc  s    PPPPPP......		!!##JJNNuQRRyy>EdGUY>Z>Zd
OT:::`d= =<<<<<&&((E''ItTTTT
 
 

 ;QCc




rY   	subsystemr6   c                J    ddl m}  || dt          |                     dS )zLPersist <subsystem>.write_approval to config (for /memory|/skills approval).r   )save_config_valuez.write_approvalN)r   r,  ry   )rG   r*  r6   r,  s       rW   r
  z%CLICommandsMixin._save_write_approval  s<    ))))))Y777gGGGGGrY   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)MNr6  api_keyruntimebase_urlproviderapi_modeacp_commandr   acp_argsrK   
max_tokensr2  rg  
quiet_modeTverbose_loggingFr   r\  r   
session_dbr3  service_tierrequest_overridesproviders_allowedproviders_ignoredproviders_orderprovider_sortprovider_require_parametersprovider_data_collectionopenrouter_min_coding_scorefallback_modelc                     d S r  rQ  )_a_kws     rW   r  zUCLICommandsMixin._handle_background_command.<locals>.run_background.<locals>.<lambda>  s     rY   r|   r   r}   r~   c                l    j         s)| _        j        rj                                         d S d S d S r  )r   _spinner_textrM  
invalidate)r|   rG   s    rW   _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 3rY   )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)rb   z bold]z (background #z)[/]left)r      )r  title_alignborder_stylestyler   paddingwidthz  (No response generated)u     ❌ Background task #z	 failed: )min_intervalrQ  r|   r   r}   r~   )._sudo_password_callback_approval_callback_secret_capture_callbackr   rA   rO  rg  r  r3  rB  _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_conversationrM  rQ  r  r  r4   r;   hermes_cli.skin_enginerW  get_branding	get_colorr   final_response_markdownrich_boxHORIZONTALS_scrollback_box_widthbell_on_completesysr  writeflush_background_taskspopr   rP  _invalidate)bg_agentrR  rR   responserW  _skinrv   _resp_color
_resp_text_chat_consoler   r.  r  r/  r   r0  r1  rr  rG   r2  r3  r4  rT  task_num
turn_routes              rW   run_backgroundzCCLICommandsMixin._handle_background_command.<locals>.run_background  s   &&t'CDDD!!$"9:::++D,IJJJJ   o5"7   $W--&y155i@@@ (	266zBBB (	266zBBB	
 (	266zBBB !+9 5 9 9) D D D (	266v>>>  *)488FFF $(>> &*%:%:  $t %*E  'w #U  $//  &*%:%:!" "&!2!2#$ '1nn5H&I&I&I%& '+&:&:'( '+&<&<)* %)$9$9+, #'"5"5-. 150M0M/0 .2-K-K12 150Q0Q34 $(#7#75: &=%<"3 3 3 3 3 3 .:*!22!'# 3  
 @FM6::&6;;;2 ;F ;vzz'/B/B ;:::H
 9 %I((***Jt$$$##$G$G$G
$G$G$GHHHE(EEEFFFYvcrc{YS[[2=M=MEESUYYYZZZ##$G$G$G
$G$G$GHHH 9	/JJJJJJ / 1 1 % 2 23C\ R R&A&A%//RcenBoBo&p&p%@%@Q^`iAjAj%k%k

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


/
 %0KMMM!''77tGcdddX+XXUXX(XXX$*%0($0 &"88::	) 	) 	) 	 	 	 	 G7888 ( 'J$$T***J$$&&& J J J9 %I((***Jt$$$H(HHQHHIIIIIIIIJ..t444))$/////5555    D&**7D999* ,)+D&9 5$$!$444445 5..t444))$/////5555    D&**7D999* ,)+D&9 5$$!$44445s   4 
A AJ P &A$M 
P MP MB=P T 
R&AQ>9T >RT !R) )
R65R6U?!T'&U?'
T41U?3T44AU?Tzbg-task-)r  daemonr   )r   r.  r  r/  r   r0  r1  r2  r3  r4  r9  r:   r;   _background_task_counterr   rG  rH  rI  rJ  rK  _ensure_runtime_credentials_resolve_turn_agent_config	threadingThreadr~  start)rG   r   rJ   r  threadr.  r  r/  r   r0  r1  rr  r2  r3  r4  rT  r  r  s   `    @@@@@@@@@@@@@rW   _handle_background_commandz+CLICommandsMixin._handle_background_command  s    	Q  	Q  	Q  	Q  	Q  	Q  	Q  	Q  	Q  	Q  	Q  	Q  	Q  	Q  	Q  	Q  	Q  	Q  	Q  	Q  	Q  	Q		!!1!--u::>>q!1!1>G3444GOPPPG_```Fq!!%%*%%0R//99RRDJLL<LRaR<PRR //11 	GQRRRFs8sssWZ[aWbWbegWgWgeemosssttt'g''(((RSSS44V<<
v	5 v	5 v	5 v	5 v	5 v	5 v	5 v	5 v	5 v	5 v	5 v	5 v	5 v	5 v	5 v	5 v	5 v	5p !K_V]K_K_```*0w'rY   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   rm  bundlesr   rq  r(   z%[1;31mBundle subsystem unavailable: Nz  No skill bundles installed.rd   zGCreate one with: hermes bundles create <name> --skill <s1> --skill <s2>zDirectory: diru   
  ▣ zSkill Bundlesr  z installed):r  descriptionzLoad z skillsz
    [bold z]/r  z<20z[/] [dim]-[/] z [dim](z skills)[/]u           [dim]· rV  rj   z;Invoke a bundle with /<slug>. Manage with `hermes bundles`.)r   r  r  r#  r$  r/  r   rt  rn  ro  ru  r;   rA   r4   _escape)rG   r   r  r  r#  r$  r/  r   rn  ro  rv  r  infoskill_countdescr   s                   rW   _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	
 	
 	
 	
 	
rY   c                   ddl }|                                                    dd          }t          |          dk    r,|d                                                                         nd}t
          }t          j                            dd                                          }|dk    s|	                    d          rd	|v r.|                    dd          d                                         nd
}ddl
m}m}	 ddlm}
 |dvrKt                       t          d           t          d           t          d           t                       dS  |            }|                    di           }|d
k    rid|d<    |	|            |
             |                                  t                       t          d           t          d           t                       nnddlm} ||d<    |	|            |
             |                                  t                       t          d           t          d           t                       dS |	                    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tA          |d()          }|rt          d*|            n|rx|}tC          |          r6tE          |          }t          d+| d,           t          d-| d.           nt          d/           tG          ||$                                          }|j%        rwtM          d0          D ]/}t?          |d()          }|r|}d1} ntO          j(        d2           0|rt          d3|            nt          d4| d5           t          d6           nt          d7           |j)        }|rt          d8|            |$                                }tU          ||          }|r"t          d9           t          d8|            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                       tY          | dA          r| j-        .                    dB           dS dS |dCk    r|rt          j        /                    dd           	 ddDlm}m0}  |d>            |             n# t<          $ r Y nw xY wt                       t          dE           t          dF           t                       tY          | dA          r| j-        .                    dG           dS dS t                       t          dH           t                       dS |dk    rt                       	 ddIlm1}  |            } n# t<          $ r dJ} Y nw xY w| rKt          dK           t          dL           t                       t          dM           t                       dS |rt          dN           t          d@|            dO}	 te          |3                    dPd          dQ                             dR          d                   }n# t.          th          f$ r Y nw xY w	 ddl5}!|!5                    |!j6        |!j7                  }"|"8                    d           |"9                    dS|f           |":                                 t          dT           n# tv          t<          f$ r t          dU           Y nw xY w	 ddVlm<}#  |#            }$n# t<          $ r d}$Y nw xY w|$&t          dW|$=                                 dX           n}	 ddYlm>}%  |%            }&n# t<          $ r dZ}&Y nw xY w|&d[k    r.t          d\           t          d]           t          d^           n%|&d_k    rt          d`           nt          da           t                       t          db           t          dc           t                       dS t                       t          dd           t                       t          de           t          df           t          dg           t          dh           t                       dS )iuY   Handle /browser connect|disconnect|status — manage live Chromium-family CDP connection.r   Nr   r   BROWSER_CDP_URLr$   usezuse r   on)rc  save_config)invalidate_check_fn_cache>   r  r  zUsage: /browser use [off]uO      /browser use       — switch to Browser Use mode (browser_exec via CLI 3.0)u>      /browser use off   — revert to the built-in browser toolsbrowserzbrowser-usebackenduJ   🌐 Browser Use mode enabled — browser_exec via the Browser Use CLI 3.0z3   Session reset. New tool configuration is active.)BACKEND_DISABLEDuB   🌐 Browser Use mode disabled — built-in browser tools restoredconnectr!   z://zhttp://>   wswsshttphttpsu'      ⚠ Unsupported browser url scheme: z	(missing)z( (expected one of: http, https, ws, wss)>   r  r  i  r&   u$      ⚠ Invalid port in browser url: u$      ⚠ Missing host in browser url: z/devtools/browser/)r  paramsqueryfragment)cleanup_all_browsersg      ?)r  u7      ✓ 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  Tr  u>      ✓ Chromium-family browser launched and listening on port u!      ⚠ Browser launched but port z isn't responding yetuL        Try again in a few seconds — the debug instance may still be startingu6      ⚠ Could not auto-launch a Chromium-family browserz     z/     Launch a Chromium-family browser manually:zN     No supported Chromium-family browser executable found in this 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)r  _stop_cdp_supervisoru;   🌐 Browser disconnected from live Chromium-family browserzL   Browser tools reverted to default mode (local headless or cloud provider)z[System note: The user has disconnected the browser tools from their live Chromium-family browser. Browser tools are back to default mode (headless local browser or cloud provider).]zWBrowser is not connected to a live Chromium-family browser (already using default mode))is_browser_use_cli_modeFuI   🌐 Browser: Browser Use mode (browser_exec via the Browser Use CLI 3.0)z6   Local Chrome via CDP, or Browser Use cloud browsersuA      /browser use off      — revert to the built-in browser toolsu?   🌐 Browser: connected to live Chromium-family browser via CDPi$  rk   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|status|usezR   connect      Connect browser tools to your live Chromium-family browser sessionz1   disconnect   Revert to default browser backendz)   status       Show current browser modezM   use [off]    Switch to Browser Use mode (CLI 3.0) / back to built-in tools)?r\  r9  r:   r;   r<   r   r7   r"  rA   r  rf  rc  r  tools.registryr  r4   
setdefaultrh  tools.browser_use_clir  r   schemeportro   hostnamer  geturl_replacetools.browser_toolr  r   r   r   r   r   r   systemlaunchedranger  r  rB  r   r  r3   r  r  r  r  r  r   rsplit
IndexErrorsocketAF_INETSOCK_STREAM
settimeoutr  closer!  r  provider_namer  )'rG   r   _platrJ   r  _DEFAULT_CDPr  rt   rc  r  r  ra  browser_cfgr  connect_partscdp_url
parsed_cdp_port_hostr  _is_default_found_already_open_launch_port_launch_wait_hintsys_name
chrome_cmdr  r  r  _bu_moder  r   r  r:  r  engines'                                          rW   _handle_browser_commandz(CLICommandsMixin._handle_browser_commandG	  s       		!!$***-e**q..eAhnn$$&&&h.*..!2B77==??%<<3>>&11<36#::#))D!$$Q'--///4CBBBBBBBB@@@@@@-''1222ghhhVWWW []]F ++Ir::Kd{{)6I&F###))+++  """bcccKLLLBBBBBB)9I&F###))+++  """Z[[[KLLLF>>)$$ f	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!IIIIII2244 ! ! ! ! abbbNOOOYZZZ )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ABBBGGGfgggEFFF=>>>abbbGGGGGs   L/ /8M+*M+P 
P%$P%Y   
Y-,Y-\" "
\/.\/_. ._=<_=4Ab7 7c
cA3e  e&%e&*e; ;f
	f
6g ggc                   ddl m}m}m} ddl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    r=|
                                }| |d| d|            n |d|j                    dS |	dk    rb|
                                }| |d| d|            n8|                                   |d ||j                   d|j                    dS |	dv r3|
                                r |d           n |d| d|            dS |                    dd          }d}d}|rc|d         
                                dk    rEt          |          dk    r2 |d|d                    }t          |          dk    r|d         nd}nL|rJ ||d                   }|r5|dk    r/|t          |d                   d                                         nd}| |d            |d| d|            dS |dk     rddlm}  |d| d           dS |                                s |d           dS 	 |
                    ||          }n&# t*          $ r} |d|            Y d}~dS d}~ww xY w|                                   |d ||j                   d|j                     |d| d|            dS )u[  Dispatch /heartbeat: set / status / pause / resume / clear.

        ``/heartbeat every 10m Check the deployment`` sets the session's one
        recurring instruction; the idle watchdog injects it as a normal user
        turn whenever due. Session-scoped and in-process — for durable
        cross-process schedules use `hermes cron`.
        r   r#  r$  r   )parse_intervalformat_intervalr$   Nr   rd   z+Heartbeats unavailable (no active session).r   r  zNo heartbeat set.u     ⏸ Heartbeat paused: r  zNo heartbeat to resume.u     ▶ Heartbeat resumed (every z): >   r  stopclearu     ✓ Heartbeat cleared.r!   everyzevery zT  Usage: /heartbeat every <interval> <prompt>   (e.g. /heartbeat every 10m Check CI)z0Also: /heartbeat status | pause | resume | clear)MIN_INTERVAL_SECONDSu$     Interval too small — minimum is zs.uI     Usage: /heartbeat every <interval> <prompt> — the prompt is required.z  Invalid heartbeat: u     ♥ Heartbeat set (every u   Fires as a normal turn whenever the session is idle and the interval has elapsed. /heartbeat pause | resume | clear to manage; lives only while this Hermes process runs — use `hermes cron` for durable schedules.)r   r#  r$  r   hermes_cli.heartbeatr  r  r9  r:   r;   r<   _get_heartbeat_managerstatus_liner  rr  r  _start_heartbeat_watchdoginterval_secondsr  r  r  ro   )rG   r   r#  r$  r   r  r  rJ   rt   r<   rH   r  r  intervalrr  r  r   s                    rW   _handle_heartbeat_commandz*CLICommandsMixin._handle_heartbeat_command_
  s    	,+++++++++HHHHHHHH!!##))$22"%e**q..eAhnnb		))++;GPPP$PPQQQF 	ex''G,**,,---FGIIKKE}:T::D::;;;;A5<AABBBFHJJLLE}@T@@$@@AAAA..000t//%J`:a:attfkfrttuuuF,,,yy{{ <23333:T::D::;;;F 4## 	WfQioo''722s6{{a7G7G%~&:vay&:&:;;H"%f++//VAYYrFF 	W%~fQi00H5=V(Q,,SVAY)//111TVFGjkkkGUUUtUUVVVFa<<AAAAAAGS;OSSSTTTF||~~ 	G_```F	GGFH--EE 	 	 	G1C11222FFFFF	 	&&(((hooe>T.U.UhhZ_Zfhhiii( ( ( "&( (	
 	
 	
 	
 	
s   K6 6
L LLc                x   ddl m}m}m} |pd                                                    dd          }t          |          dk    r|d                                         nd}t          | dd          }| |d| d|            dS t          t          | d	d          pg           }|s |d| d
|            dS dt          |dt                                v }		 |
                    |d|	|pd           n&# t          $ r}
 |d|
            Y d}
~
dS d}
~
ww xY w|rd| dnd} |d| d           dS )u  Dispatch /refine — run the memory/skill review fork on demand.

        Same machinery as the automatic post-turn self-improvement loop
        (``AIAgent._spawn_background_review``), but user-triggered and with
        optional focus instructions. Writes go to the memory + skill stores
        in a background fork; the live conversation and prompt cache are
        never touched.
        r   r  r$   Nr   r   rd   u/   Nothing to refine yet — send a message first.rE   u4   Nothing to refine yet — the conversation is empty.skill_managevalid_tool_namesT)messages_snapshotreview_memoryreview_skillsfocusz  /refine failed to start: z	 (focus: rF  u3     ⚗ Reviewing this conversation in the backgroundu9    — any memory/skill updates will be reported when done.)r   r#  r$  r   r9  r:   r;   r   r   r  _spawn_background_reviewr   )rG   r   r#  r$  r   rJ   r  r   snapshotr  r   tails               rW   _handle_refine_commandz'CLICommandsMixin._handle_refine_command
  s    	,+++++++++!!##))$22$'JJNNa   gt,,=GTTTdTTUUUF&<dCCIrJJ 	GYYYSWYYZZZF&'%9KSUU*S*SS		**"*"+mt	 +      	 	 	G7#77888FFFFF	 (-4#5####"D$ D D D	
 	
 	
 	
 	
s   C; ;
DDD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    r|                                }
|
 |d| d|            n~ |d|
j                    |                                }d}|r.	 | j                            |           d}n# t&          $ r Y nw xY w|r |d| d|            n |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-# t2          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'k    s|                    d(          rP|t          d'          d                                         }|                                }|r|d)k    r9|                                                                D ]} |d|            dS |                    d*          r|t          d+          d                                         }	 |                    |          }n-# t2          t.          f$ r} |d,|            Y d}~dS d}~ww xY w |d-|j         d |j         d.|j          d/           dS |                    d0          s|                    d1          r|                    dd          d                                         }	 |!                    t-          |                    }n3# t2          t.          tD          f$ r} |d2|            Y d}~dS d}~ww xY w |d3|            dS |d4k    rX	 |#                                }n&# t2          $ r} |d5|            Y d}~dS d}~ww xY w |d6| d7|dk    rd8nd d9           dS  |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 ]} |dA|             |d| dB|
)                                rdCnd dD|            	 | j                            |
j                   dS # t&          $ r Y dS w xY w)EzXDispatch /goal subcommands: set / draft / show / gate / status / pause / resume / clear.r   r  r$   Nr   rd   &Goals unavailable (no active session).r   r  draftz2  Usage: /goal draft <objective in plain language>r  zuser-pausedr   zNo goal set.u     ⏸ Goal paused: r  zNo goal to resume.u     ▶ Goal resumed: FTu(   Continuing now — taking the next step.z+Send any message to kick off the next step.>   r  r  r  u     ✓ 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  rF  u     ⏳ Goal parked on pid z. Loop pauses until it exits.unwaitu1     ▶ Wait barrier cleared — goal loop resumes.zNo wait barrier set.gatezgate r   zadd r  z  /goal gate add: u     ⚿ Gate added: $ z
 retries, z6s timeout). It must pass before the goal can complete.zremove zrm z  /goal gate remove: u     ✓ Gate removed: $ r  z  /goal gate clear:      ✓ Cleared z gater   r   z?  Usage: /goal gate [list | add <command> | remove <N> | clear])parse_contractcontract  Invalid goal:      ⊙ Goal set (-turn budget): zCompletion contract:r   z9After each turn, a judge model checks if the goal is donez against the contract abovez. Hermes keeps working until it is, you pause/clear it, or the budget is exhausted. Use /goal status, /goal show, /goal pause, /goal resume, /goal clear.),r   r#  r$  r   r9  r:   r;   _get_goal_managerr<   r  render_contractr  _handle_goal_draftr  r   r  next_continuation_promptr  r  r   has_goalr  r   ro   wait_onRuntimeErrorstop_waitingrender_gatesrB   add_gater   max_retriestimeout_secondsremove_gater  clear_gateshermes_cli.goalsr  r  is_emptyrO  has_contractr  render_block) rG   r   r#  r$  r   rJ   rt   rH   r<   	objectiver  rr  queuedhadwait_argwtokenspidr-   r   rtxtgate_arg
gate_lowerr   r   r  idx_textr  prevr  headliner  	goal_texts                                    rW   _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;;<<<
 5577 +//777!%$    GUUUtUUVVVVGTTTTdTT   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
 F??e..w77?3v;;<<(..00H!))J zV33,,..99;; ) )DGKKK(((($$V,, "3u::;;/5577<<00DD$j1   G666777FFFFF B4< B B(B B484HB B B  
 $$Y// :3H3H3O3O #>>$2215;;==!ooc(mm<<GG$j*=   G9C99:::FFFFF :::;;;W$$??,,DD#   G8388999FFFFF OOO4199CC"OOOPPPGUVVV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	s   H3 3
I ?I "L8 8MMN O-OO8T T8T33T8:"W X4XX'X< <
YYY$-[ 
[5[00[5_   
__r  c                h   ddl m}m}m} ddlm} |                                 }| |d| d|            dS  |d| d|            	  ||          }nK# t          $ r>}ddl}	|		                    t                                        d|           d}Y d}~nd}~ww xY w	 |                    ||	          }
n&# t          $ r} |d
|            Y d}~dS d}~ww xY w |d|
j         d|
j                    |
                                r_ |d| d|            |
j                                                                        D ]} |d|             |d| d|            n |d| d|            	 | j                            |
j                   dS # t          $ r Y dS w xY w)zDraft a structured completion contract from a plain objective and
        set it as the active goal. Falls back to a bare goal if the aux model
        can't produce a contract.r   r  )draft_contractNrd   r  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.)r   r#  r$  r   r  r(  r  r   logging	getLoggerrT  debugr  ro   rO  r   r  r  r  rB   r  r  )rG   r  r#  r$  r   r(  rH   r  r   _loggingr  r   s               rW   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                Z   ddl m}m}m} |pd                                                    dd          }t          |          dk    r|d                                         nd}|                                 }| |d| d|            dS ddlm	}  |||          }	|	
                    d	          pd                                D ]}
 |d|
            |	
                    d
          r=	 ddlm}  ||j                  r |d| d|            dS dS # t          $ r Y dS w xY wdS )u   Dispatch /loop — recurring in-session wakeups (Claude Code parity).

        Forms:
          /loop [interval] <prompt> [--times N] [--until <cond>]   start a loop
          /loop status | pause | resume | stop                     controls
        r   r  r$   Nr   rd   z&Loops unavailable (no active session).)dispatch_loop_commandr   created)goal_blocks_loop_tickuo   Note: an active /goal is driving this session — loop wakeups defer until the goal finishes, pauses, or parks.)r   r#  r$  r   r9  r:   r;   _get_loop_managerhermes_cli.loopsr.  rA   rB   r0  r   r   )rG   r   r#  r$  r   rJ   rt   rH   r.  rR   r   r0  s               rW   _handle_loop_commandz%CLICommandsMixin._handle_loop_command  s    	,+++++++++!!##))$22"%e**q..eAhnnb$$&&;GKKKTKKLLLF::::::&&sC00ZZ))/R;;== 	! 	!DGKKK    ::i   
		BBBBBB((88 G_T _ _X\_ _     
    
	 
	s   /'D 
D('D(c                   ddl m}m}m} |pd                                                    dd          }t          |          dk    r/d                    |dd                                                   nd}|                                 }| |d| d	|            dS |	                                s |d| d
|            dS |sB |d|
                                             |d|                                            dS |                    dd          }|d                                         }	t          |          dk    r|d                                         nd}
|	dk    r|
s |d           dS 	 t          |
                                d                   }n# t          $ r  |d           Y dS w xY w	 |                    |          }n-# t           t"          f$ r} |d|            Y d}~dS d}~ww xY w |d| d|            dS |	dk    rl	 |                                }n&# t"          $ r} |d|            Y d}~dS d}~ww xY w|r |d| d|dk    rdnd d           n |d| d|            dS 	 |                    |          }n-# t          t"          f$ r} |d|            Y d}~dS d}~ww xY w|j        rt          |j        j                  nd} |d| d|            dS )u  Dispatch /subgoal subcommands.

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

        Subgoals are extra criteria the user adds mid-loop. They get
        appended to both the judge prompt (verdict must consider them)
        and the continuation prompt (agent sees them) on the next turn
        boundary. No special kick — the running turn finishes, the next
        judge call includes them.
        r   r  r$   Nr!   r   r   rd   r  z*No active goal. Set one with /goal <text>.r  z  Usage: /subgoal remove <n>z:  /subgoal remove: <n> must be an integer (1-based index).z  /subgoal remove: u     ✓ Removed subgoal r,   r  z  /subgoal clear: r   z subgoalr   r   zNo subgoals to clear.z  /subgoal: u     ✓ Added subgoal )r   r#  r$  r   r9  r:   r;   rC   r  r  r  render_subgoalsr<   r   ro   remove_subgoalr  r  clear_subgoalsadd_subgoalr  subgoals)rG   r   r#  r$  r   rJ   rt   rH   r  rj  r  r   r  r   r#  r|   s                   rW   _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   )rH  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    ●rd   r5  r9  r  rF  r$   z   r   u    — r  z
  Usage: /skin <name>z$  Custom skins: drop a YAML file in z/skins/
c                    h | ]
}|d          S r   rQ  )r   r   s     rW   r  z8CLICommandsMixin._handle_skin_command.<locals>.<setcomp>L  s    5551QvY555rY   z  Unknown skin: z  Available: r/   zdisplay.skinz  Skin set to: z (saved)z8  Note: banner colors will update on next session start.z  Prompt + TUI colors updated.)r   rH  r,  rs  r<  r=  r>  ImportErrorr4   r9  r:   r;   r	   r<   rC   sortedr  _apply_tui_skin_style)rG   r   rH  r,  r<  r=  r>  rJ   r  skinsr   rq  r5  new_skin	availables                  rW   _handle_skin_commandz%CLICommandsMixin._handle_skin_command3  s   22222222	``````````` 	 	 	.///FF	 		!!1!--u::>>q!1!1>**,,GJLLE0w00111&''' Q Q#$V9#7#7T01(v0E0E,ak,,,,2OFOOQvYOOOQ}=MOOPPPP+,,,Y9L9N9NYYYZZZF8>>##))++55

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

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

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

        Opens the user's editor on a temporary markdown file (optionally
        seeded with text passed after the command), then queues the saved
        buffer as the next agent turn via the one-shot ``_pending_agent_seed``
        the interactive loop already consumes (same path as /blueprint).
        r   r  r$   Nr   rd   z(>_<) Could not open editor: u$   (._.) Empty prompt — nothing sent.)
r   r#  r$  r   r9  r:   r;   ra  r   r  )	rG   r  r#  r$  r   initialrJ   composedr   s	            rW   _handle_prompt_compose_commandz/CLICommandsMixin._handle_prompt_compose_command  s    	,+++++++++#**,,224;;u::>>AhG	..w77HH 	 	 	GGGGCGGGHHHFFFFF	  	GIII4IIJJJF $,   s   A) )
B3BBc           
     @   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_moder^   r   r%   rk   rd   r6   disabled)r6   rt  )r   r   r,  hermes_cli.colorsri  hermes_cli.focus_viewrj  rk  rl  rm  rn  ro  r9  r:   r;   r   ry   r   	partitionGREENDIMBOLDRESETrr  _set_tool_progress_moderp  _focus_hidden_linesr  )rG   r  r   r,  _Colorsrj  rk  rl  rm  rn  ro  rt   rJ   r  r  r  restore_modebodyr_   r  r  rv   r  state_colorr  messagewords                              rW   _handle_focus_commandz&CLICommandsMixin._handle_focus_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%: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	rb   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   )rn  r   N)rv  rn  rs  r   r   )rG   rb   rn  r  r   s        rW   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.
        rp  FNr   )would_display_tool_linerr  _focus_last_counted_toolr}  r   )r   rv  r  r  r   r}  )rG   r  r  rp  lasts        rW   _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   rY   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   Nrp  F)format_hidden_liner  rd   )r   r   r}  r  rv  r  r   r#  r$  r   r   )rG   countr  r   r#  r$  r   s          rW   _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   rd   )r   r   hermes_cli.approval_moder  r9  r:   r;   r  )rG   r  r   r  rJ   	requestedrR   s          rW   _handle_approvals_commandz*CLICommandsMixin._handle_approvals_command?  s    FFFFFF#**,,224;; #E

QE!HHD	**955%V^%%&&&&&rY   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   rg  rb  rh  r$   Nr   rx  runtime_footerr6   Ffields)r6  context_pctrI   >   r   r   ONOFFrd   zRuntime footer:r   z
  Fields: r/   >   1r  truerY  T>   0r  falserZ  z   Usage: /footer [on|off|status]zdisplay.runtime_footer.enabledz  Runtime footer: z6  Failed to save runtime_footer setting to config.yaml)r   r   r,  rf  rc  ru  ri  r9  r:   r;   r<   r   rA   ry   rz  r{  rC   rx  ry  )rG   r  r   r,  rc  r~  rt   rJ   cfg
footer_cfgr  r  r  	new_states                 rW   _handle_footer_commandz'CLICommandsMixin._handle_footer_commandI  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   rg  rh  r$   Nr   show_timestampsF>   r   r   r  r  rd   zMessage timestamps:r   >   r  r  r  rY  T>   r  r  r  rZ  z$  Usage: /timestamps [on|off|status]zdisplay.timestampsz  Message timestamps: z2  Failed to save timestamps setting to config.yaml)r   r   r,  ru  ri  r9  r:   r;   r<   r   ry   r   rz  r{  r  rx  ry  )
rG   r  r   r,  r~  rt   rJ   r  r  r  s
             rW   _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_CONFIGrH  r#  r$  r   _parse_reasoning_configr,  r   r/  r!   Nzmedium (default)r6   Fznone (disabled)effortmediumu   on ✓r  reasoning_fullfullzclamped to 10 linesrd   zReasoning effort:  zReasoning display: r  rF  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  NrQ  r   r  s     rW   r  z=CLICommandsMixin._handle_reasoning_command.<locals>.<genexpr>  s:         999 9999 rY   >   r  r  Tzdisplay.show_reasoningu!   ✓ Reasoning display: ON (saved)z>  Model thinking will be shown during and after each response.>   r  hideu"   ✓ Reasoning display: OFF (saved)>   r^   r  zdisplay.reasoning_fullu#   ✓ Reasoning display: FULL (saved)z;  The post-response recap box will print complete thinking.uC     Note: reasoning display is OFF — run /reasoning show to see it.>   clampshortcollapseu2   ✓ Reasoning display: CLAMPED to 10 lines (saved)(._.) Unknown argument: 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 're  z$' (session only; config save failed)u,   ' (this session — use --global to persist))r   r  rH  r#  r$  r   r  r,  r9  r:   r;   r3  rA   show_reasoningr   r<   rC   r   _current_reasoning_callbackreasoning_callbackr  r   r   )rG   r   r  rH  r#  r$  r   r  r,  rJ   rcleveldisplay_state
full_statert   
arg_tokensexplicit_globalparsed	agent_cfgs                      rW   _handle_reasoning_commandz*CLICommandsMixin._handle_reasoning_command  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wrY   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   rH  r#  r$  r   r,  r   r/  r!   r   rd   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 're  rf  )r   rH  r#  r$  r   r,  r9  r:   r;   r<   busy_input_mode)rG   r   rH  r#  r$  r   r,  rJ   	_behaviorrt   behaviors              rW   _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ZrY   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_STYLESrx  tui_status_indicatorr   r/  r!   r   rd   zBusy-indicator style: zUsage: /indicator [|r  Nz(._.) Unknown indicator style: zdisplay.tui_status_indicatoru!   ✓ Busy-indicator style set to 're  z2The TUI picks up the new style on its next render.rf  )r   rH  r#  r$  r   r,  r   r  r  ra  rA   r9  r:   r;   r<   rC   r  )rG   r   rH  r#  r$  r   r,  r  r  stylesr  rJ   rt   s                rW   _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\^^_____rY   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   r6  zAnthropic Fast ModezPriority Processingz	Fast moder   r/  r!   r   priorityfastnormalrd   r,   z,Usage: /fast [normal|fast|status] [--global]r  r   c              3  "   K   | ]
}|d v|V  dS r  rQ  r  s     rW   r  z8CLICommandsMixin._handle_fast_command.<locals>.<genexpr>  s:       
 
555 5555
 
rY   >   r  r  FAST>   r  r  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))r   rH  r#  r$  r   r,  _fast_command_availablehermes_cli.modelsr  r   r   r9  r:   r;   r<   rB  rC   r   )rG   r   rH  r#  r$  r   r,  r  r   r6  feature_namerJ   r   r  r  rt   saved_valuerv   s                     rW   _handle_fast_commandz%CLICommandsMixin._handle_fast_commandf  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 rQ  )r<   r  s     rW   r  z9CLICommandsMixin._handle_debug_command.<locals>.<setcomp>  s     ===q===rY   r   Nlocalnous      T)r`  expirer  r  yes)hermes_cli.debugr  typesr  r:   )rG   r  r  r  wordsr  r  rK   s           rW   _handle_debug_commandz&CLICommandsMixin._handle_debug_command  s     	544444))))))==L$6$6$8$8$<===5 ,u9 au4T
 
 
 	rY   c                   ddl m}m}  |            rt          d |d                      dS ddg}|                     dd	|
          }|t          d           dS |                     ||          }|dk    rt          d           dS t                       t          d           t                       dg| _        dS )u  Handle /update — update Hermes Agent to the latest version.

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

        Returns ``True`` when the update was confirmed (caller should trigger
        app exit so the relaunch is deferred to the main thread after
        prompt_toolkit cleans up terminal modes).  Returns ``False`` / falsy
        when cancelled.
        r   )
is_managedformat_managed_messageu     ✗ zupdate Hermes AgentF)oncez
Update Nowz0exit the current session and update Hermes Agent)cancelCancelzkeep the current sessionu   ⚕  Update Hermes Agentz;This will exit the current session and run `hermes update`.)r  r  choicesNu     🟡 /update cancelled.r  u     ⚕ Launching update...r  T)rf  r  r  r4   _prompt_text_input_modal_normalize_slash_confirm_choice_pending_relaunch)rG   r  r  r  r_  choices         rW   _handle_update_commandz'CLICommandsMixin._handle_update_command  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)*** #+trY   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)r   r   r9  r:   r;   r<   _enable_voice_mode_disable_voice_mode_toggle_voice_tts_show_voice_status_voice_moderG   r   r   rJ   ri  s        rW   _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8rY   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)r   r   r9  r:   r;   r<   _start_wake_word_listener_persist_wake_word_enabled_stop_wake_word_listenerr   _show_wake_word_statusr  s        rW   _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3rY   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_configr6   Nzwake_word.enabledz
Wake word rt  z in config (wake_word.enabled: r   )r   r   r#  r$  r,  tools.wake_wordr  ry   rA   r   r   r<   )rG   r6   r   r#  r$  r,  r  s          rW   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   )rI   r   rs   ry   rd  )r  r   r}   r~   )r  r   )r   r   )r  r   r}   ry   )r*  r   r6   ry   )r   r   r}   r~   )r  r   r}   r~   )r$   )rG  r   r}   r   )rb   r   r}   r~   )r  r   r}   r~   )r}   r~   rS  )r6   ry   )ArT  rU  rV  __doc__rX   rx   rp   rr   r   r   r   r   r  r!  r,  r;  rF  rk  ry  r  r  r  r-  rZ  rs  r  r  r  r  r  r  r  r  r  r   r)  r
  r  r  r  r  r  r&  r	  r3  r:  rF  ra  re  r  r|  r  r  r  r  r  r  r  r  r  r  r  r  r  r  rQ  rY   rW   r   r   +   s        }. }. }. }.~L( L( L( L(\&( &( &( &(P    UU UU UU UUn# # # #>)1 )1 )1 )1V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`  o o o obC2 C2 C2 C2J6 6 6 6BG8 G8 G8 G8R_9 _9 _9 _9BK K K KZ8M 8M 8M 8MtN] N] N] N]`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V V V VpS
 S
 S
 S
j'
 '
 '
 '
Ry y y yv, , , ,\   B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rY   r   )#r  
__future__r   r  r7   r{  r  r  rI  r   urllib.parser   richr   rw  rich.markupr   r  
rich.panelr   r   r	   r
   r'  agent.turn_contextr   hermes_cli.browser_connectr   r   r   r   r   r   r   r   rQ  rY   rW   <module>r     s    # " " " " "  				 



             ! ! ! ! ! !             ) ) ) ) ) )       U U U U U U U U : : : : : :                 D<K D<K D<K D<K D<K D<K D<K D<K D<K D<KrY   