
    `gjk                       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"y)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                  d   e Zd ZdZd.dZd.dZd Zd Zd/dZd Z	d/dZ
d0d	Zd1d
Zd Zd2dZd/dZd/dZd/dZd1dZd1dZd1dZd1dZd1dZd1dZd1dZd1dZd1dZd1dZd1dZd3dZd1dZd4dZd1dZ d4dZ!d5d Z"d4d!Z#d1d"Z$d6d7d#Z%d/d$Z&d/d%Z'd/d&Z(d1d'Z)d1d(Z*d1d)Z+d6d0d*Z,d8d+Z-d.d,Z.y-)9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.
    c           	        ddl m} t        | d      r| j                  st	        d       y| j                  j
                  }|j                  s"t	        d       t	        d       t	        d       yt        j                  d	t        j                               }|j                         }t        |      d
kD  r|d
d ng }|s$|j                  |      }t	         |||             y|d   j                         dk(  r)t        |      dk  rt	        d       y|j                  |      }|st	        d|        y| j                  |d
   |      }|sy|j                  ||      }	|	d   r|	j!                  dd      }
|	j!                  dd      }|
s|st	        d       y|
rt	        d|
        |re|j#                         }t        |      dkD  r9t	        dj%                  |dd              t	        dt        |      dz
   d       yt	        d|        yt	        d|	d           y|j                  |      }|st	        d|        y| j                  |d   |      }|syt        |      d
kD  r|d
   nd}|j'                  |||      }	|	d   rj|rt	        d| d|	d    d|	d           nt	        d|	d    d|	d           t	        d        | j(                  r| j+                  d!"       t	        d#       yyt	        d|	d           y)$u  Handle /rollback — list, diff, or restore filesystem checkpoints.

        Syntax:
            /rollback                 — list checkpoints
            /rollback <N>             — restore checkpoint N (also undoes last chat turn)
            /rollback diff <N>        — preview changes since checkpoint N
            /rollback <N> <file>      — restore a single file from checkpoint N
        r   )format_checkpoint_listagentz  No active agent session.Nz  Checkpoints are not enabled.z#  Enable with: hermes --checkpointsz3  Or in config.yaml: checkpoints: { enabled: true }TERMINAL_CWD   diff   z  Usage: /rollback diff <N>z  No checkpoints found for successstat z#  No changes since this checkpoint.
P   z
  ... (z more lines, showing first 80)u     ❌ error)	file_pathu     ✅ Restored z from checkpoint restored_to: reasonu     ✅ Restored to checkpoint z2  A pre-rollback snapshot was saved automatically.F)prefillz0  Chat turn undone to match restored file state.)tools.checkpoint_managerr   hasattrr   print_checkpoint_mgrenabledosgetenvgetcwdsplitlenlist_checkpointslower_resolve_checkpoint_refr   get
splitlinesjoinrestoreconversation_history	undo_last)selfcommandr   mgrcwdpartsargscheckpointstarget_hashresultr   r   
diff_linesr"   s                 P/root/.hermes/venv/lib/python3.12/site-packages/hermes_cli/cli_commands_mixin.py_handle_rollback_commandz)CLICommandsMixin._handle_rollback_command3   s    	DtW%TZZ./jj(({{2378GHii		4JNuQRy..s3K(c:; 7==?f$4y1}34..s3K3C59:66tAwLKXXc;/Fi zz&"-zz&"-D?@  4&k*%)__%6
z?R/!$))JsO"<=!Ic*o.B-CCa"bc
  "Btf+.  vg/01 **3//u562247KH  #4y1}DG$	S+C)	{2CF=DYCZZ\]cdl]m\nop5f]6K5LBvV^O_N`abFG ((u-HI ) F6'?+,-    c                   ddl m}m}m}m} ddlm} |j                         }t        |      dkD  r|d   j                         nd}|dv r |       }	|	st        d       t        d       y	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 ]  \  }
}|j                  dd      }|dk  r| d}n|dk  r
|dz  d d!}n|dz  dz  d"d#}|j                  d$      xs d%}t        d|
d&d|d'   dd|j                  d(d      dd|dd| 
        y	|d)k(  rJt        |      d*kD  rdj                  |d*d	       nd	} ||+      }|rt        d,|        y	t        d-       y	|d.v rt        |      d/k  r+t        d0        |d1      }	|	rt        d2|	d   d'           y	|d*   }	 t        |      } |       }	d|cxk  rt        |	      k  rn n|	|dz
     d'   }nt        d3t        |	       d4       y		  ||      rt        d5|        t        d6       y	t        d7|        y	|d8k(  r;d9}t        |      d*kD  r	 t        |d*         } ||;      }t        d<| d=| d>       y	t        d?|        t        d@       y	# t        $ r Y w xY w# t        $ r t        d:       Y y	w xY w)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>   lsrM   z  No state snapshots yet.z&  Create one: /snapshot create [label]Nz  State snapshots (z/state-snapshots/):
  #z>3IDz<35 Filesz>5Sizez>10Labelu	   ───ui   ───────────────────────────────────u   ─────u   ──────────u<   ────────────────────
total_sizei   z Bi   z.0fz KBz.1fz MBlabelr   3id
file_countcreater   )rW   z  Snapshot created: z#  No state files found to snapshot.>   rewindr7      z(  Usage: /snapshot restore <snapshot-id>limitz  Most recent: z!  Invalid snapshot number. Use 1-.z  Restored state from: z:  Restart recommended for state.db changes to take effect.z  Snapshot not found: prune   z%  Usage: /snapshot prune [keep-count])keepz	  Pruned z old snapshot(s) (keeping ).z  Unknown subcommand: z?  Usage: /snapshot [list|create [label]|restore <id>|prune [N]])hermes_cli.backuprH   rI   rJ   rK   hermes_constantsr	   r/   r0   r2   r)   	enumerater4   r6   int
ValueError)r:   r;   rH   rI   rJ   rK   r	   r>   subcmdsnapsissizesize_strrW   snap_ididxrc   deleteds                      rD   _handle_snapshot_commandz)CLICommandsMixin._handle_snapshot_command   sU   	
 	
 	9%(Z!^q!^#(*E12>?'(;(='>>STUBs2hbc
!GB<qAgYOPBwir(1WIQxj(LM!%+ 	d1uu\1-$;"&r{HK'"&+c!2#6H"&+"4S!9=Hg,"1Q%r!D'#alA0Fr/J!HUX>YZ[`Zabc	d x+.u:>CHHU12Y'tE+%8G,WI67;<,,5zA~@A,15OE!HTN+;<=AhG	'l,.)s5z)#C!GnT2G=c%j\KL  &g./y9:RS.wi89wD5zA~uQx=D ,6GIgY&@bIJ *6(34ST+   " ABs%   AJ5 1K 5	K KKKc                   ddl m} |j                         }|D cg c]  }|j                  d      dk(  s| }}	 ddlm}m}  |       }|s|st        d       y|r7t        dt        |       d	       |j                         }t        d
| d       |r| |d      }	t        d|	 d       yyyc c}w # t        $ r d}d}Y |w xY w)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_registrystatusrunning)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_registryru   list_sessionsr4   tools.async_delegationrx   ry   	Exceptionr)   r0   kill_all)
r:   ru   	processesprw   rx   ry   n_asynckilledstoppeds
             rD   _handle_stop_commandz%CLICommandsMixin._handle_stop_command   s     	<$224	'H155?i+G1HH	!J"nG
 w67KG~-GHI%..0FN6(-89}0#73G&wi/IJK 17' I  	!G M	!s   B3B3B8 8CCc           
     x   ddl m} ddlm}m} |j                         }|D cg c]  }|j                  d      dk(  s| }}|D cg c]  }|j                  d      dk7  s| }} |dt        |              |D ]P  }|j                  dd      d	d
 } ||j                  dd            }	 |d|j                  dd       d|	 d|        R |r |dt        |              	 ddlm	}
  |
       }|D cg c]  }|j                  d      dk(  s| }}|re |dt        |       d       |D ]K  }|j                  d      xs dd	d } |d|j                  dd       d|j                  dd       d|        M t        | dd      } |d|rdnd        y	c c}w c c}w # t        $ r g }Y w xY wc c}w )u>   Handle /agents — show background processes and agent status.r   _cprint)format_uptime_shortru   rv   rw   z  Running processes: r;   r   Nr    uptime_seconds    
session_id?u    · z  Recently finished: )list_async_delegationsz  Background delegations: z runninggoal<   delegation_id_agent_runningFz	  Agent: idle)clir   r{   r   ru   r|   r4   r0   r}   r   r~   getattr)r:   r   r   ru   r   r   rw   finishedcmdupr   delegationsd	running_dr   agent_runnings                   rD   _handle_agents_commandz'CLICommandsMixin._handle_agents_command	  s   P$224	'H155?i+G1HH(I!AEE(Oy,HAII'G~67 	HA%%	2&s+C$QUU+;Q%?@Bd155s34DDFG	H
 +CM?;<	E02K !,L1quuX)/KQL	L0Y0@IJ  f+Sb1155#67tuuXs+,D8  &6>)IFCDE; II  	K	Ls4   FFF!!F!'F& 8F7F7&F43F4c                ~   ddl }ddl}ddl}ddlm} ddlm} ddlm} |j                  dd      } ||       |j                  dd	      }		 |j                  t        |	      d	kD  r|j                  |	d	         ng       }
t        |
d
d      dv }	 |r|
j                  |
       yd|
_        |j#                         } ||      5  |
j                  |
       ddd        ||j%                         j'                  d             y# t        $ r Y yw xY w# 1 sw Y   >xY w# t(        $ r} |d|        Y d}~yd}~ww xY w)ur  Handle /journey — the learning timeline (see `hermes journey`).

        The read-only views (default + ``list``) render Rich color, which
        patch_stdout would swallow as raw escapes; capture with forced ANSI and
        re-emit through ``_cprint``. ``delete``/``edit`` are interactive
        (confirm prompt / ``$EDITOR``) so they keep the real stdio.
        r   Nredirect_stdoutr   )register_cliz/journeyF)progadd_helpr   journey_action)deleteeditTr   z  /journey failed: )argparseioshlex
contextlibr   r   r   hermes_cli.journeyr   ArgumentParserr/   
parse_argsr0   
SystemExitr   funcforce_colorStringIOgetvaluerstripr~   )r:   cmd_originalr   r   r   r   r   r   parserrestr?   interactivebufexcs                 rD   _handle_journey_commandz(CLICommandsMixin._handle_journey_command.  s-    	.3((j5(IV!!$*	$$SY]U[[a%9PRSD d$4d;?QQ
	1		$#D++-C %  		$ CLLN))$/0  		     	1)#/00	1sH   3D D $D D-D 	DDDD 	D<'D77D<c                   ddl m}m}m}m} t               r |d| d |        |        yddlm}  |       rA| j                         r"t        | j                        } |d| d       y |d| d	|        y |d| d
|        y)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_pathrO   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_imager0   _attached_images)r:   r   r   r   r   r   ns          rD   _handle_paste_commandz&CLICommandsMixin._handle_paste_commandS  s     	HG!#TF F-/08
 < //1--..+CDE"TF"TUYTZ[\b?vFGrF   c                *   ddl m}m} |j                  d      }t	        |      dkD  r|d   j                         nd}| j                  D cg c]  }|j                  d      dk(  s| }}|s	 |d       y	|r8	 t        |      dz
  }|dk  s|t	        |      k\  rv |dt	        |       d       y	t	        |      dz
  }|dk\  r? |||   j                  d            s%|dz  }|dk\  r |||   j                  d            s%|dk  r	 |d       y	 |||   j                  d            }	|	s	 |d       y		 | j                  |	        |d|dz    d       y	c c}w # t        $ r  |d
       Y y	w xY w# t        $ r}
 |d|
        Y d	}
~
y	d	}
~
ww xY w)u=   Handle /copy [number] — copy assistant output to clipboard.r   )_assistant_copy_textr   r   maxsplitr   role	assistantz  Nothing to copy yet.Nz  Usage: /copy [number]z!  Invalid response number. Use 1-r`   contentz-  Nothing to copy in assistant responses yet.z-  Nothing to copy in that assistant response.z  Copied assistant response #z to clipboardz  Clipboard copy failed: )r   r   r   r/   r0   stripr8   r4   rh   ri   _write_osc52_clipboardr~   )r:   r   r   r   r>   argmr   rq   textes              rD   _handle_copy_commandz%CLICommandsMixin._handle_copy_commandm  s   5""A"."%e*q.eAhnnb $ 9 9Z1QUU6]k=YQZ	Z,-#hl Qw#Y/;C	N;K1MNi.1$C(#7	#8J8J98U#Vq (#7	#8J8J98U#VQwGH#IcN$6$6y$ABCD	5''-3C!G9MJK; [  12,  	5/s344	5s6   E&E:E 7 E4 E10E14	F=FFc                ^   ddl m}m}m}m}m}m}m} d|v r#|j                  dd      d   j                         nd}	|	s$t               r |       nd}
 |d| d	|
 |        y ||	      \  }} ||      }| |d| d
| |        y|j                  j                         |vr |d| d|j                   |        y| j                  j                  |        |d|j                          |r |d| d| |        yt               r" |d| d ||j                         d|        yy)uG   Handle /image <path> — attach a local image file for the next prompt.r   )r   _IMAGE_EXTENSIONSr   r   _resolve_attachment_path_split_path_inputr   rR   Nr   r   z/path/to/image.pngrO   z"Usage: /image <path>  e.g. /image z(>_<) File not found: z"(._.) Not a supported image file: u     📎 Attached image: z<Now type your prompt (or use --image in single-query mode): z;Tip: type your next message, or run hermes chat -q --image z "What do you see?")r   r   r   r   r   r   r   r   r/   r   r   suffixr2   namer   append)r:   r   r   r   r   r   r   r   r   raw_argshint
path_token
_remainder
image_paths                 rD   _handle_image_commandz&CLICommandsMixin._handle_image_command  s    	H  	H  	H>A\>QL&&tQ/288:WY3I3K-/QeDb@tfMN!28!<
J-j9
b4ZLGH""$,==b@@QRVQWXY$$Z0)*//):;<bZ[eZfgkflmn#%bYZtu  vE  vE  [F  ZG  G\  ]a  \b  c  d &rF   c                    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}	 |j                  |      }t!        |      d	kD  r|d	   nd
}	|	dvr j#                          y|	dk(  r | |dd             y|dd }
|
s.t%        d|	 d       t%        d|	 d       t%        d|	 d       y|	dk(  rdnd}dj'                  |
      } | | d| d|         | ||	|
d             ddlm} ddlm}  | |       d       _         j1                           | d|        y# t        $ r |j                         }Y w xY w)!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_commandc                    t        dd      	 |        y G d d      } |       } |      5   |        ddd       |j                         j                         D ]
  } |        y# 1 sw Y   5xY w)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y)MCLICommandsMixin._handle_tools_command.<locals>._run_capture.<locals>._TTYBufc                     y)NT )r:   s    rD   isattyzTCLICommandsMixin._handle_tools_command.<locals>._run_capture.<locals>._TTYBuf.isatty  s    rF   Nreturnbool)__name__
__module____qualname__r   r   rF   rD   _TTYBufr     s     rF   r   )r   r   r5   )	nsr   r   liner   r   r   r:   r   s	       rD   _run_capturez<CLICommandsMixin._handle_tools_command.<locals>._run_capture  s~     tVT*2,R0
 (   )C % 1,R01113 1 1s   	A//A8r   r   >   rM   enabledisablerM   r   )tools_actionplatformr   z(._.) Usage: /tools z <name> [name ...]z  Built-in toolset:  /tools z webz  MCP tool:          /tools z github:create_issuer   	DisablingEnabling, rR   ...)r   namesr   )_get_platform_toolsload_configz0Session reset. New tool configuration is active.)r   r   r   None)r   r   r   r   r   r   r   r   r   r   r   r   hermes_cli.tools_configr   r/   ri   r0   
show_toolsr)   r6   r   hermes_cli.configr  enabled_toolsetsnew_session)r:   r   r   r   r   r   r   r   r>   
subcommandr   verbrW   r   r  r   r   r   r   s   `              @@@@rD   _handle_tools_commandz&CLICommandsMixin._handle_tools_command  sj    	54&.H	 	6	 KK$E "%UaU1XR
::OOGHab	(4FGH0DAB0<PQR
 )I5{:		% 7)D65'TF34YJeeTU 	@1 3KM5 I4&HOPC  	 IIKE	 s   D9 9EEc                    ddl m} ddlm}  |       } |       }t	                t	        d|        t	        d|        t	                y)z/Display active profile name and home directory.r   rL   )get_active_profile_namez  Profile: z  Home:    N)rf   r	   hermes_cli.profilesr  r)   )r:   r	   r  displayprofile_names        rD   _handle_profile_commandz(CLICommandsMixin._handle_profile_command  s@    8?%'.0L>*+G9%&rF   c           	        ddl m} ddlm} |j	                  d      }t        |      dk  s|d   j                         s |d        |d        |d	       y
|d   j                         j                         }	 ddlm	}m
} 	  ||      }		  |       }
|
j                  j                  |	      }|r|j                   s |d| d       y
|
j#                  |	      }|r|j$                  s |d| d        |d       y
t'        | dd      r	 |d       y
| j(                  s	 ddlm}  |       | _        | j(                  s |d |               y
	 | j(                  j-                  | j.                        }|s8d| j.                  dd  }| j(                  j1                  | j.                  |       d}	 | j(                  j-                  | j.                        }|r|j                  d      xs d}|s| j.                  dd }| j(                  j3                  | j.                  |      }|s	 |d       y
 |d | d!| d"|j4                   d#        |d$       ddl}|j7                         d%z   }d&}|j7                         |k  r	 | j(                  j9                  | j.                        }|xs i j                  d'      xs d&}||k7  r|d(k(  r |d)       |}|d*k(  r/ |d        |d+| d        |d,|         |d       d
| _        y|d-k(  r-|xs i j                  d.      xs d/} |d0|         |d1       y
|j=                  d2       |j7                         |k  r	 | j(                  j?                  | j.                  d3        |d4        |d5       y
# t        $ r} |d|        Y d}~y
d}~ww xY w# t        t        f$ r  |d| d       Y y
w xY w# t        $ r} |d|        Y d}~y
d}~ww xY w# t        $ r Y w xY w# t        $ r} |d|        Y d}~y
d}~ww xY w# t        $ r Y Hw xY w# t        $ r d}Y w xY w# t        $ r Y w xY w)6u  Handle ``/handoff <platform>`` — transfer this CLI session to a gateway platform.

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

        Returns:
            False to signal CLI exit, True to keep going.
        r   r   format_session_db_unavailabler   r   r   z  Usage: /handoff <platform>z@  Hands the current session off to that platform's home channel.z:  The CLI session ends here; resume it later with /resume.T)load_gateway_configPlatformz!  Could not load gateway config: Nz  Unknown platform 'z'.z  Platform 'z+' is not configured/enabled in the gateway.z!  No home channel configured for r`   z6  Set one with /sethome on the destination chat first.r   FzJ  Agent is busy. Wait for the current turn to finish, then retry /handoff.)	SessionDBrO   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: rd   z*  Waiting for the gateway to pick it up...g      N@pendingstaterw   z'  Gateway picked it up; transferring...	completedu5     ↻ Handoff complete. The session is now active on z,  Resume it on this CLI later with: /resume failedr!   zunknown errorz  Handoff failed: zV  Your CLI session is intact. Try /handoff again, or /resume on the platform manually.      ?ztimed out waiting for gatewayzA  Timed out waiting for the gateway. Is `hermes gateway` running?z  Your CLI session is intact.) r   r   hermes_stater  r/   r0   r   r2   gateway.configr  r  r~   ri   KeyError	platformsr4   r+   get_home_channelchat_idr   _session_dbr  get_sessionr   set_session_titlerequest_handoffr   timeget_handoff_state_should_exitsleepfail_handoff)r:   r   r   r  r>   platform_namer  r  r   r   	gw_configpcfghomer  rowplaceholder_titlesession_titleok_timedeadline
last_state	state_rowcurrenterrs                           rD   _handle_handoff_commandz(CLICommandsMixin._handle_handoff_command
  s   " 	 >""A".u:>q!123VWPQa(..0	D
	.H
	+-I
 ""&&x04<<l=/1\]^))(34<<7aHILM 4)51`a 2#,;  b689:;	""..t?C
 '/tr/B.C$D!  224??DUV 	""..t?C # 0 6B  OOBQ/M --doo}Mde'f]O8TXT]T]S^^`ab<= 	::<$&
jjlX%! ,,>>tO	 !B++G4A	G*$i'EF$
+%OP]^_`aF}oVW$(!(" B++G4G,SE23pqKK/ jjlX%4	))$//;Z[ 	ST/0k  	7u=>	 H% 	*=/<=	  	7u=>	4  &  	B3%HI	  		*  ! 	!2  		s   ;N N8 O !O: AP
 3<P+ %P;  &Q 	N5 N00N58OO	O7"O22O7:	PP
	P(P##P(+	P87P8;Q
	Q
	QQc                p
   ddl m}m} |j                  dd      }t	        |      dkD  r|d   j                         nd}t	        |      dk\  rS|d   dk(  r|d   d	k(  s0|d   d
k(  r|d   dk(  s |d   dk(  r|d   dk(  s|d   dk(  r|d   dk(  r|dd j                         }|s; |d       | j                  d      r| j                  d      | _        y |d       yd| _        | j                  sddl
m}  |d |               y|j                         rS| j                  d      }t        |      }|dk  s|t	        |      kD  r |d| d        |d       y||dz
     }	|	d   }
nddlm}  ||      }|xs |}
| j                  j!                  |
      }|s |d|         |d       y	 | j                  j#                  |
      }|r5||
k7  r0 |d|
 d| d       |}
| j                  j!                  |
      }|r|}|
| j&                  k(  r	 |d        y| j&                  }| j(                  r&	 | j(                  j+                  | j,                         	 | j                  j/                  | j&                  d!       |
| _        d"| _        d| _         ||
       | j                  j5                  |
d"#      }|xs g D cg c]  }|j7                  d$      d%k7  s| }}|| _        	 | j                  j9                  |
       | j(                  r|
| j(                  _        | j(                  j;                          t=        | j(                  d&      r$t	        | j,                        | j(                  _        t=        | j(                  d'      r	 dd(l m!}  |       | j(                  _"        t=        | j(                  d)      r| j(                  jG                          	 tI        | j(                  d*d      }||jK                  |
|xs dd+d,       |j7                  d-      r	d.|d-    dnd}t	        | j,                  D cg c]  }|j7                  d$      d/k(  s| c}      }| j,                  rB |d0|
 | d1| d2|dk7  rd3nd d4t	        | j,                         d5
       | jM                          n |d0|
 | d6       | jO                  |       y# t$        $ r |
}Y w xY w# t$        $ r Y w xY w# t$        $ r Y |w xY wc c}w # t$        $ r Y w xY w# t$        $ r Y xw xY w# t$        $ r Y %w xY wc c}w )7uW   Handle /resume <session_id_or_title> — switch to a previous session mid-conversation.r   r   _sync_process_session_idNr   r   r   <>[]"'z-  Usage: /resume <number|session_id_or_title>resumerz   
   r^   zA  Tip:   Use /history or `hermes sessions list` to find sessions.r  rO   z  Resume index z is out of range.z:  Use /resume with no arguments to see available sessions.rY   )_resolve_session_by_name_or_idz  Session not found: zC  Use /history or `hermes sessions list` to see available sessions.z
  Session z was compressed into z/; resuming the descendant with your transcript.z  Already on that session.resumed_otherT)repair_alternationr   session_meta_last_flushed_db_idx_todo_store	TodoStore_invalidate_system_prompt_memory_managerFparent_session_idresetr%   r  z "useru     ↻ Resumed session  ( user messagerm   r   z total)u!    — no messages, starting fresh.)(r   r   r>  r/   r0   r   _show_recent_sessions_list_recent_sessions_pending_resume_sessionsr$  r  r  isdigitrh   hermes_cli.mainrH  r%  resolve_resume_session_idr~   r   r   _flush_messages_to_session_dbr8   end_session_resumed_pending_titleget_messages_as_conversationr4   reopen_sessionreset_session_stater(   rL  tools.todo_toolrO  rM  rP  r   on_session_switch_display_resumed_history_restore_session_cwd)r:   r   r   r>  r>   targetr  sessionsindexselected	target_idrH  resolvedrK  resolved_idresolved_metaold_session_idrestoredr   rO  _mm
title_part	msg_counts                          rD   _handle_resume_commandz'CLICommandsMixin._handle_resume_command  si   9""4+%(Z!^q! v;!AY#&*"3q	S VBZ3%6q	S VBZ3%6q	S VBZ3%6Ab\'')FCD))): 150J0JQS0J0T-WX )-%Bb689:; >>111;HKEqyECM1/%0ABCTU	*H IF5f=H *FI''33I>+F845YZ	$**DDYOK ;)3YK'<[M J@ A $I ,,88CM,'01::

88--	((/J
 $" + ##@@$ A 
 !)BS!155=N3RASS$,!	++I6
 ::$-DJJ!JJ**,tzz#9:25d6O6O2P

/tzz=19-6[DJJ* tzz#>?

446
djj*;TB?))!*8*>B#'	 *  9E8H8H8Qs<014WY
D$=$=YqvRXAXYZ	$$(J<YK}INS,K L11237<
 ))+,YK
|Cdef 	!!,/O  	$#K	$.  
  		" T  		 ! $   Zs   /S 2%S &S.  S>S>(T T 2T# 9T3T3SS	S+*S+.	S;:S;	TT	T T #	T0/T0c                J   ddl m} |j                  dd      }t        |      dkD  r|d   j	                         nd}|j                         }|r|dv r>| j                  sddlm}  |d |               y| j                  d	
      s |d       y| j                  d|        y)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   >   rN   rM   browser  rO   rj  rz   z!  (._.) No previous sessions yet.z/resume )r   r   r/   r0   r   r2   r$  r  r  rX  rv  )r:   r   r   r>   r   subr  s          rD   _handle_sessions_commandz)CLICommandsMixin._handle_sessions_commandM  s     	 ""4+"%e*q.eAhnnbiik c55##F":<=>?--Z-@;< 	##hse$45rF   c                	   ddl m}m} | j                  s	 |d       y| j                  sddlm}  |d |               y|j                  dd      }t        |      dkD  r|d   j                         nd}t        j                         }|j                  d	      }t        j                         j                  dd
 }	| d|	 }
|r|}nTd}| j                  r%| j                  j!                  | j"                        }|xs d}| j                  j%                  |      }| j"                  }| j&                  r&	 | j&                  j)                  | j                         	 | j                  j-                  | j"                  d       	 | j                  j/                  |
t0        j2                  j5                  dd      | j6                  | j8                  | j:                  |d|       | j                  D ]  }	 | j                  j=                  |
|j5                  dd      |j5                  d      |j5                  d      xs |j5                  d      |j5                  d      |j5                  d      |j5                  d      t?        |              	 | j                  jA                  |
|       | jC                  | j"                  |
       |
| _        || _"        d| _#        d| _$         ||
       | j&                  r|
| j&                  _        || j&                  _"        | j&                  jK                          tM        | j&                  d      r$t        | j                        | j&                  _'        tM        | j&                  d      r	 ddl(m)}  |       | j&                  _*        tM        | j&                  d       r| j&                  jW                          	 tY        | j&                  d!d      }||j[                  |
|xs dd"d#       t        | j                  D cg c]  }|j5                  d      dk(  s| c}      } |d$| d%| d&|dk7  rd'nd d(        |d)|         |d*|
        y# t*        $ r Y w xY w# t*        $ r Y w xY w# t*        $ r} |d|        Y d}~yd}~ww xY w# t*        $ r Y w xY w# t*        $ r Y w xY w# t*        $ r Y 8w xY w# t*        $ r Y w xY wc c}w )+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  rO   r   r   z%Y%m%d_%H%M%S   _branchbranchedHERMES_SESSION_SOURCEr   )max_iterationsreasoning_config_branched_from)r   sourcemodelmodel_configrS  z#  Failed to create branch session: r   rU  r   	tool_namer   
tool_callstool_call_id	reasoning)r   r   r   r  r  r  r  api_contentTrL  rM  rN  rP  rQ  FrR  u     ⑂ Branched session "z" (rW  rm   )z  Original session: z  Branch session:   ).r   r   r>  r8   r$  r  r  r/   r0   r   r   nowstrftimeuuiduuid4hexget_session_titler   get_next_title_in_lineager   r^  r~   r_  create_sessionr,   environr4   r  	max_turnsr  append_messager   r&  _transfer_session_yolosession_startra  r`  rd  r(   rL  re  rO  rM  rP  r   rf  )r:   r   r   r>  r  r>   branch_namer  timestamp_str
short_uuidnew_session_idbranch_titlecurrent_titlebaserS  r   msgrO  rs  r   ru  s                        rD   _handle_branch_commandz'CLICommandsMixin._handle_branch_commandn  s    	:((KLBb689:;""4+*-e*q.eAhnn&b lln_5ZZ\%%bq)
)?!J<8 &L !M $ 0 0 B B4?? S ,HD++EEdKL !OO ::

88--	((*E	++)zz~~&=uEjj&*nn(,(=(=&7
 #4 , 
  ,, 	C  //-0GGI.!ggk2Ecggfo"ww|4!$!8!ggk2 !<C @ 0 	&	..~|L
 	##DOO^D( " 0 ::$2DJJ!'*DJJ$JJ**,tzz#9:25d6O6O2P

/tzz=19-6[DJJ* tzz#>?

446
djj*;TB?))&*;*Ar#'	 *  D$=$=YqvRXAXYZ	'~ 6=	QB(GqJ	
 	&'8&9:;&~&678K    		(  	9!=>	(    		, ! $   Zs   5%Q, &Q< A R 2BR-R= S 2S S,1S,,	Q98Q9<	R	R		R*R%%R*-	R:9R:=	S
	S
	SS	S)(S)c                   ddl m} |j                  d      }t        |      dkD  rF|d   j	                         j                         }|dv r:d| _        d| _         |dd      rt        d	       nt        d
       t        d       y|| j                  v r| j                  | j                  |         | _        d| _         |d| j                        rt        d| d       nt        d| d       t        d| j                  dd  t        | j                        dkD  rdnd d       yt        d|        t        ddj                  | j                  j                                       yt                t        d       t        d       t        d       t                t        dddd       | j                  j                         D ]^  \  }}t        |t              r)|j!                  d      xs |j!                  dd      dd }nt#        |      dd }t        d|dd |        ` t                t        d!       t                y)"z@Handle the /personality command to set predefined personalities.r   save_config_valuer   r   >   nonedefaultneutralr   Nzagent.system_promptz,(^_^)b Personality cleared (saved to config)z((^_^) Personality cleared (session only)u7     No personality overlay — using base agent behavior.z(^_^)b Personality set to '' (saved to config)z(^_^) Personality set to '' (session only)z  "r   r   rD  z(._.) Unknown personality: z  Available: none, r   z4+--------------------------------------------------+z1|            (^o^)/ Personalities               |rO   r  <12z - (no personality overlay)descriptionsystem_prompt2   z - z  Usage: /personality <name>)r   r  r/   r0   r   r2   r  r   r)   personalities_resolve_personality_promptr6   keysitems
isinstancedictr4   str)r:   r   r  r>   personality_namer   promptpreviews           rD   _handle_personality_commandz,CLICommandsMixin._handle_personality_command  s(   )		1	%u:>$Qx~~/557#AA%'"!
$%:B?HIDEOP!T%7%77%)%E%EdFXFXYiFj%k"!
$%:D<N<NO78H7II\]^67G6HHXYZT//45s4CUCU?VY[?[eac5ddfgh34D3EFG+DIId6H6H6M6M6O,P+QRS G&'JK&'GBvcl"=>? $ 2 2 8 8 : 3ffd+$jj7_6::oWY;Z[^\^;_G!&k#2.G4*Cy123 G01GrF   c                P   ddl m} ddlm} ddlm}m}m}m}m	} |j                  d      }	t        |	      dkD  r|	d   j                         nd}
|
j                         }|
r|dk(  rB |       \  }}}|rt        d	|        y
|rt        d| d       y
t        |rd| dnd       y
|dv r |        y
|dk(  s|j                  d      rR|
t        d      d
 j                         }|st        d       y
 ||      \  }}t        |r
d	|        y
d|dd       y
|dk(  r |d       t        d       y
t        d|
 d       	 |j!                  |
      } ||
       t        d|j$                   d       y
# |j"                  |f$ r}t        d|
 d|        Y d
}~y
d
}~ww xY w)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.)rM   galleryrx  allscalezscale z7(o_o) Usage: /pet scale <factor>  (e.g. /pet scale 0.5)u   (^_^) Pet scale → gr`   offFz(o_o) Fetching 'u   ' from petdex…z(x_x) Couldn't adopt 'z': )	agent.petr  agent.pet.manifestr  hermes_cli.petsr  r  r  r  r  r/   r0   r   r2   r)   
startswithinstall_petPetStoreErrordisplay_name)r:   r   r  r  r  r  r  r  r  r>   r   lowr+   r   r:  valuer  petr   s                      rD   _handle_pet_commandz$CLICommandsMixin._handle_pet_command1  s    	$4ss		1	%"%e*q.eAhnnbiikcXo!3!5GT3sen%v%FGH  d	$z2@XY66'>S^^H5G&,,.EOP&u-JE3CF3%.O 0DE!9A-NO%<*+ %567	##C(C 	C(())JKL	 ##]3 	*3%s3%89	s   E9 9F%
F  F%c                p   ddl m} ddlm} ddlm} ddlm} |j                  d      }t        |      dkD  r|d   j                         nd}|s	 t        d	      j                         }|st        d       y
dj                  d |j                         d
d D              d
d j                         xs d}|j!                  |      xs |j!                  |      xs d}	t        d| d       	 |j#                  |d      }
|
st        d       y
dd}	 |j%                  |
d   |	|||      } ||j&                         t        d|j(                   d       y
# t        t        f$ r t                Y y
w xY w# |$ r}t        d|        Y d
}~y
d
}~ww xY w# |$ r}t        d|        Y d
}~y
d
}~ww xY w)a  Generate ("hatch") a brand-new petdex pet from a description.

        ``/hatch <description>`` runs the full pet pipeline in-process: a base
        look, then one grounded animation row per state, sliced + normalized into
        a spritesheet, then adopted as the active mascot. Progress streams inline
        (it's ~a minute of image-model calls). In the desktop app this command
        opens the richer generate overlay instead; here we run it directly.
        r   r  )orchestrate)GenerationError)r  r   r   r   z(o_o) Describe your pet: NzA(o_o) Usage: /hatch <description>  (e.g. /hatch a tiny cyber fox)rR   c              3  <   K   | ]  }|j                           y wN)
capitalize).0ws     rD   	<genexpr>z9CLICommandsMixin._handle_hatch_command.<locals>.<genexpr>  s     L1Ls   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.c                    | dk(  r%|j                  dd      d   }t        d| d       y | dk(  rt        d       y | d	k(  rt        d
       y y )Nr1  :r   r   u     ┊ drawing u   …composeu     ┊ composing spritesheet…saveu     ┊ saving…)r/   r)   )eventdetailr  s      rD   	_progressz9CLICommandsMixin._handle_hatch_command.<locals>._progress  sU    ~S!,Q/ugS12)#67&'( !rF   )
base_imageslugr  concepton_progressz(x_x) Hatch failed: r  u.    hatched and adopted — it'll pop in shortly!)r  r  r  r  r   r  )r  r  agent.pet.generater  agent.pet.generate.imagegenr  r  r  r/   r0   r   inputEOFErrorKeyboardInterruptr)   r6   slugifygenerate_base_drafts	hatch_petr  r  )r:   r   r  r  r  r  r>   r  r  r  draftsr   r  rB   s                 rD   _handle_hatch_commandz&CLICommandsMixin._handle_hatch_commandk  s    	$2?/		1	%&)%j1n%(.."" ;<BBD
 UV xxL8KLLSbQWWYb]b}}\*MemmG.DM!'*NOP	 55g5CF
 @A	)
	 **!!9)% + F 	FKK ++,,Z[\] /0   	9#?@	4  	(./	sB   E .E8 F E54E58F=FFF5F00F5c           
     @   ddl m} ddl}ddlm fd}d }d }|j                  |      }t        |      dk(  rt                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      }|j                  d      r|j                  dg       ng }	|	rt        d       t        d       |	D ]  }
|
j                  dd      }t        d|
d   dd  d!d"|
d#   d$d"|d%       |
j                  d&      r t        d'd(j                  |
d&                 t        d)|
j                  d*d+              |
j                  d,      rt        d-|
d,           t                 t                yt        d.       t                y|d   j                         } ||d/d       }|y|dk(  r| |d|d0   1      }|j                  d      r|j                  dg       ng }	|	st        d2       yt                t        d3       t        d4       |	D ]  }
t        d5|
d           t        d6|
d7           t        d8|
j                  d9d              t        d:|
d#    d;|
j                  dd       d<       t        d=|
j                  d,d>              |
j                  d&      r t        d?d(j                  |
d&                 t        d@|
j                  d*d+              |
j                  dA      r%t        dB|
dA    d;|
j                  dCd       d<       t                 y|dDv r	|dE   }|st        dF       y|d#   xs |d   }|dG   xs dHj                  |dd       } ||d&         }|s|st        dI       y |dJ||xs d|d7   |dK   |d   |xs dL      }|j                  d      ret        dM|d           t        d:|d#           |j                  d&      r t        d?d(j                  |d&                 t        d=|d,           yt        dN|j                  dO              y|dPk(  r|dE   }|st        dQ       y|d   } ||      }|st        dR|        yd} ||d&         } ||dS         }t         ||dT               }t        |j                  d&      xs% |j                  dU      sg n|j                  dU      g      }|dV   rg }n:|r|}n5|s|r1|D cg c]	  }||vs| }}|D ]  }||vs|j                  |         |dW||d#   |dG   |d7   |dK   |d   |X      }|j                  d      re|dY   }
t        dZ|
d           t        d:|
d#           |
j                  d&      r!t        d?d(j                  |
d&                 yt        d[       yt        d\|j                  dO              y|d]v r"|dE   }|st        d^| d_       y|d   }|d`v rdan|} ||||dbk(  rdcndd      }|j                  d      s!t        de| df|j                  dO              y|dbk(  rt        dg|dY   d7    d;| d<       y|dhk(  r9t        di|dY   d7    d;| d<       t        d=|dY   j                  d,              y|djk(  r$t        dk|dY   d7    d;| d<       t        dl       y|j                  dmi       }t        dn|j                  d7|       d;| d<       yt        do|        t        dp       yc c}w )qz3Handle the /cron command to manage scheduled tasks.r   )get_jobN)cronjobc                 :    t        j                   di |       S )Nr   )jsonloads)kwargscronjob_tools    rD   	_cron_apiz8CLICommandsMixin._handle_cron_command.<locals>._cron_api  s    ::l4V455rF   c                    g }| D ]8  }t        |xs d      j                         }|s#||vs(|j                  |       : |S )Nr   )r  r   r   )values
normalizedr  r   s       rD   _normalize_skillsz@CLICommandsMixin._handle_cron_command.<locals>._normalize_skills  sM    J ,5;B'--/D
2%%d+, rF   c                   d d d g g g ddd d g d}d}|t        |       k  r| |   }|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(  r-|dz   t        |       k  r	 t        | |dz            |d<   |dz  }n)|dk(  r1|dz   t        |       k  r |d   j	                  | |dz             |dz  }n|dk(  r1|dz   t        |       k  r |d   j	                  | |dz             |dz  }n|dk(  r1|dz   t        |       k  r |d   j	                  | |dz             |dz  }n|dk(  rd|d<   |dz  }nw|dk(  rd|d<   |dz  }ng|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   j	                  |       |dz  }|t        |       k  r|S # t        $ r t        d       Y y w xY w)NF)r   deliverrepeatskills
add_skillsremove_skillsclear_skillsr  r  schedulepositionalsr   z--namer   r   r   z	--deliverr  z--repeatr  z!(._.) --repeat must be an integerz--skillr  z--add-skillr  z--remove-skillr  z--clear-skillsTr  z--allr  z--promptr  z
--scheduler	  r
  )r0   rh   ri   r)   r   )tokensoptsrl   tokens       rD   _parse_flagsz;CLICommandsMixin._handle_cron_command.<locals>._parse_flags  s}    !# % !D Ac&k/q	H$QV)<#)!a%=DLFAk)a!ec&k.A&,QUmDOFAj(QUS[-@$),VAE]);X FAi'AECK,?N))&Q-8FAm+AF0C&--fQUm<FA..1q53v;3F)00A?FA..+/D(FAg%"&DKFAj(QUS[-@%+AE]DNFAl*q1us6{/B'-a!e}D$FA'..u5FAM c&k/N K9 & $AB#$s   G" "G98G9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>rM   )actionr   jobsz  Current Jobs:zA  ---------------------------------------------------------------r  r   r   job_id   r  z | r	  z<15z<8r  z      Skills: r   z      prompt_previewr   next_run_atz      Next: z3  No scheduled jobs. Use '/cron add' to create one.r   r  )r  include_disabledz(._.) No scheduled jobs.zScheduled Jobs:zP--------------------------------------------------------------------------------z  ID: z  Name: r   z	  State: r  z  Schedule: rV  r  z  Next run: zN/Az
  Skills: z
  Prompt: last_run_atz  Last run: last_status>   addr[   r
  z*(._.) Usage: /cron add <schedule> <prompt>r  rR   z3(._.) Please provide a prompt or at least one skillr[   r  )r  r	  r  r   r  r  r  z(^_^)b Created job: z(x_x) Failed to create job: r!   r   zN(._.) Usage: /cron edit <job_id> [--schedule ...] [--prompt ...] [--skill ...]z(._.) Job not found: r  r  skillr  update)r  r  r	  r  r   r  r  r  jobz(^_^)b Updated job: z  Skills: nonez(x_x) Failed to update job: >   rmrunpauser   removerF  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: rF  z(^_^)b Resumed job: r  z(^_^)b Triggered job: z)  It will run on the next scheduler tick.removed_jobz(^_^)b Removed job: z(._.) Unknown cron command: z8  Available: list, add, edit, pause, resume, run, remove)r   r  r   tools.cronjob_toolsr  r/   r0   r)   r4   r6   r2   setrM   r   )r:   r   r  r   r  r  r  r  rB   r  r  
repeat_strr  r  r
  r	  r  r  r  existingfinal_skillsreplacement_skillsr  r  existing_skillsr  r  removedr  s                               @rD   _handle_cron_commandz%CLICommandsMixin._handle_cron_command  s;   ?	6	6	p S!v;!G&'KL&'G- "#XYUVLMFG:;,--.*+-.Gf-F-3ZZ	-B6::fb)D'(o& C!$3!7JDXs!3C 8C
OC;PPST^_aSbcdwwx(tyyX/G.HIJF377+;R#@"ABCww}-S-?,@ABG G KLGAY__&
F12J'<ftE{KF-3ZZ	-B6::fb)D01G#$(O s8}o./V./	#'''3"7!89:S_$5R#8N7OqQRSWW]E%B$CDE778$JtyyX'?&@AB
377+;R#@"ABC77=)L]);(<Bsww}VY?Z>[[\]^ **}-KBCJ'9;q>H(^@sxxAB'@F&tH~6F&KL!~&\YH~~F zz)$,VH-=,>?@VJ%7$89:::h'Jtyy1A'B&CDEVM%:$;<=  4VZZ5H4IJK}-Kfg ^FvH-fX67L!24>!B*4+=>J 1$2G HIM"8<<#9#{U\H]bdldpdpqxdycz|ON#!#1}3Ba%eS`F`aa' 3EL0$++E23 j)H~&\YH~#	F zz)$Um,S]O<=S_$567778$JtyyX'?&@AB
  *+  4VZZ5H4IJKMM}-K+J<yAB ^F!+/I!IXzFfV[ael[lDWrvwF::i((vzz'7J6KLM +F5M&,A+B"VHANO  8#,VE]6-B,C2fXQOPVE]%6%6}%E$FGH  5.ve}V/D.ERxqQRAB  !**]B7,W[[-H,IF8STUV,ZL9:HIi  bs   :	^^c                "   ddl }	 |r|j                  |      dd ng }dj                  |      }	 ddlm}  ||      }| j                  |       y# t        $ r |xs dj                         dd }Y Tw xY w# t        $ r}d| }Y d}~Kd}~ww xY w)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   rR   )handle_suggestions_commandzSuggestions command failed: )r   r/   ri   r6   hermes_cli.suggestions_cmdr+  r~   _console_print)r:   r   r   r  r?   r+  outputr   s           rD   _handle_suggestions_commandz,CLICommandsMixin._handle_suggestions_command  s     		--0U[[%ab)bF xx	8M/5F 	F#  	-iR&&(,F	-  	83A37F	8s(   A A6  A32A36	B?B		Bc                   ddl 	 |rj                  |      dd ng }dj                  fd|D              }	 ddlm}  ||      }| j                  |j                         t        |d	d      }|r|| _
        yy# t        $ r |xs dj                         dd }Y ~w xY w# t        $ r}| j                  d|        Y d}~yd}~ww xY w)
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   rR   c              3  @   K   | ]  }j                  |        y wr  )quote)r  tr   s     rD   r  z=CLICommandsMixin._handle_blueprint_command.<locals>.<genexpr>  s     71A7s   )handle_blueprint_commandzCron blueprint command failed: 
agent_seed)r   r/   ri   r6   hermes_cli.blueprint_cmdr4  r~   r-  r   r   _pending_agent_seed)	r:   r   r  r?   r4  rB   r   seedr   s	           @rD   _handle_blueprint_commandz*CLICommandsMixin._handle_blueprint_command  s     		--0U[[%ab)bF xx777	I-d3F 	FKK(v|T2 (,D$   	-iR&&(,F	-  	"A! EF	s(   A; B! ; BB!	C*CCc                    ddl }|r|j                  |      dd ng }|sdg}	 ddlm}  ||       y# t        $ r Y yt
        $ r}t        d|        Y d}~y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   rv   )cli_mainz(._.) curator: )r   r/   hermes_cli.curatorr;  r   r~   r)   )r:   r   r   r  r;  r   s         rD   _handle_curator_commandz(CLICommandsMixin._handle_curator_command  si     	),S!!"%"ZF	+3V 	  	+OC5)**	+s   2 	AAAAc                2   ddl m} |j                         }|j                  d      r|j	                  d      }|j                  d      r|t        d      d j	                         }	  ||      }|rt        |       yy# t        $ r}d| }Y d}~"d}~ww xY w)u#  Handle the /kanban command — delegate to the shared kanban CLI.

        The string form passed here is the user's full ``/kanban ...``
        including the leading slash; we strip it and hand the remainder
        to ``kanban.run_slash`` which returns a single formatted string.
        r   )	run_slash/kanbanNz(._.) kanban error: )hermes_cli.kanbanr?  r   r  lstripr0   r~   r)   )r:   r   r?  r   r.  r   s         rD   _handle_kanban_commandz'CLICommandsMixin._handle_kanban_command  s     	0yy{??3;;s#D??8$H'..0D	2t_F &M   	2+C51F	2s   'A> >	BBBc                2    ddl m} |j                         j                         }t	        |      dkD  r|dd ng }|rG|d   j                         dv r2ddlm} ddlm	}  ||j                  | fd	      }|t        |       ydd
lm}  || |              y)uD   Handle /skills slash command — delegates to hermes_cli.skills_hub.r   )ChatConsoler   N>	   denyr   dropmodeapplyrejectapprover  approvalhandle_pending_subcommandwrite_approvalc                (    j                  d|       S )Nr  _save_write_approvalr+   r:   s    rD   <lambda>z9CLICommandsMixin._handle_skills_command.<locals>.<lambda>  s    D,E,EhPW,X rF   )set_mode_fn)handle_skills_slash)r   rF  r   r/   r0   r2   "hermes_cli.write_approval_commandsrO  toolsrQ  SKILLSr)   hermes_cli.skills_hubrX  )	r:   r   rF  r>   r?   rO  waoutrX  s	   `        rD   _handle_skills_commandz'CLICommandsMixin._handle_skills_command  s    # 		!!#JNuQRyDGMMO (T TT2+		4XC c
=C/rF   c                >   ddl m} |j                         j                  dd      }t	        |      dkD  r|d   j                         nd} ||      }|rt        d       nt        d       t        | d      r| j                  j                  |       yt        d	       y)
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_promptra  r   r/   r0   r)   r(   rb  put)r:   r   ra  r>   user_requestr  s         rD   _handle_learn_commandz&CLICommandsMixin._handle_learn_command  s     	: 		!!$*+.u:>uQx~~'r .EFDE4)*##C(ABrF   c                >    ddl m} ddlm} |j	                         j                         }t        |      dkD  r|dd ng }t         dd      rt         j                  dd      nd}|ddl	m
}  |       } ||j                  || fd	
      }|d}t        |       y)uG   Handle /memory slash command — pending review + approval-gate toggle.r   rN  rP  r   Nr   _memory_store)load_on_disk_storec                (    j                  d|       S )NmemoryrS  rU  s    rD   rV  z9CLICommandsMixin._handle_memory_command.<locals>.<lambda>G  s    (A(A(G(T rF   )memory_storerW  zWUnknown /memory subcommand. Use: pending, approve <id>, reject <id>, approval <on|off>.)rY  rO  rZ  rQ  r   r/   r0   r   r   tools.memory_toolri  MEMORYr)   )	r:   r   rO  r]  r>   r?   r  ri  r^  s	   `        rD   _handle_memory_commandz'CLICommandsMixin._handle_memory_command2  s    P.		!!#JNuQRy>EdGUY>Z

OT:`d= =&(E'IItT

 ;QCc
rF   c                :    ddl m}  || dt        |             y)zLPersist <subsystem>.write_approval to config (for /memory|/skills approval).r   r  z.write_approvalN)r   r  r   )r:   	subsystemr+   r  s       rD   rT  z%CLICommandsMixin._save_write_approvalN  s    )YK7gGrF   c                R   	
 ddl mmmmm	m
mmm	 |j                         j                  d      }t        |      dk  s|d   j                         s d        d        d       y	|d   j                          xj                  dz  c_         j                  d
t        j                         j!                  d       dt#        j$                         j&                  d	d   j)                         s	 d       y	 d dd	d  t              dkD  rdnd d        d         d        j+                        	
 fd}t-        j.                  |dd       }| j0                  <   |j3                          y	)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   )	AIAgentrF  _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   rD  z  Task ID: u?     You can continue chatting — results will appear when done.
c                 p
    j                           j                         	  j                         	  dGi dd   dd   j	                  d      dd   j	                  d      dd   j	                  d      dd   j	                  d      dd   j	                  d      d	d   j	                  d
      dd   j	                  d      dj
                  dj                  ddddddddj                  dj                  dj                  dj	                  d      dj                  dj                  dj                  dj                  dj                  dj                  dj                   d j"                  } d! | _        dHfd"}|| _        | j)                  #      }|r|j	                  d$d%      nd%}|s|r|j	                  d&      rd'|d&    }j*                  r/j*                  j-                          t/        j0                  d(       t3                        j3                  d)         d*d+ d,        d- d.        d/d d0  t5              d0kD  rd1nd% d2               j3                  d)         d*d+ d,       |r	 d3d4lm}  |       }|j;                  d5d6      } |j=                  d7d8            } |j=                  d9d:            }        }	|	j3                  t?         |j@                  ;      d)| d<| d= d>d?||tB        jD                  d@jG                         A             n dB       jH                  r=tJ        jL                  jO                  dC       tJ        jL                  jQ                          	  d         d         d        jR                  jU                  d        jV                  sd%_,        j*                  rj[                  d3F       y y # t        $ r Y w xY w# t        $ r
 d6}d8}d:}Y =w xY w# t        $ r]}
j*                  r/j*                  j-                          t/        j0                  d(       t3                 dD dE|
        Y d }
~
d }
~
ww xY w# t        $ r Y w xY w# 	  d         d         d        n# t        $ r Y nw xY wjR                  jU                  d        jV                  sd%_,        j*                  rj[                  d3F       w w xY w)INr  api_keyruntimebase_urlproviderapi_modeacp_commandr;   acp_argsr?   
max_tokensr  r  
quiet_modeTverbose_loggingFr   r   r   
session_dbr  service_tierrequest_overridesproviders_allowedproviders_ignoredproviders_orderprovider_sortprovider_require_parametersprovider_data_collectionopenrouter_min_coding_scorefallback_modelc                      y r  r   )_a_kws     rD   rV  zUCLICommandsMixin._handle_background_command.<locals>.run_background.<locals>.<lambda>  s    rF   c                |    j                   s/| _        j                  rj                  j                          y y y r  )r   _spinner_textr   
invalidate)r   r:   s    rD   _bg_thinkingzYCLICommandsMixin._handle_background_command.<locals>.run_background.<locals>._bg_thinking  s5    ..-1*99 II002 % /rF   )user_messagetask_idfinal_responser   r!   zError: g?rB  rC  ux   ────────────────────────────────────────[/]u     ✅ Background task #z	 completez  Prompt: "r   r   rD  r   )get_active_skinresponse_labelu
   ⚕ Hermesresponse_borderz#CD7F32banner_textz#FFF8DC)rI  z bold]z (background #z)[/]left)r      )r  title_alignborder_stylestyler   paddingwidthz  (No response generated)u     ❌ Background task #z	 failed: )min_intervalr   )r   r  r   r  )._sudo_password_callback_approval_callback_secret_capture_callbackr~   r4   r  r  r$  r  r  _providers_only_providers_ignore_providers_order_provider_sort_provider_require_params_provider_data_collection_openrouter_min_coding_score_fallback_model	_print_fnthinking_callbackrun_conversationr   r  r(  r+  r)   r0   hermes_cli.skin_enginer  get_branding	get_colorr   final_response_markdownrich_boxHORIZONTALS_scrollback_box_widthbell_on_completesysstdoutwriteflush_background_taskspopr   r  _invalidate)bg_agentr  rB   responser  _skinrW   _resp_color
_resp_text_chat_consoler   rs  rF  rt  r   ru  rv  r  r:   rw  rx  ry  r  task_num
turn_routes              rD   run_backgroundzCCLICommandsMixin._handle_background_command.<locals>.run_backgroundr  s   &t'C'CD!$"9"9:+D,I,IJo5" $W-&y155i@ (	266zB (	266zB	
 (	266zB !+9 5 9 9) D (	266v>  *)488F $(>> &*%:%:  $ %*  ' #  $//  &*%:%:!" "&!2!2#$ '1nn5H&I%& '+&:&:'( '+&<&<)* %)$9$9+, #'"5"5-. 150M0M/0 .2-K-K12 150Q0Q34 $(#7#75: &="3 .:*!22!'# 3 
 @F6::&6;2Fvzz'/B!((9:H
 99II((*JJt$##aa
|3$GH1(9EF,vcr{mS[2=MESU3VVXYZ##aa
|3$GH	/J / 1 % 2 23C\ R&A%//RcenBo&p%@Q^`iAj%k
 %0MM!''7tGcGcd !+fUG>(SWX$*%0($00 &"88:	) 	 78 ((JJ$$T*JJ$$&.t4)$//5 &&**7D9**)+D&99$$!$4 a  L % / ,&/%.
/0  J99II((*JJt$1(9QCHIIJ ! 	.t4)$//5  &&**7D9**)+D&99$$!$4 s   P I9Q 4AP. B3Q 7R- 	P+*P+.Q=Q  QQ 	R*AR% R< %R**R< -	R98R9<T5>ST5	S# T5"S##AT5Tzbg-task-)ri  daemonr   )r   rs  rF  rt  r   ru  rv  rw  rx  ry  r   r/   r0   _background_task_counterr   r  r  r  r  r  _ensure_runtime_credentials_resolve_turn_agent_config	threadingThreadr  start)r:   r   r>   r  threadrs  rF  rt  r   ru  rv  r  rw  rx  ry  r  r  r  s   `    @@@@@@@@@@@@@rD   _handle_background_commandz+CLICommandsMixin._handle_background_commandS  s    	Q  	Q  	Q		!!1!-u:>q!134OP_`q!%%*%00//9:!DJJL<L<LRa<P;QR //1QR*8*LWZ[aWbegWgemoMpprst+gY'(RS44V<
v	5 v	5 v	5p !!XV]U^K_`*0w'rF   c                   ddl m}m}m}m}m}m} 	 ddlm}m	}	  |       }|s, |d        |d| d|         |d| d	 |	        |        y |d
| d| dt        |       d       |D ]  }t        |j                  dg             }|j                  d      xs d| d} |       j                  d |        d|d   ddt        |       d| d	       |j                  dg       D ]%  } |       j                  dt        |       d       '   |d| d|        y# t        $ r}
 |d|
 |        Y d}
~
yd}
~
ww xY w)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   )rF  _BOLDr   r   rt  r   )list_bundles_bundles_dirz%[1;31mBundle subsystem unavailable: Nz  No skill bundles installed.rO   zGCreate one with: hermes bundles create <name> --skill <s1> --skill <s2>zDirectory: u   
  ▣ zSkill BundlesrV  z installed):r  r  zLoad z skillsz
    [bold z]/r  z<20z[/] [dim]-[/] z [dim](z skills)[/]u           [dim]· r  z
  z;Invoke a bundle with /<slug>. Manage with `hermes bundles`.)r   rF  r  r   r   rt  r   agent.skill_bundlesr  r  r~   r0   r4   r)   _escape)r:   r   rF  r  r   r   rt  r   r  r  r   bundlesinfoskill_countdescrm   s                   rD   _handle_bundles_commandz(CLICommandsMixin._handle_bundles_command  s    	ML	F
 .34TF 337&: bk,.)9$@A(5'tfBs7|nLQR 	HDdhhx45K88M*Jk]'.JDM[]O2d6l3-? @$T]O7;-{L XXh+ H##&6wqzl#$FGH	H 	4& ,,063	
1  	>seD6JK	s   D# #	E,D>>Ec                   ddl }|j                         j                  dd      }t        |      dkD  r!|d   j	                         j                         nd}t
        }t        j                  j                  dd      j                         }|j                  d      r}|j                         j                  dd      }t        |      dkD  r|d   j                         n|}t        d	|v r|nd
|       }	|	j                  dvr2t                t        d|	j                  xs d d       t                y	 |	j                  xs |	j                  dv rdnd}
|	j                  s#t                t        d|        t                y|	j                  }|	j                   j                  d      r|	j#                         }n#|	j%                  dddd      j#                         }	 ddlm}  |        t                ||k(  }|rt-        |
d      }|du}|r|}nt/        |d      }|rt        d|        nM|r9|
}t1        |
      r*t3        |
      }t        d|
 d       t        d| d       nt        d       t5        ||j7                               }|j8                  rft;        d      D ],  }t-        |d      }|r|}d } nt=        j>                  d!       . |rt        d"|        nt        d#| d$       t        d%       n|t        d&       |j@                  }|rt        d'|        |j7                         }tC        ||      }|rt        d(       t        d'|        nt        d)       nt        d|
 d*|        |s t                t        d+       t                y|t        j                  d<   	 dd,lm"}  |d-       t                t        d.       t        d/|        t                tG        | d0      r| jH                  jK                  d1       yy|d2k(  r|rt        j                  jM                  dd       	 dd3lm}m'}  |d-        |        t                t        d4       t        d5       t                tG        | d0      r<| jH                  jK                  d6       yt                t        d7       t                yy|dk(  rmt                |rt        d8       t        d/|        d9}
	 tQ        |jS                  d:d      d;   j                  d<      d         }
	 ddl+}|jW                  |jX                  |jZ                        }|j]                  d       |j_                  d=|
f       |ja                          t        d>       n	 dd@lm2}  |       }|t        dA|jg                          dB       nQ	 ddClm4}  |       }|dEk(  r"t        dF       t        dG       t        dH       n|dIk(  rt        dJ       nt        dK       t                t        dL       t        dM       t                yt                t        dN       t                t        dO       t        dP       t        dQ       t                y# t        $ r% t                t        d|        t                Y yw xY w# t*        $ r Y w xY w# t*        $ r Y w xY w# t*        $ r Y w xY w# t        tT        f$ r Y w xY w# tb        t*        f$ r t        d?       Y 
w xY w# t*        $ r d}Y w xY w# t*        $ r dD}Y qw xY w)RuY   Handle /browser connect|disconnect|status — manage live Chromium-family CDP connection.r   Nr   rv   BROWSER_CDP_URLr   connectr   z://zhttp://>   wswsshttphttpsu'      ⚠ Unsupported browser url scheme: z	(missing)z( (expected one of: http, https, ws, wss)>   r  r  i  r    u$      ⚠ Invalid port in browser url: u$      ⚠ Missing host in browser url: z/devtools/browser/)pathparamsqueryfragment)cleanup_all_browsersg      ?)timeoutu7      ✓ Chromium-family browser is already listening at u      ⚠ Port z< is occupied by another application that isn't a CDP browseruK        (an IDE debugger or dev server may be using it) — launching on port z instead...uZ      Chromium-family browser isn't running with remote debugging — attempting to launch...rG  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: rb  a  [System note: The user invoked /browser connect and connected your browser tools to a Chromium-family dev/debug browser via Chrome DevTools Protocol. Your browser_navigate, browser_snapshot, browser_click, and other browser tools now control that CDP browser. The command itself is a signal that using browser tools for their current browser-related request is expected; do not wait for separate permission just because CDP is connected. This is typically a Hermes-managed isolated debug profile, not the user's main everyday browser. It is still user-visible and may contain pages, logged-in sessions, or cookies in that debug profile, so avoid destructive actions, closing tabs, or navigating away unless the user's task calls for it.]
disconnect)r  _stop_cdp_supervisoru;   🌐 Browser disconnected from live Chromium-family browserzL   Browser tools reverted to default mode (local headless or cloud provider)z[System note: The user has disconnected the browser tools from their live Chromium-family browser. Browser tools are back to default mode (headless local browser or cloud provider).]zWBrowser is not connected to a live Chromium-family browser (already using default mode)u?   🌐 Browser: connected to live Chromium-family browser via CDPi$  r  r@  r@  z	127.0.0.1u      Status: ✓ reachableu9      Status: ⚠ not reachable (browser may not be running))_get_cloud_provideru   🌐 Browser: z (cloud))_get_browser_engineauto
lightpandauB   🌐 Browser: local Lightpanda (agent-browser --engine lightpanda)u;      ⚡ Lightpanda: faster navigation, no screenshot supportzB   Automatic Chromium fallback for screenshots and failed commandschromeuE   🌐 Browser: local headless Chromium (agent-browser --engine chrome)u5   🌐 Browser: local headless Chromium (agent-browser)uI      /browser connect      — connect to your live Chromium-family browseru.      /browser disconnect   — revert to defaultz)Usage: /browser connect|disconnect|statuszR   connect      Connect browser tools to your live Chromium-family browser sessionz1   disconnect   Revert to default browser backendz)   status       Show current browser mode)5r   r   r/   r0   r2   r   r,   r  r4   r  r   schemer)   portri   hostnamer  geturl_replacetools.browser_toolr  r~   r   r   r   r   r   systemlaunchedranger(  r+  r   r   r  r(   rb  rd  r  r  rh   rsplit
IndexErrorsocketAF_INETSOCK_STREAM
settimeoutr  closeOSErrorr  provider_namer  )r:   r   _platr>   ry  _DEFAULT_CDPr9  connect_partscdp_url
parsed_cdp_port_hostr  _is_default_found_already_open_launch_port_launch_wait_hintsys_name
chrome_cmdr  r  r  rm   r  r  r  engines                                 rD   _handle_browser_commandz(CLICommandsMixin._handle_browser_command  s    		!!$**-e*q.eAhnn$$&h.**..!2B7==?>>)$IIK--dA6M25m2Dq2HmA&,,.lG!Ug-='WWICVWJ  (FF=j>O>O>^S^=_ `> > "a:3D3DHX3XC^` &&<WIFG''E))*>?$++-$--	 . 
 &( C$& G "\1K/sC &d 2$G 6w LOPWyYZ$$U+#7#>L&ug-ij efress~
 vw-lELLNK##!&r (!7c!R!&,G,0M!

3( % ^_k^lmn A,OdeflmRS#LLEeWo.$||~H!<\8!TJ!OPj\23noUG+@	JK   C  D,3BJJ()E&y1 GRSM'+,G t-.##'']
 / L 

0$7](3(* STde4!12''++n
 op 3 H_GWXgY/0sA 6r : @ @ Ea HIEW!fnnf6H6HIALLOII{E23GGI45$F24H 'N8+A+A+C*DHMN(J!4!6 -bc[\bc8+efUVG]^BCG G=>GfgEF=>GU  <WIFG	2  V  : ! 4 #J/   + WUVW ! $#H$ % (!'(s   4 Z	 Z: 5[
 [ 90[* *A)\  \! \3 	+Z76Z7:	[[
	[[	['&['*[=<[= \\!\0/\03]]c                h   ddl m}m}m} |xs dj	                         j                  dd      }t        |      dkD  r|d   j	                         nd}| j                         }| |d| d|        y|j                         }|r|dk(  r |d|j                                 y|d	k(  r3 |d|j                                  |d|j                                 y|j                  d
      r9|t        d
      d j	                         }	|	s	 |d       y| j                  |	       y|dk(  r9|j                  d      }
|
 |d| d|        y |d|
j                          y|dk(  rE|j                         }
|
 |d| d|        y |d|
j                           |d| d|        y|dv r:|j!                         }|j#                          |r	 |d       y |d| d|        y|dk(  s|j                  d      r|t        d      d j	                         }|s	 |d       y|j                  dd      }	 t%        |d         }t        |      dkD  r|d   j	                         nd}	 |j)                  ||       |rd| dnd} |d| | d        y|d!k(  r(|j-                         r	 |d"       y |d| d#|        ydd$lm}  ||      \  }}|xs |}	 |j3                  ||j5                         s|nd%      }
 |d'|
j6                   d(|
j                          |
j9                         rF |d| d)|        |
j:                  j=                         j?                         D ]  } |d*|          |d| d+|
j9                         rd,nd d-|        	 | j@                  jC                  |
j                         y# t&        $ r  |d       Y yw xY w# t*        t&        f$ r} |d|        Y d}~yd}~ww xY w# t&        $ r} |d&|        Y d}~yd}~ww xY w# tD        $ r Y yw xY w).zQDispatch /goal subcommands: set / draft / show / status / pause / resume / clear.r   r   r   r   r   Nr   rO   &Goals unavailable (no active session).rv   showdraftz2  Usage: /goal draft <objective in plain language>r  zuser-pausedrz   zNo goal set.u     ⏸ Goal paused: rF  zNo goal to resume.u     ▶ Goal resumed: z`Send any message (or press Enter on an empty prompt is a no-op; type 'continue' to kick it off).>   donestopclearu     ✓ Goal cleared.zNo active goal.waitzwait z"  Usage: /goal wait <pid> [reason]z2  /goal wait: <pid> must be an integer process id.z  /goal wait: rV  r  u     ⏳ Goal parked on pid z. Loop pauses until it exits.unwaitu1     ▶ Wait barrier cleared — goal loop resumes.zNo wait barrier set.)parse_contractcontract  Invalid goal:      ⊙ Goal set (-turn budget): zCompletion contract:r   z9After each turn, a judge model checks if the goal is donez against the contract abovez. Hermes keeps working until it is, you pause/clear it, or the budget is exhausted. Use /goal status, /goal show, /goal pause, /goal resume, /goal clear.)#r   r   r   r   r   r/   r0   _get_goal_managerr2   status_linerender_contractr  _handle_goal_draftr  r   rF  has_goalr#  rh   ri   wait_onRuntimeErrorstop_waitinghermes_cli.goalsr&  r"  is_emptyr  has_contractr(  render_blockr5   rb  rd  r~   )r:   r   r   r   r   r>   r   r<   r2   	objectiver  hadwait_argwtokenspidr%   r   rtxtr&  headliner(  	goal_textr   s                          rD   _handle_goal_commandz%CLICommandsMixin._handle_goal_command  s   ++!!#))$2"%e*q.eAhnnb$$&;bDTFKL		 ex'b*+,- F?b*+,-b,,./01 G$CLM*002ILM##I.GII]I3E}"TF,tf56  -ejj\:;HJJLE}"TF"4TF;<  .uzzl;< CCG&J --,,.CIIK-.  "TF/$89
 F?e..w73v;<(..0H<=nnT1-G'!*o ,/w<!+;WQZ%%'FC/ &,Rxq>D/uTF:WXY H!KL  "TF"6tf=> 	4+C0(O		GGI@Q@Q@SY]G^E
 	"5??"3?5::,OPb24&9:335@@B '$tf&'O050B0B0D,"M N__c^df	
	##EJJ/c  LM !*- ../2  	&se,-	&  		sT   <O .O %P  %P% OOP,O<<P	P"PP"%	P10P1c                   ddl m}m}m} ddlm} | j                         }| |d| d|        y |d| d|        	  ||      }	 |j                  ||	      }
 |d|
j                   d|
j                          |
j!                         rU |d| d|        |
j"                  j%                         j'                         D ]  } |d|          |d| d|        n |d| d|        	 | j(                  j+                  |
j                         y# t        $ r6}ddl}	|	j                  t              j                  d|       d}Y d}~
d}~ww xY w# t        $ r} |d
|        Y d}~yd}~ww xY w# t        $ r Y y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_contractNrO   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   r4  rB  r,  r~   logging	getLoggerr   debugr"  ri   r  r   r6  r(  r7  r5   rb  rd  )r:   r8  r   r   r   rB  r<   r(  r   _loggingr  r   s               rD   r/  z#CLICommandsMixin._handle_goal_draft|  s    	,+3$$&;bDTFKL"TF9$@A	%i0H	GGIG9E
 	"5??"3?5::,OPb:4&AB335@@B '$tf&'TF ,,063 TF QQUPVX	##EJJ/7  	&x(../FLH	  	&se,-	*  		sB   D 
E 3%E< 	E"+EE	E9$E44E9<	FFc                   ddl m}m}m} |xs dj	                         j                  dd      }t        |      dkD  r"dj                  |dd       j	                         nd}| j                         }| |d| d	|        y|j                         s |d| d
|        y|s3 |d|j                                  |d|j                                 y|j                  dd      }|d   j                         }	t        |      dkD  r|d   j	                         nd}
|	dk(  rI|
s	 |d       y	 t        |
j                         d         }	 |j                  |      } |d| d|        y|	dk(  r9	 |j%                         }|r |d| d|dk7  rdnd d       y |d| d|        y	 |j'                  |      }|j(                  rt        |j(                  j*                        nd} |d| d|        y# t        $ r  |d       Y yw xY w# t         t"        f$ r} |d|        Y d}~yd}~ww xY w# t"        $ r} |d|        Y d}~yd}~ww xY w# t        t"        f$ r} |d|        Y d}~yd}~ww xY w)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   rR   rO   r  z*No active goal. Set one with /goal <text>.r  z  Usage: /subgoal remove <n>z:  /subgoal remove: <n> must be an integer (1-based index).z  /subgoal remove: u     ✓ Removed subgoal r$   r#  z  /subgoal clear: u     ✓ Cleared z subgoalrm   r`   zNo subgoals to clear.z  /subgoal: u     ✓ Added subgoal )r   r   r   r   r   r/   r0   r6   r,  r0  r-  render_subgoalsr2   rh   ri   remove_subgoalr  r2  clear_subgoalsadd_subgoalr  subgoals)r:   r   r   r   r   r>   r   r<   r  r	  r   rq   r(  r   prevr   s                   rD   _handle_subgoal_commandz(CLICommandsMixin._handle_subgoal_command  s    	,+!!#))$2-0Z!^chhuQRy!'')$$&;bDTFKL||~bHOP b*+,-b,,./014#ay $'K!Ovay 867$**,q/*,,S1 ,SEG9=>7?))+ .hdaisR6PPQRS  "TF"7v>?	??3'D *-c#))$$%&se2dV45=  TU
 - -cU34   ,SE23 L) 	l3%()	sZ   /G8 H 2H6 +I 8HHH3H..H36	I?III;&I66I;c                   ddl m}m} 	 ddlm}m}m} |j                         j                  d      }t        |      dk  s|d   j                         s |       } |       }	t        d	|        t        d
       |	D ]=  }
|
d   |k(  rdnd}|
d   dk(  r	d|
d    dnd}t        d| d|
d    | d|
d           ? t        d       t        dt                d       y|d   j                         j                         } |       D 
ch c]  }
|
d   	 }}
||vr5t        d|        t        ddj                  t        |                    y ||       |j!                           |d|      rt        d| d       nt        d|        t        d        | j#                         rt        d!       yy# t        $ r t        d       Y yw xY wc c}
w )"u8   Handle /skin [name] — show or change the display skin.r   )r   r  )
list_skinsset_active_skinget_active_skin_namezSkin engine not available.Nr   r   r   z
  Current skin: z  Available skins:r   u    ●rO   r  rU  rV  r  r   z   rR   u    — r  z
  Usage: /skin <name>z$  Custom skins: drop a YAML file in z/skins/
z  Unknown skin: z  Available: r   zdisplay.skinz  Skin set to: z (saved)z8  Note: banner colors will update on next session start.z  Prompt + TUI colors updated.)r   r   r  r  rP  rQ  rR  ImportErrorr)   r   r/   r0   r	   r2   r6   sortedrT  _apply_tui_skin_style)r:   r   r   r  rP  rQ  rR  r>   r9  skinsrm   markerr  new_skin	availables                  rD   _handle_skin_commandz%CLICommandsMixin._handle_skin_command  s   2	``
 		!!1!-u:>q!1*,GLE&wi01&' Q#$V9#7T01(v0E2ak]!,2F81QvYKxuQ}=M<NOPQ +,89L9N8OyYZ8>>#))+(251QvY5	59$$XJ/0M$))F9,=">!?@A! ^X6OH:X67OH:./HI%%'23 (G  	./	( 6s   
F9 G9GGc                   ddl }ddl}ddl}ddl}|j                  j                  d      xs |j                  j                  d      }|s|j                  dk(  rdnd}d}|j                  d	d
      \  }}		  |j                  |dd      5 }
|
j                  |       |r|
j                  |       ddd       	 |j                  g |j                  |      |	       t        |	dd      5 }
|
j                         }ddd       	  |j                   |	       j%                         D cg c]  }|j'                  d      r| }}dj)                  |      j+                         S # 1 sw Y   xY w# t        $ r* |j                  | d|j                  |	       d       Y w xY w# 1 sw Y   xY w# t"        $ r Y w xY w# 	  |j                   |	       w # t"        $ r Y w w xY wxY wc c}w )aw  Open ``$VISUAL``/``$EDITOR`` on a temp markdown file and return the
        saved buffer (comment lines starting with ``#!`` stripped).

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

z.mdhermes_prompt_)r   prefixr  zutf-8)encodingrR   T)shellrz#!r   )r,   r   
subprocesstempfiler  r4   r   mkstempfdopenr  callr/   r~   r2  openreadunlinkr  r5   r  r6   r   )r:   initial_textr,   r   rf  rg  editorheaderfdr  fhrawlnliness                 rD   _compose_in_editorz#CLICommandsMixin._compose_in_editor!	  s    	)ERZZ^^H-E"$''T/YvFC 	 ##59I#JD	2sW5 + HH\*+M <%++f"5 <t <=
 dC'2  bggi 		$ "nn.JbmmD6IJJyy%%'''+ +  M 6(!EKK,=+> ?tLM   
  		$  Ks   7G %E&1G :$E2 G ,F(=G F4 *G*G*&E/+G 20F%"G $F%%G (F1-G 4	G ?G G'GG'	G$!G'#G$$G'c                *   ddl m}m}m} d}|xs dj	                         j                  dd      }t        |      dkD  r|d   }	 | j                  |      }|s |d| d|        y|| _	        y# t        $ r} |d| d| |        Y d}~yd}~ww xY w)	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   rO   z(>_<) Could not open editor: u$   (._.) Empty prompt — nothing sent.)
r   r   r   r   r   r/   r0   rv  r~   r7  )	r:   r   r   r   r   initialr>   composedr   s	            rD   _handle_prompt_compose_commandz/CLICommandsMixin._handle_prompt_compose_commandM	  s     	,+#**,224;u:>AhG	..w7H
 bB4&IJ $,   	b;C5GH	s   A/ /	B8BBc                4   ddl m}m} ddlm} ddlm} d}	 |xs dj                         j                  dd      }t        |      dkD  r!|d   j                         j                         } |       xs i }|j                  d      xs i j                  d	      xs i }	t        |	j                  d
d            }
|	j                  d      xs g d}|dv r>|
rdnd} |d|j                   d|j                   d| ddj!                  |              y|dv rd}n|dv rd}n|dk(  r|
 }n	 |d       y |d|      rD|r|j"                   d|j                   n|j$                   d|j                   } |d|        y |d       y# t        $ r d}Y +w xY w)u   Toggle or inspect ``display.runtime_footer.enabled`` from the CLI.

        Usage:
            /footer           → toggle
            /footer on|off    → explicit
            /footer status    → show current state
        r   r   r  r   Colorsr   Nr   r  runtime_footerr+   Ffields)r  context_pctr=   >   rv   r   ONOFFrO   zRuntime footer:rR   z
  Fields: r   >   1ontruer   T>   0r  falser   z   Usage: /footer [on|off|status]zdisplay.runtime_footer.enabledz  Runtime footer: z6  Failed to save runtime_footer setting to config.yaml)r   r   r  r  r  hermes_cli.colorsr~  r   r/   r0   r2   r~   r4   r   BOLDRESETr6   GREENDIM)r:   r   r   r  r  _Colorsr   r>   cfg
footer_cfgr9  r  r  	new_states                 rD   _handle_footer_commandz'CLICommandsMixin._handle_footer_commandj	  s    	317 	!'R..066tQ?E5zA~Ahnn&,,. m!rwwy)/R445EFL"
z~~i78)L-L/!#DEW\\N/'--% I!YYv./1 //I44IBY#I67=yI7@7==/GMM?3}C7  (01LMC  	C	s   AF FFc                r   ddl m}m} ddlm} d}	 |xs dj                         j                  dd      }t        |      dkD  r!|d   j                         j                         }t        t        | dd            }|d	v r,|rd
nd} |d|j                   d|j                   d|        y|dv rd}	n|dv rd}	n|dk(  r| }	n	 |d       y|	| _         |d|	      rD|	r|j                   d
|j                   n|j                    d|j                   } |d|        y |d       y# t        $ r d}Y w xY w)u  Toggle or inspect ``display.timestamps`` from the CLI.

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

        Usage:
            /timestamps           → toggle
            /timestamps on|off    → explicit
            /timestamps status    → show current state
        r   r|  r}  r   Nr   show_timestampsF>   rv   r   r  r  rO   zMessage timestamps:rR   >   r  r  r  r   T>   r  r  r  r   z$  Usage: /timestamps [on|off|status]zdisplay.timestampsz  Message timestamps: z2  Failed to save timestamps setting to config.yaml)r   r   r  r  r~  r   r/   r0   r2   r~   r   r   r  r  r  r  r  )
r:   r   r   r  r  r   r>   r9  r  r  s
             rD   _handle_timestamps_commandz+CLICommandsMixin._handle_timestamps_command	  sS    	37	!'R..066tQ?E5zA~Ahnn&,,. wt%6>?/!#DEb&9'--%QR//I44IBY#I:;(19=7@7==/GMM?3}C7  ,UG45HI9  	C	s   AD( (D65D6c           
        ddl m}m}m}m}m}m}m} |j                         j                  d      }	t        |	      dk  r| j                  }
|
d}n(|
j                  d      d	u rd
}n|
j                  dd      }| j                  rdnd}t        | dd	      rdnd} |d| d| |         |d| d| d| d|         |d| d|        y|	d   j                         j                         }|j                         }d|v }|sd|v rdj!                  d |D              }|dv rXd| _        | j"                  r| j%                         | j"                  _         |dd        |d| d|         |d| d |        y|d!v rJd	| _        | j"                  r| j%                         | j"                  _         |dd	        |d| d"|        y|d#v rGd| _         |d$d        |d| d%|         |d| d&|        | j                  s |d| d'|        y|d(v rd	| _         |d$d	        |d| d)|        y ||      }|; |d| d*| |         |d| d+|         |d| d,|         |d| d-|        y|| _        d| _        |rH |d.|      r?|j                  d/      }t+        |t,              si }||d/<   ||d0<    |d| d1| d2|        y|r |d| d1| d3|        y |d| d1| d4|        y)5u  Handle /reasoning — manage effort level and display toggle.

        Usage:
            /reasoning              Show current effort level and display state
            /reasoning <level>      Set effort for this session only (none, minimal, low, medium, high, xhigh, max, ultra)
            /reasoning <level> --global  Persist reasoning effort to config.yaml
            /reasoning show|on      Show model thinking/reasoning in output
            /reasoning hide|off     Hide model thinking/reasoning from output
            /reasoning full         Show complete thinking (no 10-line clamp)
            /reasoning clamp        Collapse long thinking to the first 10 lines
        r   )
CLI_CONFIGr   r   r   r   _parse_reasoning_configr  r   r   r   Nzmedium (default)r+   Fznone (disabled)effortmediumu   on ✓r  reasoning_fullfullzclamped to 10 linesrO   zReasoning effort:  zReasoning display: rV  r  z`Usage: /reasoning <none|minimal|low|medium|high|xhigh|max|ultra|show|hide|full|clamp> [--global]--global	--sessionrR   c              3  (   K   | ]
  }|d vr|  yw)r  r  Nr   r  r  s     rD   r  z=CLICommandsMixin._handle_reasoning_command.<locals>.<genexpr>	  s!       99    >   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 'r  z$' (session only; config save failed)u,   ' (this session — use --global to persist))r   r  r   r   r   r   r  r  r   r/   r0   r  r4   show_reasoningr   r2   r6   r   _current_reasoning_callbackreasoning_callbackr  r  r  )r:   r   r  r   r   r   r   r  r  r>   rcleveldisplay_state
full_stater   
arg_tokensexplicit_globalparsed	agent_cfgs                      rD   _handle_reasoning_commandz*CLICommandsMixin._handle_reasoning_command	  s    	mll		!!1!-u:>&&Bz*	"e+)x2(,(;(;HM#*41A5#IOdJb	!4UGD6BCb	!4]O2j\QRSWRXYZb~  @D  E  F  GAhnn$$&YY[
 %
2kZ7(( #- C . "&Dzz040P0P0R

-6=b	!B4&IJb\]a\bcd/!"'Dzz040P0P0R

-6>b	!CD6JK /!"&D6=b	!DTFKLbYZ^Y_`a&&"TF"efjeklm00"'D6>b	!STXSYZ[ )->b6seD6BCb_`d_efgb6tf=>bZ[_Z`ab &
01I3O"w/Ii.	&/
7#,/I()b	!>seCVW[V\]^b	!>seCghlgmnob	!>seCoptouvwrF   c                   ddl m}m}m}m}m} |j                         j                  d      }t        |      dk  s$|d   j                         j                         dk(  r_ |d| d| j                   |        | j                  d	k(  rd
}n| j                  dk(  rd}nd} |d| d| |         |d| d|        y|d   j                         j                         }	|	dvr |d| d|	 |         |d| d|        y|	| _
         |d|	      r3|	d	k(  rd}
n
|	dk(  rd}
nd}
 |d| d|	 d|         |d| |
 |        y |d| d|	 d|        y)u  Handle /busy — control what Enter does while Hermes is working.

        Usage:
            /busy               Show current busy input mode
            /busy status        Show current busy input mode
            /busy queue         Queue input for the next turn instead of interrupting
            /busy steer         Inject Enter mid-run via /steer (after next tool call)
            /busy interrupt     Interrupt the current run on Enter (default)
        r   r   r   r   r   r  r   r   r   rv   rO   zBusy input mode: queuezqueues for next turnsteerz.steers into current run (after next tool call)zinterrupts current runzEnter while busy: z+Usage: /busy [queue|steer|interrupt|status]N>   r  r  	interruptr  zdisplay.busy_input_modez6Enter will queue follow-up input while Hermes is busy.zNEnter will steer your message into the current run (after the next tool call).z:Enter will interrupt the current run while Hermes is busy.u   ✓ Busy input mode set to 'r  r  )r   r   r   r   r   r  r   r/   r0   r2   busy_input_mode)r:   r   r   r   r   r   r  r>   	_behaviorr   behaviors              rD   _handle_busy_commandz%CLICommandsMixin._handle_busy_command4
  s    	HG		!!1!-u:>U1X^^-335Ab	!243G3G2HOP##w.2	%%0L	4	b0D6BCbI$PQAhnn$$&55b6seD6BCbI$PQ"6<g~SkWb	!=cUBUVZU[\]bxj/0b	!=cUBRSWRXYZrF   c           
        ddl m}m}m}m}m} | j                         s	 |d       y	 ddlm} t        | dd      }t        |dd      xs t        | dd      }	 ||	      rdnd	}
|j                         j                  d      }t        |      dk  s$|d   j                         j                         dk(  r4| j                  dk(  rdnd} |d| |
 d| |         |d| d|        y|d   j                         j                         j                         }d|v }dj!                  d |D              }|dv rd| _        d}d}n/|dv rd| _        d}d}n |d| d| |         |d| d|        yd| _        |r |d|      r |d| d|
 d| d |        y|r |d| d|
 d| d!|        y |d| d|
 d| d"|        y# t        $ r d
}
Y qw xY w)#u   Handle /fast — toggle fast mode (OpenAI Priority Processing / Anthropic Fast Mode).

        Session-scoped by default; ``--global`` persists agent.service_tier
        to config.yaml (parity with /model and /reasoning).
        r   r  zv  (._.) /fast is only available for models that support fast mode (OpenAI Priority Processing or Anthropic Fast Mode).N)_is_anthropic_fast_modelr   r  zAnthropic Fast ModezPriority Processingz	Fast moder   r   r   rv   priorityfastnormalrO   r$   z,Usage: /fast [normal|fast|status] [--global]r  rR   c              3  (   K   | ]
  }|d vr|  ywr  r   r  s     rD   r  z8CLICommandsMixin._handle_fast_command.<locals>.<genexpr>|
  s!      
55 
r  >   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   r   r   r   r   r  _fast_command_availablehermes_cli.modelsr  r   r~   r   r/   r0   r2   r  r6   r   )r:   r   r   r   r   r   r  r  r   r  feature_namer>   rv   r  r  r   saved_valuerW   s                     rD   _handle_fast_commandz%CLICommandsMixin._handle_fast_command_
  sB    	HG++-  M  N	'BD'40EE7D1QWT7D5QE4LU4S0YnL 		!!1!-u:>U1X^^-335A#00J>VHFb	,r&$@AbJ4&QR1X^^%++-335
$
2hh 
)
 

 .  *D KE%% $D"KEb6seD6BCbJ4&QR
01E{Sb	l^8E7BTUYTZ[\b	l^8E7Befjeklmb	l^8E7BmnrmstuI  	'&L	's   ;G GGc                    ddl m} ddlm} |j	                         dd D ch c]  }|j                          }}d|v }d|v xr | } |dd	||d
      } ||       yc c}w )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)SimpleNamespacer   Nlocalnous      T)ru  expirer  r  yes)hermes_cli.debugr  typesr  r/   r2   )	r:   r   r  r  r  wordsr  r  r?   s	            rD   _handle_debug_commandz&CLICommandsMixin._handle_debug_command
  ss     	5)$0$6$6$8$<=q==5 ,u9 au4T
 	 >s   Ac                ,   ddl m}m}  |       rt        d |d              yddg}| j	                  dd	|
      }|t        d       y| j                  ||      }|dk7  rt        d       yt                t        d       t                dg| _        y)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  choicesu     🟡 /update cancelled.r  u     ⚕ Launching update...r  T)r  r  r  r)   _prompt_text_input_modal_normalize_slash_confirm_choice_pending_relaunch)r:   r  r  r  rs  choices         rD   _handle_update_commandz'CLICommandsMixin._handle_update_command
  s     	I<F12GHIJK W<
 ++,P , 

 ;-.55c7CV-.)* #+rF   c                   ddl m} |j                         j                  d      }t	        |      dkD  r!|d   j                         j                         nd}|dk(  r| j                          y|dk(  r| j                          y|dk(  r| j                          y|d	k(  r| j                          y|dk(  r.| j                  r| j                          y| j                          y |d
|         |d       y)z*Handle /voice [on|off|tts|status] command.r   r   r   r   r   r  r  ttsrv   zUnknown voice subcommand: z!Usage: /voice [on|off|tts|status]N)r   r   r   r/   r0   r2   _enable_voice_mode_disable_voice_mode_toggle_voice_tts_show_voice_status_voice_mode)r:   r;   r   r>   r  s        rD   _handle_voice_commandz&CLICommandsMixin._handle_voice_command
  s    %%q%114UaU1X^^%++-R
##%5 $$&5 ""$8###%2((*'')0=>78rF   N)r;   r  )r   r  r   r  )r   r  )r   r  )r   r  r   r   )rq  r  r+   r   )r   r  r   r  )r8  r  r   r  )r   )rn  r  r   r  r   )/r   r   r   __doc__rE   rs   r   r   r   r   r   r   r
  r  r;  rv  rz  r  r  r  r  r)  r/  r9  r=  rD  r_  rf  ro  rT  r  r  r  r@  r/  rN  rZ  rv  rz  r  r  r  r  r  r  r  r  r   rF   rD   r   r   +   s   \.|UUnLB#FJ#1JH4%5Nd2NQ`Unj0X6BS9j,\8MtB]HtJl$*,<+,*0*C48H
Yv%
NcJ@D,\J6X)4V*(X,:3Nj0JdaxF)[V5vn42h9rF   r   )#r  
__future__r   r  r,   r  r  r(  r  r   urllib.parser   richr   r  rich.markupr   r  
rich.panelr   rf   r	   r
   r   agent.turn_contextr   hermes_cli.browser_connectr   r   r   r   r   r   r   r   r   rF   rD   <module>r     sQ    #  	 
     !   )  U :  O+9 O+9rF   