
    PL
j*                    j    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dS )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_windowsFreturnboolc                 "    t           j        dk    S )z4Return True iff running on native Windows (not WSL).win32)sysplatform     4/home/kuhnn/.hermes/hermes-agent/hermes_cli/stdio.pyr   r   )   s    <7""r   Nonec                     	 ddl } | j        j        }|                    d           |                    d           dS # t
          $ r Y dS 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   .   sl    
=)e$$$##E*****    	s   :> 
AAutf-8replaceencodingerrorsr   strr   c               n    	 t          | dd          }|dS  |||           dS # t          $ r Y dS 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::FXf555555   s   & & 
44c                    t           rdS t                      sda dS t          j                            d          dv rda dS t          j                            dd           t          j                            dd           t                      } | rMt          j                            d	          s.t          j                            d
          s| t          j        d	<   t                       t                       t          t          j                   t          t          j                   t          t          j                   da dS )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&      u<< u	z~~3448TTTu
 J,g666 J,,,, .//O /rz~~h77 /
x@X@X /.
8 #$$$ $%%% 
###
### 	"""K4r   c                 <    ddl } |                     d          rdS dS )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)r;   s    r   r2   r2      s/    * MMM
 ||I y 2r   c            
     d   t                      sdS ddl} t          j                            dd          }|sdS t          j                            |ddd          t          j                            |ddd          t          j                            |ddd	d          t          j                            |dd
dd          t          j                            |ddd          g}t          j                            dd          }d |                    t          j                  D             }g }|D ]L}t          j        	                    |          r+|
                                |vr|                    |           M|r2t          j                            g ||          t          j        d<   dS dS )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   LOCALAPPDATAr:   hermesgitcmdbinusrzhermes-agentvenvScripts	MicrosoftWinGetLinksPATHc                :    h | ]}||                                 S r   )lower).0ps     r   	<setcomp>z1_augment_path_with_known_tools.<locals>.<setcomp>   s%    IIIAqIaggiiIIIr   )r   r;   r.   r/   r0   pathjoinsplitpathsepisdirrK   append)_shutillocal_appdatacandidate_dirsexistingexisting_lowerprependds          r   r3   r3      s   * << JNN>266M  	]HeU;;
]HeU;;
]HeUEBB 	]HnfiPP
 	]K7CCN z~~fb))HII
)C)CIIING  7== 			 ? ?NN1 CZ__-Aw-A-ABB
6C Cr   )r   r   )r   r   )r   r   r   r   r   r   )r   r   )__doc__
__future__r   r.   r
   __all__r-   r   r   r"   r   r2   r3   r   r   r   <module>r_      s    : # " " " " " 				 



$l
3 # # # #
   . 4;)       I I I IX   D9C 9C 9C 9C 9C 9Cr   