
    `gj               
          d Z ddlZddlZddlZddlmZmZ ddlmZm	Z	 de
eeef      fdZ e       Zdee   de
e   fdZdee   fd	Zd
dddee   dedeee      de
e   fdZd
dddee   dedeee      ddfdZy)aN  
Unified self-relaunch for Hermes CLI.

Preserves critical flags (--tui, --dev, --profile, --model, etc.) across
process replacement so that ``hermes sessions browse`` or post-setup relaunch
doesn't silently drop the user's UI mode or other preferences.

Also works when ``hermes`` is not on PATH (e.g. ``nix run`` or ``python -m``).
    N)OptionalSequence)PRE_ARGPARSE_INHERITED_FLAGSbuild_top_level_parserreturnc                  d   t               \  } }}g }t               }| |fD ]y  }|j                  D ]h  }|j                  st	        |dd      s|j
                  dk7  }|j                  D ]-  }||f}	|	|vs|j                  |	       |j                  |	       / j { |j                  t               |S )u(  Build the ``(option_string, takes_value)`` table of flags that must
    survive a self-relaunch, by introspecting the real parser used by
    ``hermes`` itself.

    A flag participates if its argparse Action carries
    ``inherit_on_relaunch = True`` — set by ``_parser._inherited_flag``.
    inherit_on_relaunchFr   )
r   set_actionsoption_stringsgetattrnargsaddappendextendr   )
parser_subparserschat_parsertableseenpactiontakes_valueoptkeys
             F/root/.hermes/venv/lib/python3.12/site-packages/hermes_cli/relaunch.py_build_inherited_flag_tabler      s     (>'?$FK$&E"%%Dk" &jj 
	&F((6#8%@ ,,!+K,, &K(d?HHSMLL%	&
	&& 
LL-.L    argvc                    g }d}|t        |       k  r| |   }d|v rA|j                  dd      d   }t        D ]  \  }}||k(  s|j                  |        n |dz  }Xt        D ]c  \  }}||k(  s|j                  |       |rD|dz   t        |       k  r3| |dz      j	                  d      s|j                  | |dz             |dz  } n |dz  }|t        |       k  r|S )zDPull out flags that should carry over into a self-relaunched hermes.r   =   -)lensplit_INHERITED_FLAGS_TABLEr   
startswith)r   flagsiargr   flag_r   s           r   _extract_inherited_flagsr-   6   s   E	A
c$i-1g#:))C#A&C1 a$;LL% FA!7 	D+d{S!1q53t9#4T!a%[=S=STW=XLLa!e-FA	 	
Q% c$i-& Lr   c                  |   t         j                  d   } t         j                  dk(  }dt        dt        fd}t
        j                  j                  |       rOt
        j                  j                  |       r0t        j                  | t
        j                        r|r ||       s| S | j                  d      snt
        j                  j                  |       rOt
        j                  j                  |       }t        j                  |t
        j                        r|r ||      s|S t        j                  d      }|r|S y)	u;  Find the hermes entry point.

    Priority:
      1. ``sys.argv[0]`` if it resolves to a real executable.
      2. ``shutil.which("hermes")`` on PATH.
      3. ``None`` → caller should fall back to ``python -m hermes_cli.main``.

    Windows note: ``os.access(path, os.X_OK)`` returns True for ``.py`` and
    ``.pyc`` files on Windows (the OS treats anything listed in PATHEXT as
    executable, and Python files are often registered there).  But
    ``subprocess.run([script.py, ...])`` can't actually execute a .py
    directly — CreateProcessW needs a real .exe, not a script associated
    with the Python launcher.  On Windows we therefore skip the argv[0]
    fast-path when it points at a .py file and fall through to either
    ``hermes.exe`` on PATH or the ``sys.executable -m hermes_cli.main``
    fallback.
    r   win32r   r   c                 @    | j                         j                  d      S )N)z.pyz.pyc)lowerendswith)r   s    r   _is_python_scriptz-resolve_hermes_bin.<locals>._is_python_scripte   s    wwy!!/22r   r#   hermesN)sysr   platformstrboolospathisabsisfileaccessX_OKr'   abspathshutilwhich)argv0_is_windowsr3   abs_pathpath_bins        r   resolve_hermes_binrF   P   s    $ HHQKE,,')K3S 3T 3 
ww}}Uu 5"))E277:S 1% 8L C RWW^^E%:77??5)99Xrww'$5h$? ||H%Hr   Tpreserve_inheritedoriginal_argv
extra_argsrH   rI   c                    t               }|r|g}nt        j                  ddg}|t        |      nt        t        j                  dd       }|r|j                  t        |             |j                  |        |S )a  Construct an argv list for replacing the current process with hermes.

    Args:
        extra_args: Arguments to append (e.g. ``["--resume", id]``).
        preserve_inherited: Whether to carry over UI / behaviour flags
            tagged with ``inherit_on_relaunch`` in the parser.
        original_argv: The original argv to scan for flags (defaults to
            ``sys.argv[1:]``).
    z-mzhermes_cli.mainNr"   )rF   r5   
executablelistr   r   r-   )rJ   rH   rI   bin_pathr   srcs         r   build_relaunch_argvrP   |   sm     "#Hz&78!.!:$}
SXXab\@RC,S12KK
Kr   c          	         t        | ||      }t        j                  dk(  r6ddl}	 |j	                  |      }t        j
                  |j                         yt        j                  |d   |       y# t        $ r t        j
                  d       Y yt        $ rP}t        d| ddj                  |       d	t        j                  
       t        j
                  d       Y d}~yd}~ww xY w)uH  Replace the current process with a fresh hermes invocation.

    On POSIX we use ``os.execvp`` which replaces the running process with
    the new one in place — same PID, no double-fork.  That's what the
    relaunch contract wants: "run hermes again as if the user had typed
    the new argv".

    Windows has no native exec semantics — ``os.execvp`` on Windows
    *emulates* exec by spawning the child and exiting the parent, but
    only works when the target is a real Win32 executable.  Our target
    is usually ``hermes.exe`` (a Python console-script shim that wraps
    ``python -m hermes_cli.main``) or a ``.cmd`` batch file, and both
    raise ``OSError(8, "Exec format error")`` on Windows' execvp.

    The Windows-correct pattern is: spawn the child with ``subprocess.run``
    (which routes through ``cmd.exe`` via ``shell=False`` + PATHEXT resolution),
    wait for it to exit, then propagate its exit code via ``sys.exit``.
    That's functionally equivalent — the user sees "hermes exited, then
    new hermes started" — just with two PIDs in play instead of one.
    rG   r/   r   N   z
Hermes relaunch failed: z

Command:  z?
Fix: open a new terminal so PATH picks up, then re-run hermes.)filer"   )rP   r5   r6   
subprocessrunexit
returncodeKeyboardInterruptOSErrorprintjoinstderrr9   execvp)rJ   rH   rI   new_argvrU   resultexcs          r   relaunchrb      s    4 #'9H ||w	^^H-FHHV&&'  			(1+x( ! 	HHSM 	
 ,SE 2HHX./ 0QR ZZ	 HHQKK	s   0A2 2C*C*AC%%C*)__doc__r9   r@   r5   typingr   r   hermes_cli._parserr   r   rM   tupler7   r8   r   r&   r-   rF   rP   rb    r   r   <module>rh      s    
  
 %T%T	*:%; : 56 8C= T#Y 4)HSM )^  $-1	  HSM*	
 
#YD  $-1	2)2) 2) HSM*	2)
 
2)r   