
    sj)                        d Z ddlmZ ddlZddlZg dZddZdd	Zd dZd!dZ	d!dZ
d dZd"dZddZd dZd#dZd#dZddd$dZd%d&dZdS )'u  Pre-import startup fast paths — THE canonical lightweight helpers.

This module is imported by ``hermes_cli/main.py`` BEFORE its heavy import
wall (config, argparse tree, logging, providers). Everything here must stay
**stdlib-only and cheap** (os/sys file probes; no yaml, no hermes_cli.config,
no argparse). A guard test (``test_startup_fast_import_weight``) subprocess-
imports this module and fails if any heavy module sneaks into sys.modules.

Why this module exists (the bug class it kills): version-printing kept being
reimplemented as ``*_fast()`` copies at the top of main.py (Termux first,
then globally), each duplicating canonical logic — project-root resolution,
container detection, profile detection. The copies drifted: eb4040242
changed the canonical output and referenced ``PROJECT_ROOT`` inside the fast
function, which doesn't exist yet on the fast path → the Termux fast path
NameError'd on --version and nobody noticed. One implementation, imported
by both the fast path and the module constants, makes that drift
structurally impossible; the parity guard test would have caught eb4040242
the day it landed.

``hermes_cli/config.py``'s ``get_container_exec_info()`` reads the same
``.container-mode`` file; keep the file-format assumptions here and there in
sync (this module deliberately only PROBES existence/typos cheaply and errs
toward the slow path, which then does the authoritative parse).
    )annotationsN)project_root_strensure_project_root_on_pathis_termux_envis_termux_fast_version_argvis_global_fast_version_argv is_container_startup_environment active_profile_may_override_homecontainer_mode_may_be_activeread_openai_versionread_install_methodprint_fast_version_infotry_fast_versionreturnstrc                     t           j                            t           j                            t           j                            t
                    t           j                            S )uD   Repo root as a str — the single source for main.py's PROJECT_ROOT.)ospathrealpathjoindirname__file__pardir     </home/agent/.hermes/hermes-agent/hermes_cli/_startup_fast.pyr   r   /   s8    7BGLL)B)BBINNOOOr   Nonec                 *   t                      } t          j                            t          j                            |                     fdt
          j        D             t
          j        dd<   t
          j                            d|            dS )zCPut the project root at sys.path[0], deduping realpath-equivalents.c                    g | ]F}|r@t           j                            t           j                            |                    k    D|GS r   )r   r   normcaser   ).0entrynormalized_roots     r   
<listcomp>z/ensure_project_root_on_path.<locals>.<listcomp>8   s[        7BG,,U3344GG 	 HGGr   Nr   )r   r   r   r    r   sysinsert)project_rootr#   s    @r   r   r   4   s    #%%Lg&&rw'7'7'E'EFFO   X  CHQQQK HOOA|$$$$$r   boolc                     t           j                            dd          } t          t           j                            d          pd| v p|                     d                    S )z3Tiny Termux check for pre-import startup shortcuts.PREFIX TERMUX_VERSIONzcom.termux/files/usrz/data/data/com.termux/)r   environgetr(   
startswith)prefixs    r   r   r   A   s_    Z^^Hb))F

'(( 	7!V+	7566  r   argv	list[str]c                    | dgdgfv S Nz	--versionz-Vr   r1   s    r   r   r   K       [MD6***r   c                    | dgdgfv S r4   r   r5   s    r   r   r   O   r6   r   c                 :   t           j                            d          st           j                            d          rdS 	 t          dd          5 } |                                 }ddd           n# 1 swxY w Y   n# t
          $ r Y dS w xY wd	|v pd
|v pd|v S )zDTrue when we're already INSIDE a container (fast path is then safe).z/.dockerenvz/run/.containerenvTz/proc/1/cgrouputf-8encodingNFdockerpodmanz/lxc/)r   r   existsopenreadOSError)handlecgroups     r   r	   r	   S   s    	w~~m$$ 7K(L(L t"W555 	#[[]]F	# 	# 	# 	# 	# 	# 	# 	# 	# 	# 	# 	# 	# 	# 	#   uuvHV!3Hw&7HHs6   B  A4(B  4A88B  ;A8<B   
BBhermes_rootc                ~   t           j                            | d          }	 t           j                            |          rdt	          |d          5 }|                                                                }ddd           n# 1 swxY w Y   t          |o|dk              S n# t          t          f$ r Y nw xY wdS )zECheap probe: does an active non-default profile redirect HERMES_HOME?active_profiler9   r:   NdefaultF)
r   r   r   r>   r?   r@   stripr(   rA   UnicodeDecodeError)rD   rF   rB   actives       r   r
   r
   _   s    W\\+/?@@N7>>.)) 	8nw777 /6,,../ / / / / / / / / / / / / / /66Y#6777	8 '(   5s5   0B& 'B9B& B		B& B	B& &B:9B:c                     t           j                            dd                                          } | r| S t           j                            t           j                            d          d          S )NHERMES_HOMEr+   ~.hermes)r   r-   r.   rH   r   r   
expanduser)hermes_homes    r   _resolved_homerQ   l   sW    *..3399;;K 7<<**3//;;;r   c                 D   t           j                            d          dk    rdS t                      rdS t           j                            dd                                          } | rt           j                            t           j                            | d                    rdS t           j                            t           j        	                    t           j        
                    |                               }|dk    ot          |           S t           j                            t           j                            d	          d
          }t          |          rdS t           j                            t           j                            |d                    S )u  Conservative probe for NixOS container-mode routing.

    False positives are fine (we fall through to the slow path, whose
    ``get_container_exec_info()`` does the authoritative check and routes
    into the container). False negatives are NOT fine — they'd print the
    host's version instead of the container's. Hence: any profile
    ambiguity → assume container mode may be active.
    
HERMES_DEV1FrL   r+   z.container-modeTprofilesrM   rN   )r   r-   r.   r	   rH   r   r>   r   basenamer   normpathr
   rO   )rP   parent_namedefault_homes      r   r   r   s   s;    
z~~l##s**u')) u*..3399;;K 
7>>"',,{4EFFGG 	4g&&rwrw7G7G7T7T'U'UVV:% >0==	

 7<< 2 23 7 7CCL'55 t7>>"',,|5FGGHHHr   
str | Nonec                 D   t           j        D ]} | st          j                    } t          j                            | dd          }	 t          |d          5 }|D ]}|                                }|                    d          s,|                    d          \  }}}|	                    dd          d	                                                             d
          }|pdc cddd           c S 	 ddd           n# 1 swxY w Y   # t          $ r Y w xY wdS )zARead OpenAI SDK version without importing ``importlib.metadata``.openaiz_version.pyr9   r:   __version__=#   r   z"'N)r%   r   r   getcwdr   r?   rH   r/   	partitionsplitrA   )baseversion_filerB   linestripped_key_sepvalues           r   r   r      s      	9;;Dw||D(MBB
	lW555 )" ) )D#zz||H#..}== ! (0(:(:3(?(?%D$!KKQ//288::@@GGE =D(() ) ) ) ) ) ) ) ) ))) ) ) ) ) ) ) ) ) ) ) ) ) ) )  	 	 	H	4s=   DBD&D6DD	D	D	
D
DDc                 H   t           j                            t                      d          } 	 t	          | d          5 }|                                                                                                }ddd           n# 1 swxY w Y   |pdS # t          $ r Y dS w xY w)u  Read the installer's ``.install_method`` stamp, if present.

    Only the stamp (step 1 of ``config.detect_install_method``'s resolution
    order) — the managed/git/pip fallbacks need heavier imports and stay on
    the slow path. On the fast path home ambiguity is already excluded:
    ``container_mode_may_be_active()`` bails to the slow path whenever a
    non-default profile might redirect HERMES_HOME.
    z.install_methodr9   r:   N)	r   r   r   rQ   r?   r@   rH   lowerrA   )stamprB   methods      r   r   r      s     GLL))+<==E%'*** 	3f[[]]((**0022F	3 	3 	3 	3 	3 	3 	3 	3 	3 	3 	3 	3 	3 	3 	3~   tts4   B 9B8B BB BB 
B! B!T)check_updatesro   c           	        	 ddl m} t           |                       n.# t          $ r! ddlm}m} t          d| d| d           Y nw xY wt          dt                                  	 ddlm	} dd	l
m}  | |t                                          }n# t          $ r t                      }Y nw xY w|rt          d
|            t          dt          j                                        d                     t!                      }t          |rd| nd           | sdS 	 ddl m}m}	 ddl
m}
  |	            }||k    rt          d |
             d           dS |r3|dk    r-|dk    rdnd}t          d| d| d |
             d           dS |dk    rt          d           dS dS # t          $ r Y dS w xY w)uQ  THE canonical ``hermes --version`` output (also used by /version).

    The static lines print instantly from stdlib-only probes; everything
    heavier (upstream SHA in the version line, authoritative install-method
    detection, the update-status check) is lazy-imported AFTER the first
    line is already on screen, so perceived latency stays instant while the
    output carries the full information that used to require the (removed)
    ``hermes version`` subcommand. Every lazy block degrades gracefully —
    a broken/heavy import can never take the basic version output down.
    r   )format_banner_version_label)__release_date__r]   zHermes Agent vz ()zInstall directory: )Path)detect_install_methodzInstall method: zPython: zOpenAI SDK: zOpenAI SDK: Not installedN)UPDATE_AVAILABLE_NO_COUNTcheck_for_updates)recommended_update_commandu   Update available — run ''r`   commitcommitszUpdate available:  u    behind — run 'z
Up to date)hermes_cli.bannerrq   print	Exception
hermes_clirr   r]   r   pathlibrt   hermes_cli.configru   r   r%   versionrc   r   rv   rw   rx   )ro   rq   rr   r]   rt   ru   install_methodopenai_versionrv   rw   rx   behindcommits_words                r   r   r      s   CAAAAAA))++,,,, C C C<<<<<<<<A{AA.>AAABBBBBC
 

4 0 2 2
4
4555/      ;;;;;;..tt4D4F4F/G/GHH / / /,../ 3111222	
-S[&&((+
-
-...(**N	^
\
)
)
)
)A\]]] 
RRRRRRRR@@@@@@""$$...N/I/I/K/KNNNOOOOO 	 

'-{{88	L8V 8 8l 8 822448 8 8     q[[, [   s?     (A
A-,B B54B5)9F2 $3F2 F2 2
G ?G list[str] | Nonec                "   | t           j        dd         } t                      }|r%t          j                            d          dk    rdS |rt          |           sdS n!t          |           sdS t                      rdS t                       dS )uc  Handle ``hermes --version`` before the heavy import wall.

    Only ``--version``/``-V`` (the ``version`` subcommand was removed —
    ``--version`` now carries the full output incl. update status), and
    never when container mode may need to route the command into the
    container. Termux keeps the HERMES_TERMUX_DISABLE_FAST_CLI escape hatch.
    Nr`   HERMES_TERMUX_DISABLE_FAST_CLIrT   FT)
r%   r1   r   r   r-   r.   r   r   r   r   )r1   	is_termuxs     r   r   r      s     |x|I RZ^^$DEELLu *400 	5	(.. u	%	'	' u4r   )r   r   )r   r   )r   r(   )r1   r2   r   r(   )rD   r   r   r(   )r   rZ   )ro   r(   r   r   )N)r1   r   r   r(   )__doc__
__future__r   r   r%   __all__r   r   r   r   r   r	   r
   rQ   r   r   r   r   r   r   r   r   <module>r      s{   2 # " " " " " 				 



   P P P P

% 
% 
% 
%   + + + ++ + + +	I 	I 	I 	I
 
 
 
< < < <I I I I<   (   $ 6: C C C C C CL      r   