
    
Bj*                    h    d Z ddlmZ ddlZddlZddgZdaddZddZd	d
dddZ	ddZ
ddZddZy)u  Windows-safe stdio configuration.

On Windows, Python's ``sys.stdout``/``sys.stderr`` default to the console's
active code page (often ``cp1252``, sometimes ``cp437``, occasionally ``cp932``
on Japanese locales, etc.).  Hermes's banners, tool output feed, and slash
command listings all contain Unicode: box-drawing characters (``─┌┐└┘├┤``),
mathematical and geometric symbols (``◆ ◇ ◎ ▣ ⚔ ⚖ →``), and user-supplied
text in any language.  Printing those to a cp1252 console raises
``UnicodeEncodeError: 'charmap' codec can't encode character…`` and kills the
whole CLI before the REPL even opens.

The fix is to force UTF-8 on the Python side and also flip the console's
code page to UTF-8 (65001).  Both matter: Python-level only helps when
Python's stdout is a real TTY; code-page flipping lets subprocesses and
child Python ``print()`` calls agree on encoding.

This module is a no-op on every non-Windows platform, and idempotent.
Entry points (``cli.py`` ``main``, ``hermes_cli/main.py`` CLI dispatch,
``gateway/run.py`` startup) call :func:`configure_windows_stdio` exactly
once early in startup.

Patterns cribbed from Claude Code (``src/utils/platform.ts``), OpenCode
(``packages/opencode/src/pty/index.ts`` env injection), and OpenAI Codex
(``codex-rs/core/src/unified_exec/process_manager.rs``).  None of those
actually flip the console code page — they rely on their runtime (Node or
Rust) writing UTF-16 to the Win32 console API and letting the terminal
sort it out.  Python doesn't get that luxury.
    )annotationsNconfigure_windows_stdio
is_windowsFc                 (    t         j                  dk(  S )z4Return True iff running on native Windows (not WSL).win32)sysplatform     5/home/ubuntu/.hermes/hermes-agent/hermes_cli/stdio.pyr   r   )   s    <<7""r   c                     	 ddl } | j                  j                  }|j                  d       |j	                  d       y# t
        $ r Y yw xY w)us  Set the attached console's input and output code pages to UTF-8.

    Uses ``SetConsoleCP`` / ``SetConsoleOutputCP`` via ``ctypes``.  Failure
    is silent — if there's no attached console (e.g. Hermes is running
    behind a redirected stdout, under a service, or inside a PTY-less CI
    runner) these calls simply return 0 and we move on.

    CP_UTF8 is 65001.
    r   Ni  )ctypeswindllkernel32SetConsoleCPSetConsoleOutputCP	Exception)r   r   s     r   _flip_console_code_page_to_utf8r   .   sI    
==))e$##E*  	s   <? 	A
Autf-8replaceencodingerrorsc               X    	 t        | dd      }|y |||       y# t        $ r Y yw xY w)zReconfigure a text stream to UTF-8 in place.

    Uses ``TextIOWrapper.reconfigure`` (Python 3.7+).  If the stream isn't
    a ``TextIOWrapper`` (e.g. it's been redirected to an ``io.StringIO``
    during tests), we skip rather than blow up.
    reconfigureNr   )getattrr   )streamr   r   r   s       r   _reconfigure_streamr   E   s:    fmT:Xf5 s    
 	))c                 p   t         ryt               sda yt        j                  j	                  d      dv rda yt        j                  j                  dd       t        j                  j                  dd       t               } | rQt        j                  j	                  d	      s2t        j                  j	                  d
      s| t        j                  d	<   t                t                t        t        j                         t        t        j                         t        t        j                         da y)u  Force UTF-8 stdio on Windows.  No-op elsewhere.

    Idempotent — safe to call multiple times from different entry points.

    Returns ``True`` if anything was actually changed, ``False`` on
    non-Windows or on a repeat call.

    Set ``HERMES_DISABLE_WINDOWS_UTF8=1`` in the environment to opt out
    (for diagnosing encoding-related bugs by forcing the old cp1252 path).

    Also sets a sensible default ``EDITOR`` on Windows if none is already
    set — see :func:`_default_windows_editor`.
    FTHERMES_DISABLE_WINDOWS_UTF8>   1yesTruetruePYTHONIOENCODINGr   
PYTHONUTF8r!   EDITORVISUAL)_CONFIGUREDr   osenvironget
setdefault_default_windows_editor_augment_path_with_known_toolsr   r   r   stdoutstderrstdin)_default_editors    r   r   r   U   s      <	zz~~348TT
 JJ,g6 JJ,, ./Orzz~~h7

x@X.

8 #$ $% 

#

# 		"Kr   c                 0    ddl } | j                  d      ryy)u  Return a Windows-appropriate default for ``$EDITOR``.

    Priority order, first match wins:

    1. ``notepad`` — ships with every Windows install, no deps, works as a
       blocking editor (``subprocess.call(["notepad", file])`` blocks until
       the user closes the window).  This is the "always-works" default.

    The prompt_toolkit buffer's ``open_in_editor`` and Hermes's
    ``hermes config edit`` both honour ``$EDITOR``.  Users who prefer a
    different editor can override:

    - VSCode: ``$env:EDITOR = "code --wait"``  (``--wait`` is critical;
      without it the editor returns immediately and any input is lost)
    - Notepad++: ``$env:EDITOR = "'C:\Program Files\Notepad++\notepad++.exe' -multiInst -nosession"``
    - Neovim: ``$env:EDITOR = "nvim"``  (if installed)

    Set this before launching Hermes (User env var in Windows Settings, or
    export in a PowerShell profile) and Hermes picks it up automatically.
    r   Nnotepad )shutilwhich)r7   s    r   r.   r.      s    * 
 ||I r   c            
        t               syddl} t        j                  j	                  dd      }|syt        j
                  j                  |ddd      t        j
                  j                  |ddd      t        j
                  j                  |ddd	d      t        j
                  j                  |dd
dd      t        j
                  j                  |ddd      g}t        j                  j	                  dd      }|j                  t        j                        D ch c]  }|s|j                          }}g }|D ]F  }t        j
                  j                  |      s#|j                         |vs6|j                  |       H |r5t        j                  j                  g ||      t        j                  d<   yyc c}w )uS  Prepend well-known Hermes-managed tool directories to os.environ['PATH'].

    Fixes the "User PATH was just updated but my process can't see it" gap on
    Windows.  When install.ps1 runs, it adds entries like
    ``%LOCALAPPDATA%\hermes\git\bin`` to the User PATH via
    ``SetEnvironmentVariable(..., "User")``.  That write propagates to newly
    *spawned* processes only — already-running shells (including the one the
    user invokes ``hermes`` from right after install) retain their old PATH.

    Any subprocess Hermes spawns — bash, ``rg``, ``grep``, ``npm`` — inherits
    that stale PATH and reports commands as missing even though they're on
    disk.  Symptom: ``search_files`` reports "rg/find not available" when
    the user clearly just installed ripgrep.

    Patch-up strategy: add the known Hermes-managed tool directories to our
    PATH at startup so subprocess calls resolve correctly.  No-op on POSIX
    and when the directories don't exist.  The User PATH broadcast still
    happens in the background for future shells; this just smooths over
    the first-launch gap.
    Nr   LOCALAPPDATAr6   hermesgitcmdbinusrzhermes-agentvenvScripts	MicrosoftWinGetLinksPATH)r   r7   r*   r+   r,   pathjoinsplitpathseplowerisdirappend)_shutillocal_appdatacandidate_dirsexistingpexisting_lowerprependds           r   r/   r/      sY   * <JJNN>26M 	]HeU;
]HeU;
]HeUEB 	]HnfiP
 	]K7CN zz~~fb)H)1

)CIAqaggiINIG 77==	 ?NN1 ZZ__-Aw-A-AB

6  Js   F>%F>)returnbool)rU   None)r   strr   rX   rU   rW   )rU   rX   )__doc__
__future__r   r*   r   __all__r)   r   r   r   r   r.   r/   r
   r   r   <module>r\      sO   : # 	 
$l
3 #
. 4;)  IXD9Cr   