
    
Bj*                        U d Z ddlm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Z e       Zded	<   ddd
ZddZddZddZddd	 	 	 	 	 ddZy)zFHelpers for loading Hermes .env files consistently across entrypoints.    )annotationsN)Path)load_dotenv)atomic_replace)_API_KEY_TOKEN_SECRET_KEYzset[str]_WARNED_KEYSc                    g }| D ]^  }t        |      dkD  sdt        |      d}|j                         r	|d|dz  }||vr|j                  |       t        |      |k\  s^ n dj	                  |      S )zEReturn a compact 'U+XXXX ('c'), ...' summary of non-ASCII codepoints.   zU+04X ()z, )ordisprintableappendlenjoin)valuelimitseenchlabels        :/home/ubuntu/.hermes/hermes-agent/hermes_cli/env_loader.py_format_offending_charsr      s    D r7S=R&E~~2bV1%D E"4yE! 99T?    c                 b   t        t        j                  j                               D ]0  \  } t	        fdt
        D              s	 | j                  d       2 y# t        $ r Y nw xY w| j                  dd      j                  d      }|t        j                  <   t        v rt        j                         t        |       t        |      z
  }t        |       xs d}t        d d| d|d	k7  rd
nd d| d	t        j                         t        dt        j                         )a!  Strip non-ASCII characters from credential env vars in os.environ.

    Called after dotenv loads so the rest of the codebase never sees
    non-ASCII API keys.  Only touches env vars whose names end with
    known credential suffixes (``_API_KEY``, ``_TOKEN``, etc.).

    Emits a one-line warning to stderr when characters are stripped.
    Silent stripping would mask copy-paste corruption (Unicode lookalike
    glyphs from PDFs / rich-text editors, ZWSP from web pages) as opaque
    provider-side "invalid API key" errors (see #6843).
    c              3  @   K   | ]  }j                  |        y w)N)endswith).0suffixkeys     r   	<genexpr>z/_sanitize_loaded_credentials.<locals>.<genexpr>5   s     KF3<<'Ks   asciiignore)errorsznon-printablez  Warning: z contained z non-ASCII character   s r   u8   ) — stripped so the key can be sent as an HTTP header.)filea@    This usually means the key was copy-pasted from a PDF, rich-text editor, or web page that substituted lookalike
  Unicode glyphs for ASCII letters. If authentication fails (e.g. "API key not valid"), re-copy the key from the
  provider's dashboard and run `hermes setup` (or edit the .env file in a plain-text editor).N)listosenvironitemsany_CREDENTIAL_SUFFIXESencodeUnicodeEncodeErrordecoder   addr   r   printsysstderr)r   cleanedstrippeddetailr#   s       @r   _sanitize_loaded_credentialsr<   (   s    2::++-. 

UK6JKK	LL!
 " 		,,wx,8??H!

3,u:G,(/B?#k(3G!ms,Bvh 712 		
 	1 	
s   	A	A)(A)c                   	 t        | |d       t                y # t        $ r t        | |d       Y t                y w xY w)Nutf-8)dotenv_pathoverrideencodingzlatin-1)r   UnicodeDecodeErrorr<   )pathr@   s     r   _load_dotenv_with_fallbackrD   T   sC    Mx'J !"  Mx)L !"Ms    ??c                   | j                         sy	 ddlm} ddd}	 t	        | fi |5 }|j                         }ddd        |      }||k7  rddl}|j                  t        | j                        dd	      \  }}	 t        j                  |d
d      5 }|j                  |       |j                          t        j                  |j                                ddd       t!        ||        yy# t        $ r Y yw xY w# 1 sw Y   xY w# 1 sw Y   2xY w# t"        $ r' 	 t        j$                  |        # t&        $ r Y  w xY ww xY w# t(        $ r Y yw xY w)u  Pre-sanitize a .env file before python-dotenv reads it.

    python-dotenv does not handle corrupted lines where multiple
    KEY=VALUE pairs are concatenated on a single line (missing newline).
    This produces mangled values — e.g. a bot token duplicated 8×
    (see #8908).

    We delegate to ``hermes_cli.config._sanitize_env_lines`` which
    already knows all valid Hermes env-var names and can split
    concatenated lines correctly.
    Nr   )_sanitize_env_linesz	utf-8-sigreplace)rA   r'   z.tmpz.env_)dirr"   prefixwr>   )rA   )existshermes_cli.configrF   ImportErroropen	readlinestempfilemkstempstrparentr-   fdopen
writelinesflushfsyncfilenor   BaseExceptionunlinkOSError	Exception)	rC   rF   read_kwforiginal	sanitizedrP   fdtmps	            r   _sanitize_env_file_if_neededrc   a   s]    ;;=9 ')<G$"'" 	%a{{}H	%'1	 &&$VG ' GBYYr39 )QLL+GGIHHQXXZ() sD) !  
	% 	%) )
 ! IIcN     s   C3 E DAE  D ADD 3	C?>C?DE DD 	E
$D:9E
:	EE
EE

E 	EE)hermes_homeproject_envc                   g }t        | xs+ t        j                  dt        j                         dz              }|dz  }|rt        |      nd}|j	                         rt        |       |r|j	                         rt        |       |j	                         rt        |d       |j                  |       |r/|j	                         rt        ||        |j                  |       |S )a[  Load Hermes environment files with user config taking precedence.

    Behavior:
    - `~/.hermes/.env` overrides stale shell-exported values when present.
    - project `.env` acts as a dev fallback and only fills missing values when
      the user env exists.
    - if no user env exists, the project `.env` also overrides stale shell vars.
    HERMES_HOMEz.hermesz.envNT)r@   )r   r-   getenvhomerK   rc   rD   r   )rd   re   loaded	home_pathuser_envproject_env_paths         r   load_hermes_dotenvrn      s     F[UBIImTYY[9=T$UVI6!H,7tK(T $X.,335$%56"8d;h,335"#3&jI&'Mr   )   )r   rR   r   intreturnrR   )rq   None)rC   r   r@   boolrq   rr   )rC   r   rq   rr   )rd   str | os.PathLike | Nonere   rt   rq   z
list[Path])__doc__
__future__r   r-   r7   pathlibr   dotenvr   utilsr   r1   setr   __annotations__r   r<   rD   rc   rn    r   r   <module>r}      sp    L " 	 
     A 
 h )
X
#*^ -1,0!)! *! 	!r   