Ë
    âß²j¤W  ã                  óJ  — U d Z ddlmZ ddl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Zded<   dd	d
dddddœZded<   dZded<   dedœ	 	 	 	 	 d,d„Zdad-d„Zd.d„Zd/d„Zd0d„Zd1d„Zd2d„Zd3d„Zd4d„Zd-d „Zd5d!„Zd6d"„Zd-d#„Zd7d8d$„Zd9d%„Zd:d&„Zd;d<d'„Z d(Z!d:d)„Z"d1d*„Z#d=d+„Z$y)>a»  Dependency-light venv recovery that runs BEFORE hermes_cli.main's imports.

Deliberately **stdlib-only** so importing it can never fail on a corrupted venv. ``hermes_cli.main``
calls :func:`recover_if_needed` at the very top of its module body, before any third-party import.
Scope: repair only enough for ``hermes_cli.main`` to become importable again (force-reinstall of
the known-fragile core packages, using the pins from pyproject.toml).
é    )ÚannotationsN)ÚPath))ÚyamlÚ
SafeDumper)ÚdotenvÚload_dotenv)ÚclickÚCommand)ÚcertifiÚcontents)ÚrichÚprint)ÚcryptographyÚ__version__)ÚjwtÚencodeztuple[tuple[str, str], ...]ÚLAZY_REFRESH_IMPORT_PROBESÚPyYAMLzpython-dotenvr	   r   r   r   ÚPyJWT)r   r   r	   r   r   r   r   zdict[str, str]ÚLAZY_REFRESH_REPAIR_PACKAGES)r   éd   éú   iô  iè  útuple[int, ...]ÚQUARANTINE_RESTORE_BACKOFF_MS)ÚstreamÚ
backoff_msc               óò  — |€t         j                  }g }| D �]C  \  }}d}|D ]x  }	 t        j                  j	                  |«      st        j                  j	                  |«      sd} n5|rt        j                  |dz  «       t        j                  ||«       d} n |€Œ‰|j                  ||f«       t        j                  j                  t        |«      «      }	|	j                  «       j                  d«      r|	dd n|	}
t        d|	› d|j                  j                   › dt        j                  j                  t        |«      «      › d|
› d	|› d
|› d�|¬«       �ŒF |S # t        $ r}|}Y d}~�ŒOd}~ww xY w)aN  Rename quarantined shims back, retrying a lock instead of giving up.

    A pair is not a failure when ``original`` already exists or ``quarantined`` has gone: the
    installer wrote a fresh shim, or a concurrent sweep won the race. Both are silent, so two
    processes sweeping the same orphan cannot produce a spurious error.
    Ng     @�@z.exeéüÿÿÿu     âœ– FAILED to restore z (u!   ) â€” it is still quarantined as z.
    `zZ` will NOT be on PATH until it is put back. Run this, then re-run the update:
      move "z" "ú"©Úfile)ÚsysÚstderrÚosÚpathÚexistsÚtimeÚsleepÚrenameÚOSErrorÚappendÚbasenameÚstrÚlowerÚendswithr   Ú	__class__Ú__name__)Úmovedr   r   ÚfailedÚoriginalÚquarantinedÚlast_excÚdelay_msÚexcÚnameÚstems              ú?/home/ubuntu/.hermes/hermes-agent/hermes_cli/_early_recovery.pyÚrestore_quarantined_shimsr<   /   sr  € ð €~Ü—‘ˆØ&(€FØ!&ó 
Ñˆ�+Ø#'ˆØ"ò 	ˆHð
Ü—7‘7—>‘> (Ô+´2·7±7·>±>À+Ô3NØ#�HÙÙÜ—J‘J˜x¨&Ñ0Ô1Ü—	‘	˜+ xÔ0Ø�Ùð	ð ÐØØ�‰�x Ð-Ô.Ü�w‰w×Ñ¤ H£Ó.ˆØ ŸJ™J›L×1Ñ1°&Ô9ˆt�C�R‰y¸tˆÜØ& t fð -Ø×"Ñ"×+Ñ+Ð,ð -Ü—'‘'×"Ñ"¤3 {Ó#3Ó4Ð5ð 6Ø�6ð à&˜- s¨8¨*°Að7ð ÷	
ð'
ð8 €Møô! ò Ø–ûðús   ¦A E Á(2E Å 	E6Å)E1Å1E6Fc                 ó@   — t         xs t        j                  dd dgk(  S )u‚  True inside any ``hermes update`` process (and its import probes).

    Every dotenv load in the process â€” ``hermes_cli.main``, ``run_agent``, ``cli`` â€” consults
    this, so the updater never resolves external secret sources: on Windows they map
    ``cryptography._rust.pyd`` into the process replacing that venv, and everywhere a slow
    ``op``/``bws``/command helper (up to 120s per source) would run inside the updater's
    120s critical-module import probe and be reported as an import-health timeout.
    Profile flags are stripped before ``hermes_cli.main`` loads dotenv, so ``argv[1]`` is
    the authoritative subcommand.
    é   é   Úupdate)Ú_UPDATE_RETRY_RECOVEREDr"   Úargv© ó    r;   Ú$_should_skip_external_secret_sourcesrE   b   s    € ô #ÒA¤c§h¡h¨q° m¸°zÑ&AÐArD   c                 ód   — t        t        «      j                  «       j                  j                  S ©N)r   Ú__file__ÚresolveÚparentrC   rD   r;   Ú_project_rootrK   p   s!   € Ü”‹>×!Ñ!Ó#×*Ñ*×1Ñ1Ð1rD   c                ó  — | dz  }|j                  «       sy	 ddl}t        |d«      5 }|j                  |«      j	                  di «      }ddd«       t        t        «      r|S dS # 1 sw Y   ŒxY w# t
        $ r Y yw xY w)zQ``[project]`` table of ``root/pyproject.toml``; ``None`` when missing/unreadable.úpyproject.tomlNr   ÚrbÚproject)Úis_fileÚtomllibÚopenÚloadÚgetÚ	ExceptionÚ
isinstanceÚdict)ÚrootÚ	pyprojectrQ   ÚfrO   s        r;   Ú_load_pyproject_projectr[   t   s†   € àÐ'Ñ'€IØ×ÑÔØðÛä�)˜TÓ"ð 	9 aØ—l‘l 1“o×)Ñ)¨)°RÓ8ˆG÷	9ô ! ¬$Ô/ˆ7Ð9°TÐ9÷		9ð 	9ûäò Ùðús(   ˜A2 ¨"A&Á
A2 Á&A/Á+A2 Á2	A>Á=A>c                óò   — 	 | j                  dd¬«      j                  «       }|sy	 ddl}t	        |j                  |«      j                  dd«      «      S # t        $ r Y yw xY w# t        t        f$ r Y yw xY w)uO   Attempt counter from a marker's opportunistic JSON body; corrupt/missing â†’ 0.úutf-8Úreplace©ÚencodingÚerrorsr   NÚattempts)	Ú	read_textÚstripr*   ÚjsonÚintÚloadsrT   Ú
ValueErrorÚAttributeError)Úmarker_pathÚrawre   s      r;   Ú_read_marker_attemptsrl   ƒ   s�   € ðØ×#Ñ#¨W¸YÐ#ÓG×MÑMÓOˆñ ØðÛä�4—:‘:˜c“?×&Ñ& z°1Ó5Ó6Ð6øô ò Ùðûô œÐ'ò Ùðús"   ‚!A §-A$ Á	A!Á A!Á$A6Á5A6c                óz   — 	 t        j                  t        j                  ddddg| d¬«       y# t        $ r Y yw xY w)u\   Best-effort pip bootstrap â€” a killed install can leave the venv with no pip module at all.ú-mÚ	ensurepipz	--upgradez--default-pipT)ÚcwdÚcapture_outputN)Ú
subprocessÚrunr"   Ú
executablerU   ©rX   s    r;   Ú_run_ensurepiprv   “   s;   € ðÜ�‰œŸ™¨¨k¸;ÈÐXØ°ö	6øäò Ùðús   ‚+. ®	:¹:c                óT  — | dk  ryt         j                  dk(  �r/	 ddl}d}|j                  dd¬«      }|j                  |j
                  |j                  g|j                  _        |j                  |j                  _	        |j                  |j                  g|j                  _        |j                  |j                  _	        |j                  g|j                  _        |j
                  |j                  _	        |j                  |d| «      }|s|j                  «       d	k(  S 	 |j                  |d«      d
k(  |j                  |«       S 	 t        j                  | d«       y# |j                  |«       w xY w# t        $ r Y yw xY w# t         $ r Y yt"        $ r Y yt$        $ r Y yw xY w)a  Best-effort stdlib-only process liveness probe.

    ``os.kill(pid, 0)`` is not a no-op on Windows, so use the Win32 process handle API there. An
    access-denied result counts as live: racing an elevated updater is worse than postponing
    recovery for one launch.
    r   FÚwin32Ni   Úkernel32T)Úuse_last_erroré   i  )r"   ÚplatformÚctypesÚWinDLLÚc_ulongÚc_intÚOpenProcessÚargtypesÚc_void_pÚrestypeÚWaitForSingleObjectÚCloseHandleÚget_last_errorrU   r$   ÚkillÚProcessLookupErrorÚPermissionErrorr*   )Úpidr}   Úsynchronizery   Úhandles        r;   Ú_pid_is_runningrŽ   œ   sv  € ð ˆa‚xØÜ
‡|�|�wÓð	Ûà$ˆKØ—}‘} ZÀ�}ÓEˆHØ-3¯^©^¸V¿\¹\È6Ï>É>Ð,ZˆH× Ñ Ô)Ø+1¯?©?ˆH× Ñ Ô(Ø5;·_±_ÀfÇnÁnÐ4UˆH×(Ñ(Ô1Ø39·>±>ˆH×(Ñ(Ô0Ø-3¯_©_Ð,=ˆH× Ñ Ô)Ø+1¯<©<ˆH× Ñ Ô(Ø×)Ñ)¨+°u¸cÓBˆFÙØ×,Ñ,Ó.°!Ñ3Ð3ð-Ø×3Ñ3°F¸AÓ>À#ÑEà×$Ñ$ VÕ,ðÜ
�‰��QŒð øð ×$Ñ$ VÕ,ûÜò 	Ùð	ûô ò ÙÜò ÙÜò ÙðúsH   œDE8 Ä$E" Ä8E8 ÅF Å"E5Å5E8 Å8	FÆFÆ	F'ÆF'ÆF'Æ&F'c                ó4  — 	 | j                  dd¬«      }|j                  «       D ]R  }|j                  d«      \  }}}|sŒ|j	                  «       dk(  sŒ/	 t        t        |j	                  «       «      «      c S  y# t        $ r Y yw xY w# t        $ r Y  yw xY w)z?True when a legacy update marker names a process still running.r]   r^   r_   Fú=r‹   )rc   r*   Ú
splitlinesÚ	partitionrd   rŽ   rf   rh   )ÚmarkerÚbodyÚlineÚkeyÚ	separatorÚvalues         r;   Ú_marker_owner_is_liver™   Å   s    € ðØ×Ñ¨¸ÐÓCˆð —‘Ó!ò ˆØ $§¡¨sÓ 3ÑˆˆY˜Ú˜Ÿ™›¨Ó-ðÜ&¤s¨5¯;©;«=Ó'9Ó:Ò:ð	ð øô ò Ùðûô ò Úðús#   ‚A; Á!B
Á;	BÂBÂ
	BÂBc                óÜ  — t        |«      }|€| S i }|j                  dg «      xs g D ]�  }|j                  dd«      d   j                  «       }|}dD ]  }||v sŒ|j                  |d«      d   } n |j                  «       j                  dd«      d   j                  «       j	                  «       }|sŒŒ|||<   Œ’ | D �	cg c]"  }	|j                  |	j	                  «       |	«      ‘Œ$ c}	S c c}	w )uü   Map bare package names to their pinned specs from pyproject.toml.

    Naive requirement-head parsing on purpose â€” ``packaging`` may itself be broken in the failure
    state this module exists for. Unknown packages fall back to their bare name.
    Údependenciesú;r>   r   )z==z>=z<=z~=ú>ú<z!=ú[)r[   rT   Úsplitrd   r.   )
ÚpackagesÚproject_rootrO   Úname_to_specÚspecÚheadÚbareÚopr–   Úpkgs
             r;   Ú_pinned_specsr©   Õ   sõ   € ô & lÓ3€GØ€ØˆØ#%€LØ—‘˜N¨BÓ/Ò5°2ò 	%ˆØ�z‰z˜#˜qÓ! !Ñ$×*Ñ*Ó,ˆØˆØ:ò 	ˆBØ�TŠzØ—z‘z " aÓ(¨Ñ+�Ùð	ð �j‰j‹l× Ñ   aÓ(¨Ñ+×1Ñ1Ó3×9Ñ9Ó;ˆÚØ $ˆL˜Òð	%ð ;CÖC°3ˆL×Ñ˜SŸY™Y›[¨#Õ.ÒCÐCùÒCs   Â?'C)c                 ó¼   — 	 ddl } t        | j                  «       «      }|j                  «        xs |j	                  «       j
                  dk  S # t        $ r Y yw xY w)aZ  True when certifi imports but its ``cacert.pem`` is missing/corrupt.

    A brew Python upgrade or interrupted venv rebuild can leave certifi's metadata intact while
    ``cacert.pem`` is gone or a dangling symlink; an attribute probe passes in that state and every
    TLS connection then fails opaquely, so validate the bundle path itself.
    r   Ni   T)r   r   ÚwhererP   ÚstatÚst_sizerU   )r   Úbundles     r;   Ú_certifi_bundle_brokenr¯   ì   sR   € ðÛä�g—m‘m“oÓ&ˆà—>‘>Ó#Ð#ÒC v§{¡{£}×'<Ñ'<¸tÑ'CÐCøÜò áðús   ‚AA Á	AÁAc                 ó4  — g } t         D ]Q  \  }}	 t        j                  |«      }t        ||«      st	        |› d|› �«      ‚|dk(  rt        «       rt	        d«      ‚ŒS | S # t        $ r/ t        j                  |«      }|r|| vr| j                  |«       Y Œ�w xY w)a"  Import-probe the fragile core packages in THIS process.

    Returns repair package names (deduped, probe order) for modules that fail to import or lack
    their sentinel attribute. Failed imports leave nothing in ``sys.modules``, so a post-repair
    retry in the same process works.
    z	 missing r   z%certifi cacert.pem missing or corrupt)
r   Ú	importlibÚimport_moduleÚhasattrÚImportErrorr¯   rU   r   rT   r+   )ÚbrokenÚmod_nameÚattrÚmodr¨   s        r;   Ú_probe_broken_packagesr¹   þ   s«   € ð €FÜ4ò 
#‰ˆ�$ð		#Ü×)Ñ)¨(Ó3ˆCÜ˜3 Ô%Ü! X J¨i¸°vÐ">Ó?Ð?Ø˜9Ò$Ô)?Ô)AÜ!Ð"IÓJÐJøð
#ð €Møô	 ò 	#Ü.×2Ñ2°8Ó<ˆCÙ�s &Ñ(Ø—‘˜cÔ"ùð	#ús   �AAÁ5BÂBc                 óî   — t         j                  dk(  rdnd} dD ]E  } t        j                  «       j                  g |¢| ‘­Ž }|j                  «       sŒ:t        |«      c S  t        j                  | «      S )aD  Locate a ``uv`` binary without importing third-party modules.

    uv-managed base interpreters carry an ``EXTERNALLY-MANAGED`` marker, so the stdlib ``pip``
    fallback refuses to touch them; the only sanctioned installer is then uv itself, which Hermes
    vendors (``~/.hermes/bin/uv.exe``) or the user has on PATH.
    rx   zuv.exeÚuv))z.hermesÚbin)z.localr¼   )z.cargor¼   )	r"   r|   r   ÚhomeÚjoinpathrP   r-   ÚshutilÚwhich)ÚexeÚsubr%   s      r;   Ú_find_uv_binaryrÃ     si   € ô —l‘l gÒ-‰(°4€CØIò ˆØ#Œt�y‰y‹{×#Ñ#Ð. SÐ.¨#Ò.ˆØ�<‰<�>Ü�t“9Òðô �<‰<˜ÓÐrD   c                 óÂ   — 	 ddl } t        | j                  d«      «      }|dz  j                  «       xs |j                  dz  j                  «       S # t
        $ r Y yw xY w)ac  True when ``sys.executable`` is a uv/standalone-builds managed install.

    Those ship an ``EXTERNALLY-MANAGED`` marker next to their stdlib (PEP 668), so
    ``python -m pip install`` aborts with ``externally-managed-environment``; the early repair
    must then go through uv (or explicitly override pip) or the venv stays broken.

    See #83569.
    r   NÚstdlibzEXTERNALLY-MANAGEDF)Ú	sysconfigr   Úget_pathr&   rJ   rU   )rÆ   rÅ   s     r;   Ú'_base_interpreter_is_externally_managedrÈ   #  se   € ðÛä�i×(Ñ(¨Ó2Ó3ˆàÐ.Ñ.×6Ñ6Ó8ò CØ—M‘MÐ$8Ñ8×@Ñ@ÓBð	Døäò Ùðús   ‚AA Á	AÁAc           	     óH  — 	 t        j                  ||dddd|¬«      }|j                  d
k(  ry|j
                  xs |j                  xs ddd }|rt        |t        j
                  ¬«       y	# t        $ r+}t        d| › d|› �t        j
                  ¬«       Y d}~y	d}~ww xY w)zQRun one installer command; captured output is replayed to stderr only on failure.Tr]   r^   )rp   rq   Útextr`   ra   Úenvu&     âœ— Early venv repair could not run z: r    NFr   Ú i0øÿÿ)rr   rs   rU   r   r"   r#   Ú
returncodeÚstdout)ÚtoolÚcmdrX   rË   Úresultr8   Útails          r;   Ú_run_installerrÓ   7  s›   € ðÜ—‘ ¨¸dÈÐX_Ø'0°cô;ˆð
 ×Ñ˜AÒØØ�M‰MÒ0˜VŸ]™]Ò0¨b°%°&Ð9€DÙÜˆdœŸ™Õ$Øøô ò ÜÐ6°t°f¸B¸s¸eÐDÌ3Ï:É:ÕVÜûðús   ‚A- Á-	B!Á6!BÂB!c                ó¢  — t        «       }|r�t        «       }|rZi t        j                  ¥dt	        |dz  «      i¥}|j                  dd«       |j                  dd«       t        d|ddd	g| ¢||«      S t        d
t        j                  ¬«       t        |«       t        j                  dddd	g}|r|j                  d«       t        d|| z   |«      S )a  ``uv pip`` (or stdlib ``pip``) force-reinstall of the given specs. Never raises.

    Streams nothing to stdout (``hermes acp`` speaks JSON-RPC on stdout). uv is preferred when the
    base interpreter is externally managed; without uv, pip runs with the PEP 668 override.
    ÚVIRTUAL_ENVÚvenvÚ
PYTHONHOMENÚ
PYTHONPATHr»   ÚpipÚinstallz--force-reinstalluw     âš  Base interpreter is externally managed and no uv binary was found; retrying repair via pip with PEP 668 override.r    rn   z--break-system-packages)rÈ   rÃ   r$   Úenvironr-   ÚpoprÓ   r   r"   r#   rv   rt   r+   )Úspecsr¢   Úexternally_managedr»   rË   Úpip_cmds         r;   Ú_run_repair_installrà   G  sÓ   € ô AÓBÐÙÜÓˆÙØK”R—Z‘ZÐK ´°LÀ6Ñ4IÓ0JÑKˆCØ�G‰G�L $Ô'Ø�G‰G�L $Ô'Ü! $¨¨U°IÐ?RÐ([ÐUZÐ([Ø".°ó5ð 5äð FÜLOÏJÉJõ	Xä�<Ô Ü�~‰~˜t U¨IÐ7JÐK€GÙØ�‰Ð0Ô1Ü˜% ¨5¡°,Ó?Ð?rD   c                ó’   — dt         j                  v xr4 | t        t        «      j	                  «       j
                  j
                  k(  S )u~  True under pytest when ``root`` is this module's own checkout â€” the venv running the suite.

    Lifecycle tests spawn real subprocesses that import ``hermes_cli.main`` with recovery armed and
    inherit ``PYTEST_CURRENT_TEST``; without this guard a broken dev venv would get a REAL
    ensurepip + force-reinstall from inside a running suite. tmp_path roots are unaffected.
    ÚPYTEST_CURRENT_TEST)r$   rÛ   r   rH   rI   rJ   ru   s    r;   Ú_pytest_owns_live_checkoutrã   _  s6   € ð !¤B§J¡JÐ.Òa°4¼4Ä»>×;QÑ;QÓ;S×;ZÑ;Z×;aÑ;aÑ3aÐarD   c                ó`  — 	 |€t         j                  dd n|}| €
t        «       n| }t        |«      ry|dz  }|dz  }|j	                  «       s|j	                  «       sy|dz  j                  «       sy|j	                  «       rt        |«      ryt        ||«      rd|v rdayd|v ryt        «       }|syt        |«      sy	 t        ||«      }t        dd	j                  |«      › �t         j                  ¬
«       t        ||«      r&t        «       st        dt         j                  ¬
«       nZt        dt         j                  ¬
«       t        dt         j                   › d�dj                  |«      z   t         j                  ¬
«       t#        |«       y# t#        |«       w xY w# t$        $ r Y yw xY w)al  Repair wiped core packages so ``hermes_cli.main`` can import at all.

    Fast path (no marker present) is two ``lstat`` calls. Only acts when a recovery marker from a
    prior ``hermes update`` exists AND an import probe confirms a core package is actually broken.
    Never raises: on any failure the import of main.py proceeds and surfaces the real error.
    Nr>   z.update-incompletez.lazy-refresh-incompleterM   r@   TuQ   âš  Core package(s) broken by an interrupted update â€” repairing before launch: z, r    u     âœ“ Core packages repaired.u9     âœ— Automatic repair incomplete. Recover manually with:z    z" -m pip install --force-reinstall ú )r"   rB   rK   rã   r&   rP   r™   Ú_complete_pending_core_installrA   r¹   Ú_claim_recovery_lockr©   r   Újoinr#   rà   rt   Ú_release_recovery_lockrU   )r¢   rB   ÚargsrX   Úcore_markerÚlazy_markerrµ   rÝ   s           r;   Úrecover_if_neededrí   i  s›  € ð8Ø#˜|Œs�x‰x˜˜‰|°ˆØ".Ð"6Œ}Œ¸LˆÜ% dÔ+ØØÐ1Ñ1ˆØÐ7Ñ7ˆØ×!Ñ!Ô#¨K×,>Ñ,>Ô,@Øð Ð'Ñ'×0Ñ0Ô2Øð ×ÑÔÜ$ [Ô1ØÜ-¨d°KÔ@ÀXÐQUÑEUØ*.Ð'Øð �tÑØä'Ó)ˆÙØô $ DÔ)Øð	)Ü! &¨$Ó/ˆEÜð .Ø.2¯i©i¸Ó.?Ð-@ðBÜHKÏ
É
õTä" 5¨$Ô/Ô8NÔ8PÜÐ5¼C¿J¹JÖGäÐQÔX[×XbÑXbÕcÜ˜œSŸ^™^Ð,Ð,NÐOÐRU×RZÑRZÐ[`ÓRaÑaÜŸ:™:õ'ô # 4Õ(øÔ" 4Õ(ûÜò ÙðúsS   ‚0F! ³*F! ÁF! Á2F! ÂF! Â!F! Â&F! Â3F! Ã CF ÆF! ÆFÆF! Æ!	F-Æ,F-é   c                ó  — | dz  }	 t        j                  |t         j                  t         j                  z  t         j                  z  «      }t        j
                  |t        j                  «       › d�j                  «       «       t        j                  |«       y# t        $ rV 	 t        j                  «       |j                  «       j                  z
  dkD  r|j                  «        Y y# t        $ r Y Y yw xY wt        $ r Y yw xY w)z?Single-flight claim on the shared recovery lock.  Never raises.ú.update-incomplete.lockú
Ti  F)r$   rR   ÚO_CREATÚO_EXCLÚO_WRONLYÚwriteÚgetpidr   ÚcloseÚFileExistsErrorr'   r¬   Úst_mtimeÚunlinkr*   )rX   Ú	lock_pathÚfds      r;   rç   rç   ³  sÓ   € àÐ0Ñ0€IðÜ�W‰W�Y¤§
¡
¬R¯Y©YÑ 6¼¿¹Ñ DÓEˆÜ
�‰�œŸ	™	›�} BÐ'×.Ñ.Ó0Ô1Ü
�‰�ŒØøÜò ð	Ü�y‰y‹{˜YŸ^™^Ó-×6Ñ6Ñ6¸Ò=Ø× Ñ Ô"ñ øô ò 	ØÙð	úô ò áðús1   ‡BB Â	DÂ&AC*Ã*	C7Ã3DÃ6C7Ã7DÄDc                óJ   — 	 | dz  j                  «        y# t        $ r Y yw xY w)z0Best-effort release of the shared recovery lock.rð   N)rú   r*   ru   s    r;   ré   ré   Ç  s+   € ðØ	Ð)Ñ	)×1Ñ1Õ3øÜò Ùðús   ‚ –	"¡"c           	     ó¢  — 	 ddl m} t        |«      }|t        k\  r t	        d|› d�t
        j                  ¬«       yt        | «      sy	 t	        dt
        j                  ¬«       |j                  | «       	 t        | «       	 |j                  «        t	        dt
        j                  ¬«       y# t        $ ri}|j                  |«      }t	        d|› d	t        › d
|› �t
        j                  ¬«       t	        dt
        j                  ¬«       Y d}~t        | «       yd}~ww xY w# t        | «       w xY w# t        $ r Y Œ¬w xY w# t        $ r Y yw xY w)uå  Run the pending core install BEFORE main.py can import native modules.

    Never raises: any failure leaves the marker for the post-import path and returns ``False``.
    Returns ``True`` only after the install succeeds.

    ``recover_if_needed`` invokes this when ``.update-incomplete`` exists â€” a prior ``hermes update`` (or
    the self-lock preflight, #83569) left the dependency sync deliberately unfinished. Completing it here
    matters on Windows: the deferral exists precisely because the process that wrote the marker had a native
    venv extension mapped; this process, running before ``hermes_cli.main``'s third-party imports, maps
    nothing yet, so the installer can replace ``.pyd`` files without hitting the lock.
    r   )Ú_install_repairu:   âš  Pending interrupted-update install has already failed uJ    times in the early pass â€” leaving it for the post-import recovery path.r    Fu‹   âš  A previous `hermes update` was interrupted mid-install â€” finishing dependency installation now (before any native extensions load)...u;     âœ— Early interrupted-install completion failed (attempt ú/z): z]  The next launch will retry; hermes will keep working from the current venv in the meantime.Nu:     âœ“ Dependency installation completed in the early pass.T)Ú
hermes_clirÿ   rl   Ú _EARLY_CORE_INSTALL_MAX_ATTEMPTSr   r"   r#   rç   Úrun_core_installrU   Úbump_marker_attemptsré   rú   r*   )rX   rë   Úirrb   r8   Únew_attemptss         r;   ræ   ræ   Ï  sM  € ð"Ý4ô )¨Ó5ˆØÔ7Ò7ÜÐNØ�Jð /ð/ä58·Z±ZõAð Ü# DÔ)Øð	)Üð (ä.1¯j©jõ:ð ×Ñ Õ%ô # 4Ô(ð	Ø×ÑÔ ô 	ÐJÔQT×Q[ÑQ[Õ\Øøô ò 	Ø×2Ñ2°;Ó?ˆLÜÐOØ!�N !Ô$DÐ#EÀSÈÈðOÜUX×U_ÑU_õaäð 6Ü<?¿J¹JõHãä" 4Õ(ûð	ûô # 4Õ(ûô ò 	Ùð	ûô ò Ùðúsw   ‚9E ¼E Á	,B. Á6E ÂD3 ÂE Â.	D Â7ADÄD# ÄE ÄD Ä D# Ä#D0Ä0E Ä3	D?Ä<E Ä>D?Ä?E Å	EÅE)r2   úlist[tuple[Path, Path]]r   r   Úreturnr  )r  Úbool)r  r   )rX   r   r  údict | None)rj   r   r  rf   )rX   r   r  ÚNone)r‹   rf   r  r	  )r“   r   r  r	  )r¡   ú	list[str]r¢   r   r  r  )r  r  )r  z
str | NonerG   )
rÏ   r-   rÐ   r  rX   r   rË   r
  r  r	  )rÝ   r  r¢   r   r  r	  )rX   r   r  r	  )NN)r¢   zPath | NonerB   zlist[str] | Noner  r  )rX   r   rë   r   r  r	  )%Ú__doc__Ú
__future__r   r±   r$   r¿   rr   r"   r'   Úpathlibr   r   Ú__annotations__r   r   r<   rA   rE   rK   r[   rl   rv   rŽ   r™   r©   r¯   r¹   rÃ   rÈ   rÓ   rà   rã   rí   r  rç   ré   ræ   rC   rD   r;   ú<module>r     s  ðòõ #ã Û 	Û Û Û 
Û Ý ð;Ð Ð7ó ð  ¸'ÈiØ N¸7ñ0Ð ˜nó ð 2JÐ ˜Ó Ið /3Ø"?ñ)Ø"ð)àð)ð ó)ð`  Ð óBó2ó:óó ó&óRó Dó.ó$ó,óô(ó @ó0bôAðN $%Ð  óó(ô.rD   