
    id                        d Z ddlZddlZddlZddlZddlZddlmZ ddlm	Z	m
Z
 ddlZ ej        e          Z eh d          Zd#de	ded	efd
Zd$deded	efdZded	dfdZdeddd	dfdZddde
eef         de	dede	d	df
dZddddde
eef         de	dedededz  d	dfdZd%dede	d	e	fdZd&d eded	efd!Zd#d eded	efd"ZdS )'z*Shared utility functions for hermes-agent.    N)Path)AnyUnion>   1onyestrueFvaluedefaultreturnc                     | |S t          | t                    r| S t          | t                    r-|                                                                 t
          v S t          |           S )zDCoerce bool-ish values using the project's shared truthy string set.)
isinstanceboolstrstriplowerTRUTHY_STRINGS)r
   r   s     -/home/agentuser/.hermes/hermes-agent/utils.pyis_truthy_valuer      s`    }% % 7{{}}""$$66;;     namec                 J    t          t          j        | |          d          S )zBReturn True when an environment variable is set to a truthy value.Fr   r   osgetenv)r   r   s     r   env_var_enabledr      s!    29T733UCCCCr   pathz
int | Nonec                     	 |                                  r+t          j        |                                 j                  ndS # t          $ r Y dS w xY w)zBCapture the permission bits of *path* if it exists, else ``None``.N)existsstatS_IMODEst_modeOSError)r   s    r   _preserve_file_moder&   #   sV    48KKMMKt|DIIKK/000tK   tts   A A 
AAmodec                 \    |dS 	 t          j        | |           dS # t          $ r Y dS w xY w)a  Re-apply *mode* to *path* after an atomic replace.

    ``tempfile.mkstemp`` creates files with 0o600 (owner-only).  After
    ``os.replace`` swaps the temp file into place the target inherits
    those restrictive permissions, breaking Docker / NAS volume mounts
    that rely on broader permissions set by the user.  Calling this
    right after ``os.replace`` restores the original permissions.
    N)r   chmodr%   )r   r'   s     r   _restore_file_moder*   +   sM     |
t   s    
++   )indentdatar,   dump_kwargsc                   t          |           } | j                            dd           t          |           }t	          j        t          | j                  d| j         dd          \  }}	 t          j	        |dd	          5 }t          j        ||f|d
d| |                                 t          j        |                                           ddd           n# 1 swxY w Y   t          j        ||            t!          | |           dS # t"          $ r( 	 t          j        |           n# t&          $ r Y nw xY w w xY w)a  Write JSON data to a file atomically.

    Uses temp file + fsync + os.replace to ensure the target file is never
    left in a partially-written state. If the process crashes mid-write,
    the previous version of the file remains intact.

    Args:
        path: Target file path (will be created or overwritten).
        data: JSON-serializable data to write.
        indent: JSON indentation (default 2).
        **dump_kwargs: Additional keyword args forwarded to json.dump(), such
            as default=str for non-native types.
    Tparentsexist_ok._.tmpdirprefixsuffixwutf-8encodingF)r,   ensure_asciiN)r   parentmkdirr&   tempfilemkstempr   stemr   fdopenjsondumpflushfsyncfilenoreplacer*   BaseExceptionunlinkr%   )r   r-   r,   r.   original_modefdtmp_pathfs           r   atomic_json_writerQ   <   s   ( ::DKdT222'--M#49  LB
Yr3111 		!QI "	 
    GGIIIHQXXZZ   		! 		! 		! 		! 		! 		! 		! 		! 		! 		! 		! 		! 		! 		! 		! 	
8T"""4/////   	Ih 	 	 	D	sU   1D AC%D %C))D ,C)-(D 
E	"D76E	7
EE	EE	)default_flow_style	sort_keysextra_contentrR   rS   rT   c                   t          |           } | j                            dd           t          |           }t	          j        t          | j                  d| j         dd          \  }}	 t          j	        |dd	          5 }t          j        ||||
           |r|                    |           |                                 t          j        |                                           ddd           n# 1 swxY w Y   t          j        ||            t#          | |           dS # t$          $ r( 	 t          j        |           n# t(          $ r Y nw xY w w xY w)an  Write YAML data to a file atomically.

    Uses temp file + fsync + os.replace to ensure the target file is never
    left in a partially-written state.  If the process crashes mid-write,
    the previous version of the file remains intact.

    Args:
        path: Target file path (will be created or overwritten).
        data: YAML-serializable data to write.
        default_flow_style: YAML flow style (default False).
        sort_keys: Whether to sort dict keys (default False).
        extra_content: Optional string to append after the YAML dump
            (e.g. commented-out sections for user reference).
    Tr0   r3   r4   r5   r6   r:   r;   r<   )rR   rS   N)r   r?   r@   r&   rA   rB   r   rC   r   rD   yamlrF   writerG   rH   rI   rJ   r*   rK   rL   r%   )	r   r-   rR   rS   rT   rM   rN   rO   rP   s	            r   atomic_yaml_writerX   q   s   , ::DKdT222'--M#49  LB
Yr3111 	!QIdA2DPYZZZZ '&&&GGIIIHQXXZZ   	! 	! 	! 	! 	! 	! 	! 	! 	! 	! 	! 	! 	! 	! 	! 	
8T"""4/////   	Ih 	 	 	D	sU   1D0 A*C>2D0 >DD0 D(D0 0
E";EE"
EE"EE"textc                 t    	 t          j        |           S # t           j        t          t          f$ r |cY S w xY w)zParse JSON, returning *default* on any parse error.

    Replaces the ``try: json.loads(x) except (JSONDecodeError, TypeError)``
    pattern duplicated across display.py, anthropic_adapter.py,
    auxiliary_client.py, and others.
    )rE   loadsJSONDecodeError	TypeError
ValueError)rY   r   s     r   safe_json_loadsr_      sE    z$ )Z8   s    77keyc                     t          j        | d                                          }|s|S 	 t          |          S # t          t
          f$ r |cY S w xY w)z:Read an environment variable as an integer, with fallback.r   )r   r   r   intr^   r]   )r`   r   raws      r   env_intrd      se    
)C


"
"
$
$C 3xx	"   s   < AAc                 J    t          t          j        | d          |          S )z*Read an environment variable as a boolean.r   r   r   )r`   r   s     r   env_boolrf      s!    29S"--w????r   )F)r   )N)r   )__doc__rE   loggingr   r"   rA   pathlibr   typingr   r   rV   	getLogger__name__logger	frozensetr   r   r   r   r   r&   r*   rb   rQ   rX   r_   rd   rf    r   r   <module>rp      s   0 0   				                 		8	$	$ 55566 3  $    D D# D DT D D D D
d |    T  $    * 	2 2 2
T	
2
2 	2
 2 
2 2 2 2r  % $0 0 0
T	
0
0 	0
 0 :0 
0 0 0 0l
 
# 
 
s 
 
 
 
   s 3    @ @# @ @ @ @ @ @ @ @r   