
    i&                        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dS )%zFHelpers for loading Hermes .env files consistently across entrypoints.    )annotationsN)Path)load_dotenv)atomic_replace)_API_KEY_TOKEN_SECRET_KEYzset[str]_WARNED_KEYS   valuestrlimitintreturnc                   g }| D ]s}t          |          dk    r^dt          |          d}|                                r	|d|dz  }||vr|                    |           t          |          |k    r ntd                    |          S )zEReturn a compact 'U+XXXX ('c'), ...' summary of non-ASCII codepoints.   zU+04X ()z, )ordisprintableappendlenjoin)r   r   seenchlabels        :/home/ubuntu/.hermes/hermes-agent/hermes_cli/env_loader.py_format_offending_charsr       s    D  r77S==&R&&&E~~ &b%D  E"""4yyE!!99T??    Nonec                    t          t          j                                                  D ]&\  } t	          fdt
          D                       s'	 |                     d           ># t          $ r Y nw xY w|                     dd                              d          }|t          j        <   t          v rt          
                               t          |           t          |          z
  }t          |           pd}t          d d| d|d	k    rd
nd d| d	t          j                   t          dt          j                   (dS )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  B   K   | ]}                     |          V  d S )N)endswith).0suffixkeys     r   	<genexpr>z/_sanitize_loaded_credentials.<locals>.<genexpr>5   s/      KKF3<<''KKKKKKr!   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_credentialsrA   (   s    2:++--.. 
 

UKKKK6JKKKKK 		LL!!!! 	 	 	D	,,wx,88??HH!
3,u::G,(//B?2# 2 2( 2 2!mmss2 2/52 2 2 		
 	
 	
 	
 	1 	
 	
 	
 	
 	
+
 
s   A++
A87A8pathr   overrideboolc                   	 t          | |d           n"# t          $ r t          | |d           Y nw xY wt                       d S )Nutf-8)dotenv_pathrC   encodingzlatin-1)r   UnicodeDecodeErrorrA   )rB   rC   s     r   _load_dotenv_with_fallbackrJ   T   sn    Mx'JJJJJ M M Mx)LLLLLLM !"""""s    44c                   |                                  sdS 	 ddlm} n# t          $ r Y dS w xY wddd}	 t	          | fi |5 }|                                }ddd           n# 1 swxY w Y    ||          }||k    rddl}|                    t          | j	                  dd	          \  }}	 t          j        |d
d          5 }|                    |           |                                 t          j        |                                           ddd           n# 1 swxY w Y   t!          ||            dS # t"          $ r( 	 t          j        |           n# t&          $ r Y nw xY w w xY wdS # t(          $ r Y dS 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_linesrF   replace)rH   r,   z.tmpz.env_)dirr'   prefixw)rH   )existshermes_cli.configrL   ImportErroropen	readlinestempfilemkstempr   parentr2   fdopen
writelinesflushfsyncfilenor   BaseExceptionunlinkOSError	Exception)	rB   rL   read_kwforiginal	sanitizedrV   fdtmps	            r   _sanitize_env_file_if_neededrh   a   sl    ;;== 9999999    #i88G$""'"" 	%a{{}}H	% 	% 	% 	% 	% 	% 	% 	% 	% 	% 	% 	% 	% 	% 	%''11	  OOO&&$$VG '  GBYr3999 )QLL+++GGIIIHQXXZZ((() ) ) ) ) ) ) ) ) ) ) ) ) ) ) sD)))))    IcNNNN   D ! "    s    
--E9 A$E9 $A((E9 +A(,AE9 2E 	AD%E %D))E ,D)-E 
E4E"!E4"
E/,E4.E//E44E9 9
FF)hermes_homeproject_envri   str | os.PathLike | Nonerj   
list[Path]c                (   g }t          | p(t          j        dt          j                    dz                      }|dz  }|rt          |          nd}|                                rt          |           |r#|                                rt          |           |                                r&t          |d           |                    |           |r;|                                r't          ||            |                    |           |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)rC   )r   r2   getenvhomerQ   rh   rJ   r   )ri   rj   loaded	home_pathuser_envproject_env_paths         r   load_hermes_dotenvru      s"    F[UBImTY[[9=T$U$UVVI6!H,7AtK(((T  /$X... 7,3355 7$%5666  "8d;;;;h (,3355 ("#3&jIIII&'''Mr!   )r   )r   r   r   r   r   r   )r   r"   )rB   r   rC   rD   r   r"   )rB   r   r   r"   )ri   rk   rj   rk   r   rl   )__doc__
__future__r   r2   r<   pathlibr   dotenvr   utilsr   r6   setr   __annotations__r    rA   rJ   rh   ru    r!   r   <module>r~      s   L L L " " " " " " 				 



                         A 
         )
 )
 )
 )
X
# 
# 
# 
#* * * *^ -1,0! ! ! ! ! ! ! !r!   