Ë
    âß²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	Z	ddl
mZ ddlZddlmZmZmZ  ej"                  e«      ZdZ e«       Zded<    e«       Zded	<    e«       Zded
<   i Zded<   i Zded<   i Zded<    e«       Zded<    e	j<                  «       Zi Z ded<    ejB                  «       Z" e	j<                  «       Z# e$dh«      Z%ded<    e$h d£«      Z&ded<   d0d„Z'd1d„Z(d2d„Z)d3d„Z*d4d„Z+d4d„Z,d5d„Z-d6d7d„Z.d8d „Z/d9d:d!„Z0d;d"„Z1dd#œd<d$„Z2d1d%„Z3ddd&d'œ	 	 	 	 	 	 	 d=d(„Z4d>d)„Z5dd#œd?d*„Z6d>d+„Z7dd,œd@d-„Z8dAd.„Z9dBd/„Z:y)CzFHelpers for loading Hermes .env files consistently across entrypoints.é    )ÚannotationsN)ÚPath)Úatomic_replaceÚfast_safe_loadÚload_yaml_file_readonly)Ú_API_KEYÚ_TOKENÚ_SECRETÚ_KEYúset[str]Ú_WARNED_KEYSÚ_WARNED_UTF32_PATHSÚ_SCOPED_SKIP_LOGGEDúdict[str, str]Ú_SECRET_SOURCESzdict[str, dict[str, str]]Ú_SECRET_SOURCE_VALUES_BY_HOMEÚ_SECRET_SOURCE_RESTORE_BY_HOMEÚ_APPLIED_HOMESz&dict[str, tuple[str | None, str, int]]Ú_DOTENV_PUBLISHEDÚHERMES_DASHBOARD_SESSION_TOKENzfrozenset[str]Ú_SPAWN_CREDENTIAL_KEYS>   ÚCOPILOT_CLI_PATHÚCOPILOT_ACP_BASE_URLÚHERMES_ACP_AUTH_METHODÚHERMES_ACP_AUTO_APPROVEÚHERMES_COPILOT_ACP_ARGSÚHERMES_COPILOT_ACP_COMMANDÚ_PROFILE_MANAGED_ENV_KEYSc                ó0   — ddl m} t         || «      «      S )uÓ   KEY names assigned in a dotenv file (including empty ``KEY=``), via the same tokenizer that installs
    profile scopes â€” a key the installer sees is a key the dashboard scrub sees (BOM'd first line included).r   )Úload_env_file)Úagent.secret_scoper    Úset)Úpathr    s     ú:/home/ubuntu/.hermes/hermes-agent/hermes_cli/env_loader.pyÚ_env_keys_defined_in_dotenvr%   J   s   € õ 1ä‰}˜TÓ"Ó#Ð#ó    c                ó¤   — | j                  «       syt        | «      }t        D ]+  }||vsŒ|t        j                  v sŒt        j                  |= Œ- y)a@  After ``.env`` loaded with override, delete inherited ``_PROFILE_MANAGED_ENV_KEYS`` it does not
    define. Deliberately NARROW: only keys that change *which provider path* is used.

    Does **not** run when the ``.env`` file does not exist (bare-profile case, which follows ``#66930`` /
    ``#67027`` semantics).
    N)Úexistsr%   r   ÚosÚenviron)r#   ÚdefinedÚkeys      r$   Ú%_clear_known_keys_missing_from_dotenvr-   R   sG   € ð �;‰;Œ=ØÜ)¨$Ó/€GÜ(ò  ˆØ�gÒ #¬¯©Ò"3Ü—
‘
˜3‘ñ r&   c                ó,   — t         j                  | «      S )u›   Source label that supplied ``env_var`` (``"bitwarden"`` â€¦), None for .env/shell keys. Metadata only â€”
    never authorization to persist the raw value.)r   Úget)Úenv_vars    r$   Úget_secret_sourcer1   a   s   € ô ×Ñ˜wÓ'Ð'r&   c                 ó    — t        t        «      S )u¶   Every env-var name some profile's external secret source supplied (names only â€” the map is
    process-wide, so a value must be resolved through the active profile's secret scope).)Útupler   © r&   r$   Úsecret_source_namesr5   g   s   € ô ”Ó!Ð!r&   c           	     ó€   — t        t        j                  t        t	        | «      j                  «       «      i «      «      S )z>Return the external-secret value snapshot for ``hermes_home``.)Údictr   r/   Ústrr   Úresolve©Úhermes_homes    r$   Úget_secret_source_valuesr<   m   s/   € äÔ-×1Ñ1´#´d¸;Ó6G×6OÑ6OÓ6QÓ2RÐTVÓWÓXÐXr&   c                ób   — t         5  t        t        | «      «      cddd«       S # 1 sw Y   yxY w)až  Resolve one profile's configured sources without mutating ``os.environ``: multiplex gateways route
    turns to profiles that never ran the process-global dotenv path, so resolve against a private mapping
    seeded from that ``.env`` and record the per-home snapshot for ``build_profile_secret_scope()``.
    Fail-open / once-per-home like ``_apply_external_secret_sources``; never returns plaintext .env entries.N)Ú_SECRET_SOURCE_CACHE_LOCKÚ_hydrate_profile_secret_sourcesr   r:   s    r$   Úhydrate_profile_secret_sourcesr@   r   s-   € ô
 
#ñ BÜ.¬t°KÓ/@ÓA÷B÷ Bò Bús   ‡%¥.c                óê  — t        | j                  «       «      }|t        v rt        | «      S t        j                  |d«       t        j                  |d«       	 t        | «      }|si S 	 ddl	m
}m} ddlm} t        j                  j!                  «       D ��ci c]  \  }} ||«      sŒ||“Œ }}}|j#                   || dz  «      «       | dz  }	|	j%                  «       r0 ||	«      j!                  «       D ]  \  }
}|j'                  |
|«       Œ t        | «      |d<    ||| |¬«      }|j(                  si S t+        d	„ |j(                  D «       «      rt        j-                  |«       i }|j.                  j!                  «       D ]1  \  }}|j1                  |«      }|€Œ|j2                  t4        |<   |||<   Œ3 |t        |<   t7        |«      S # t        $ r i cY S w xY wc c}}w # t        $ r i cY S w xY w)
zALocked implementation for :func:`hydrate_profile_secret_sources`.Nr   )Ú_is_global_envr    ©Ú	apply_allú.envú.op.envÚHERMES_HOME)r*   c              3  óH   K  — | ]  }|j                   j                  –— Œ y ­w©N)ÚresultÚok)Ú.0Úsrcs     r$   ú	<genexpr>z2_hydrate_profile_secret_sources.<locals>.<genexpr>¦   s   è ø€ Ò
3˜Sˆ3�:‰:�=�=Ñ
3ùs   ‚ ")r8   r9   r   r<   r   Úpopr   Ú_load_secrets_configÚ	Exceptionr!   rB   r    Úagent.secret_sources.registryrD   r)   r*   ÚitemsÚupdater(   Ú
setdefaultÚsourcesÚallÚaddÚ
provenancer/   Úsourcer   r7   )ÚhomeÚhome_keyÚcfgrB   r    rD   ÚnameÚvalueÚ	local_envÚop_envÚ_nameÚ_valueÚreportÚvaluesÚapplieds                  r$   r?   r?   {   sá  € ä�4—<‘<“>Ó"€HØ”>Ñ!Ü'¨Ó-Ð-ô "×%Ñ% h°Ô5Ü"×&Ñ& x°Ô6ðÜ" 4Ó(ˆñ Øˆ	ðßDÝ;ä46·J±J×4DÑ4DÓ4F×_¡[ T¨5É.ÐY]ÕJ^�T˜5‘[Ð_ˆ	Ñ_Ø×Ñ™ t¨f¡}Ó5Ô6ð
 ˜	Ñ!ˆØ�=‰=Œ?Ù!.¨vÓ!6×!<Ñ!<Ó!>ò 4‘��vØ×$Ñ$ U¨FÕ3ð4ä#& t£9ˆ	�-Ñ Ù˜3 ¨iÔ8ˆð �>Š>Øˆ	ô
 Ñ
3 F§N¡NÔ
3Ô3Ü×Ñ˜8Ô$Ø€FØ×*Ñ*×0Ñ0Ó2ò ‰ˆˆgØ—‘˜dÓ#ˆØˆ=ØØ '§¡Œ˜ÑØˆˆtŠðð /5Ô! (Ñ+Ü�‹<ÐøôQ ò ØŠ	ðüó `øô ò ØŠ	ðús=   ÁG Á*/G$ ÂGÂ*GÂ/A;G$ ÇGÇGÇG$ Ç$G2Ç1G2c                óp  — | €Qt         j                  «        t        j                  «        t        j                  «        t        j                  «        yt        t        | «      j                  «       «      }t         j                  |«       t        j                  |d«       t        j                  |d«       y)u«  Forget applied homes so the next load re-pulls (tests, long-running processes after config edits).

    ``hermes_home`` limits the reset to ONE home: a multiplex gateway keeps every profile's snapshot in
    this process, and a per-fire cron re-pull or a plugin-discovery refresh for one home must not wipe
    a sibling's hydrated snapshot â€” the sibling's next scope build would run empty until it re-hydrated
    (#102041).N)
r   Úclearr   r   r   r8   r   r9   ÚdiscardrO   )r;   r\   s     r$   Úreset_secret_source_cacherj   ³   sƒ   € ð ÐÜ×ÑÔÜ×ÑÔÜ%×+Ñ+Ô-Ü&×,Ñ,Ô.ØÜ”4˜Ó$×,Ñ,Ó.Ó/€HÜ×Ñ˜8Ô$Ü!×%Ñ% h°Ô5Ü"×&Ñ& x°Õ6r&   c                ó®   — t        | «      }|sy|dk(  ry	 ddlm}  ||«      }|�|j                  rd|j                  › d�S d|› d�S # t        $ r Y Œw xY w)zc``" (from Bitwarden)"``-style suffix; ``""`` for .env/shell keys (only external sources are named).Ú Ú	bitwardenz (from Bitwarden)r   ©Ú
get_sourcez (from ú))r1   rR   ro   ÚlabelrQ   )r0   rZ   ro   Ú
registereds       r$   Úformat_secret_source_suffixrs   Æ   sx   € ä˜wÓ'€FÙØØ�ÒØ"ðÝ<á Ó'ˆ
ØÐ! j×&6Ò&6Ø˜Z×-Ñ-Ð.¨aÐ0Ð0ð �V�H˜AÐÐøô ò Ùðús   –+A Á	AÁAc                óî   — g }| D ]^  }t        |«      dkD  sŒdt        |«      d›�}|j                  «       r	|d|›d�z  }||vr|j                  |«       t        |«      |k\  sŒ^ n dj	                  |«      S )z>Compact ``U+XXXX ('c'), ...`` summary of non-ASCII codepoints.é   zU+Ú04Xú (rp   z, )ÚordÚisprintableÚappendÚlenÚjoin)r_   ÚlimitÚseenÚchrq   s        r$   Ú_format_offending_charsr€   Ù   s‚   € à€DØò ˆÜˆr‹7�S‹=Øœ˜R› ˜Ð&ˆEØ�~‰~ÔØ˜2˜b˜V 1˜Ñ%�Ø˜DÑ Ø—‘˜EÔ"Ü�4‹y˜EÓ!Ùðð �9‰9�T‹?Ðr&   c                 ó>  ‡— t        t        j                  j                  «       «      D ]ò  \  Š} t	        ˆfd„t
        D «       «      sŒ| j                  «       rŒ0| j                  dd¬«      j                  d«      }|t        j                  ‰<   ‰t        v rŒnt        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                  ¬«       Œô y)au  Strip non-ASCII from credential env vars (``_CREDENTIAL_SUFFIXES``) so the codebase never sees them.

    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rI   )Úendswith)rL   Úsuffixr,   s     €r$   rN   z/_sanitize_loaded_credentials.<locals>.<genexpr>ð   s   øè ø€ ÒK¨F�3—<‘< ×'ÑKùó   ƒÚasciiÚignore)Úerrorsznon-printablez  Warning: z contained z non-ASCII characteré   Úsrl   rw   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)Úlistr)   r*   rS   ÚanyÚ_CREDENTIAL_SUFFIXESÚisasciiÚencodeÚdecoder   rX   r{   r€   ÚprintÚsysÚstderr)r_   ÚcleanedÚstrippedÚdetailr,   s       @r$   Ú_sanitize_loaded_credentialsr™   è   s  ø€ ô œ2Ÿ:™:×+Ñ+Ó-Ó.ò 
‰
ˆˆUÜÓKÔ6JÔKÔKØØ�=‰=Œ?ØØ—,‘,˜w¨x�,Ó8×?Ñ?ÀÓHˆØ!Œ�
‰
�3‰Ø”,ÑØÜ×Ñ˜ÔÜ�u“:¤ G£Ñ,ˆÜ(¨Ó/ÒB°?ˆÜ�˜C˜5 ¨H¨:Ð5IØ  Aš‘¨2Ð.¨b°°ð 93ð4ä:=¿*¹*õ	Fô 	ð1ô —‘ö	
ñ
r&   ©Ú	load_passc               ó’  ‡— | j                  «       }	 |j                  d«      }ddlm} ddl	m
} t         |dt        j                  |«      d¬«      j                  «       «      }t        5  |€t!        t"        «      }t%        t&        j(                  «      }t*        j-                  «       D ]/  \  }	\  }
}}||k7  sŒ|j/                  |	«      |k(  sŒ%|
€||	= Œ+|
||	<   Œ1 i }|D ]:  \  }	}|�.|ri |¥|¥ni |¥|¥Šd	j1                  ˆfd
„ ||«      D «       «      }|||	<   Œ< |j-                  «       D ]“  \  }	}|�|s|	t&        j(                  v rŒt&        j(                  j/                  |	«      }t*        j/                  |	«      }|duxr ||d   k(  }|	t2        v r|r|sŒl|r|d   n|}
|t&        j(                  |	<   |
||ft*        |	<   Œ• 	 ddd«       t5        «        y# t        $ rP |j                  t        j
                  «      r|t        t        j
                  «      d }|j                  d«      }Y �Œw xY w# 1 sw Y   t5        «        yxY w)uG  Load one dotenv file into ``os.environ`` like ``dotenv.load_dotenv`` â€” same parser, same
    ``${VAR}`` / ``${VAR:-default}`` / precedence rules â€” except that ``${VAR}`` resolves against the value
    VAR had before this process's earlier passes published it (see ``_DOTENV_PUBLISHED``).

    ``load_pass`` groups the layered files of one ``load_hermes_dotenv`` call: within a pass a later layer
    (project, managed) still sees the earlier layer's output, as it always did; only OTHER passes' output
    is peeled. A bare call (``hermes send``'s direct reload) is its own pass.ú	utf-8-sigNzlatin-1r   )ÚDotEnv)Úparse_variablesF)Údotenv_pathÚstreamÚinterpolaterl   c              3  ó@   •K  — | ]  }|j                  ‰«      –— Œ y ­wrI   )r9   )rL   ÚatomÚlookups     €r$   rN   z-_load_dotenv_with_fallback.<locals>.<genexpr>/  s   øè ø€ ÒX¸ §¡¨V× 4ÑXùr…   r‰   )Ú
read_bytesr’   ÚUnicodeDecodeErrorÚ
startswithÚcodecsÚBOM_UTF8r{   Údotenv.mainrž   Údotenv.variablesrŸ   r�   ÚioÚStringIOÚparseÚ_DOTENV_LOCKÚnextÚ_DOTENV_PASSESr7   r)   r*   r   rS   r/   r|   r   r™   )r#   Úoverrider›   ÚrawÚtextrž   rŸ   ÚassignmentsÚ
lookup_envr^   ÚbaselineÚ	publishedÚpublished_passÚresolvedr_   ÚcurrentÚrecordÚoursr¥   s                     @r$   Ú_load_dotenv_with_fallbackr¿   	  s?  ø€ ð �/‰/Ó
€Cð%ð �z‰z˜+Ó&ˆõ #Ý0ä‘v¨$´r·{±{À4Ó7HÐV[Ô\×bÑbÓdÓe€Kä	ñ CØÐÜœ^Ó,ˆIÜ,0´·±Ó,<ˆ
Ü;L×;RÑ;RÓ;Tò 	0Ñ7ˆDÑ7�8˜Y¨Ø Ó*¨z¯~©~¸dÓ/CÀyÓ/PØÐ#Ø" 4Ñ(à'/�J˜tÒ$ð	0ð +-ˆØ&ò 	#‰KˆD�%ØÐ Ù7?Ð3˜JÐ3¨(Ñ3ÐE_ÈÐE_ÐT^ÐE_�ØŸ™ÓXÁÐQVÓAWÔXÓX�Ø"ˆH�TŠNð		#ð
 $Ÿ>™>Ó+ò 	C‰KˆD�%Øˆ}¡X°$¼"¿*¹*Ñ2DØÜ—j‘j—n‘n TÓ*ˆGÜ&×*Ñ*¨4Ó0ˆFØ Ð%Ò>¨'°V¸A±YÑ*>ˆDØÔ-Ñ-±'Á$Øá$(�v˜a’y¨gˆHØ$ŒB�J‰J�tÑØ'/°¸	Ð&BÔ˜dÒ#ñ	C÷!Cô8 !Õ"øôO ò %Ø�>‰>œ&Ÿ/™/Ô*Ø”cœ&Ÿ/™/Ó*Ð,Ð-ˆCØ�z‰z˜)Ó$‹ð%ú÷Cô8 !Õ"ús,   “G Á+AH3Â:H3ÃC4H3ÇAH0È/H0È3Ic                óì  — | j                  «       sy	 ddlm} 	 | j	                  «       }d}|j                  t        j                  «      s|j                  t        j                  «      rMt        | j                  «       «      }|t        vr+t        j                  |«       t        j                  d| «       y|j                  t        j                   «      s|j                  t        j"                  «      rH	 t%        j&                  t%        j(                  |«      dd¬«      5 }|j+                  «       }ddd«       d}n?	 t/        | d	d
¬«      5 }|j+                  «       }ddd«       r|d   j                  d«      ry	 D �cg c]  }|j1                  dd«      ‘Œ }} ||«      }	|	|k7  s|r¡ddl}
|
j5                  t        | j6                  «      dd¬«      \  }}	 t9        j:                  |dd¬«      5 }|j=                  |	«       |j?                  «        t9        j@                  |jC                  «       «       ddd«       tE        || «       yy# t        $ r Y yw xY w# t
        $ r Y yw xY w# 1 sw Y   �Œ;xY w# t,        $ r Y yw xY w# 1 sw Y   �Œ,xY w# t
        $ r Y yw xY wc c}w # 1 sw Y   ŒrxY w# tF        $ r' 	 t9        jH                  |«       ‚ # tJ        $ r Y ‚ w xY ww xY w# t
        $ r Y yw xY w)a	  Pre-sanitize a .env file before python-dotenv reads it. Sniffs a leading BOM *before* any text
    decode: UTF-16 (Notepad "Unicode") is rewritten as clean UTF-8; UTF-32 is refused (left untouched) so
    we never fall through to the errors=replace corruption path.Nr   )Ú_sanitize_env_linesFz^Skipping .env sanitize for %s: UTF-32 BOM detected; leaving file untouched to avoid corruptionzutf-16)ÚencodingÚnewlineTr�   Úreplace)rÂ   rˆ   u   ï¿½ú rl   z.tmpz.env_)Údirr„   ÚprefixÚwzutf-8)rÂ   )&r(   Úhermes_cli.configrÁ   ÚImportErrorr¦   rQ   r¨   r©   ÚBOM_UTF32_LEÚBOM_UTF32_BEr8   r9   r   rX   ÚloggerÚwarningÚBOM_UTF16_LEÚBOM_UTF16_BEr­   ÚTextIOWrapperÚBytesIOÚ	readlinesr§   ÚopenrÄ   ÚtempfileÚmkstempÚparentr)   ÚfdopenÚ
writelinesÚflushÚfsyncÚfilenor   ÚBaseExceptionÚunlinkÚOSError)r#   rÁ   r´   Úforce_utf8_rewriteÚpath_keyÚfÚoriginalÚliner—   Ú	sanitizedrÕ   ÚfdÚtmps                r$   Ú_sanitize_env_file_if_neededrè   @  s±  € ð �;‰;Œ=ØðÝ9ðØ�o‰oÓˆð
 ÐØ
‡~�~”f×)Ñ)Ô*¨c¯n©n¼V×=PÑ=PÔ.Qô �t—|‘|“~Ó&ˆØÔ.Ñ.Ü×#Ñ# HÔ-Ü�N‰Nð HØIMôOàØ
‡~�~”f×)Ñ)Ô*¨c¯n©n¼V×=PÑ=PÔ.Qð	Ü×!Ñ!¤"§*¡*¨S£/¸HÈdÔSð )ÐWXØŸ;™;›=�÷)ð "Ñð	Ü�d [¸ÔCð )ÀqØŸ;™;›=�÷)ñ ˜ ™×.Ñ.¨xÔ8Øðà9AÖB°�D—L‘L ¨Õ,ÐBˆÐBÙ'¨Ó1ˆ	Ø˜Ò Ñ$6ÛØ×&Ñ&¬3¨t¯{©{Ó+;ÀFÐSZÐ&Ó[‰GˆB�ðÜ—Y‘Y˜r 3°Ô9ð )¸QØ—L‘L Ô+Ø—G‘G”IÜ—H‘H˜QŸX™X›ZÔ(÷)ô ˜s DÕ)ð %7øôY ò Ùðûô
 ò Ùðú÷$)ñ )ûä!ò 	Ùð	ú÷)ñ )ûäò 	Ùð	üò C÷)ð )ûô
 !ò ðÜ—I‘I˜c”Nð øô ò ØØðúðûô ò Ùðúsé   “I šI Ã6+I8 Ä!I+Ä2I8 Ä>J ÅJÅJ Å=K' ÆJ#Æ?K' ÇJ4 Ç2AJ(È7J4 É	IÉIÉ	I(É'I(É+I5É0I8 É8	JÊJÊJÊJ Ê	J ÊJ Ê#K' Ê(J1Ê-J4 Ê4	K$Ê>KËK$Ë	K ËK$ËK Ë K$Ë$K' Ë'	K3Ë2K3T)r;   Úproject_envÚload_external_secretsc                óØ  — ddl m} | rt        | «      n |«       }ddlm} ddl m}  |«       rx |«       �qt        |j                  «       «      }|t        vr+t        j                  |«       t        j                  d|«       |r!ddlm} |j                  «       st        |«       g S g }	|dz  }
|rt        |«      nd}t!        t"        «      }|
j%                  «       rt'        |
«       |r|j%                  «       rt'        |«       |
j%                  «       r*t)        |
d	|¬
«       |	j+                  |
«       t-        |
«       |dz  }|j%                  «       r-t.        j0                  j3                  d«      st)        |d|¬
«       |r0|j%                  «       r t)        ||	 |¬
«       |	j+                  |«       t4        ryt4        j3                  t        |j                  «       «      i «      j7                  «       D ];  \  }}t.        j0                  j3                  |«      |k7  sŒ)|t.        j0                  |<   Œ= ddlm} |r|j                  «       st9        |«       t;        |¬«       t=        |«       |	S )zÊLoad Hermes env files: ``~/.hermes/.env`` overrides stale shell exports; project ``.env`` is a dev
    fallback that only fills gaps when the user env exists (and overrides shell vars when it does not).r   ©Úget_process_hermes_home)Úis_multiplex_active)Úget_hermes_home_overrideNzumultiplex: skipping process-global dotenv load for routed profile home %s (credentials resolve via the profile scope))Ú_early_recoveryrE   T©r³   r›   rF   ÚOP_SERVICE_ACCOUNT_TOKENFrš   )Úhermes_constantsrí   r   r!   rî   rï   r8   r9   r   rX   rÍ   ÚdebugÚ
hermes_clirð   Ú$_should_skip_external_secret_sourcesr@   r±   r²   r(   rè   r¿   rz   r-   r)   r*   r/   r   rS   Ú_apply_external_secret_sourcesÚ_apply_managed_envÚ_reapply_terminal_config_bridge)r;   ré   rê   rí   Ú	home_pathrî   rï   r\   rð   ÚloadedÚuser_envÚproject_env_pathr›   ra   r^   r_   s                   r$   Úload_hermes_dotenvrþ   ‡  sü  € õ 9Ù%0”�[Ô!Ñ6MÓ6O€Iõ
 7Ý9áÔÑ!9Ó!;Ð!GÜ�y×(Ñ(Ó*Ó+ˆØÔ.Ñ.Ü×#Ñ# HÔ-Ü�L‰Lð WØXaôcá Ý2à"×GÑGÔIÜ.¨yÔ9Øˆ	à€FØ˜6Ñ!€HÙ,7”t˜KÔ(¸TÐÜ”^Ó$€Ià‡�ÔÜ$ XÔ.ÙÐ,×3Ñ3Ô5Ü$Ð%5Ô6à‡�ÔÜ" 8°dÀiÕPØ�‰�hÔÜ-¨hÔ7ð
 ˜Ñ"€FØ‡}�}„œrŸz™zŸ~™~Ð.HÔIÜ" 6°EÀYÕOáÐ,×3Ñ3Ô5Ü"Ð#3À&¸jÐT]Õ^Ø�‰Ð&Ô'õ &Ü9×=Ñ=¼cÀ)×BSÑBSÓBUÓ>VÐXZÓ[×aÑaÓcò 	)‰KˆD�%Ü�z‰z�~‰~˜dÓ# uÓ,Ø#(”—
‘
˜4Ò ð	)õ +ñ  _×%YÑ%YÔ%[Ü& yÔ1Ü Õ+ô $ IÔ.à€Mr&   c                ó¨   — 	 t        | «      j                  «       t        «       j                  «       k7  ryddlm}  |d¬«       y# t
        $ r Y yw xY w)zöRe-assert config.yaml's explicit ``terminal.*`` keys over reloaded .env via the single shared bridge
    ``apply_terminal_config_to_env`` (also used by terminal_tool and the TUI/dashboard launchers) so the
    semantics can't drift between sites.Nr   )Úapply_terminal_config_to_env)Úenv)r   r9   Ú_process_hermes_homerÉ   r   rQ   )rú   r   s     r$   rù   rù   é  sI   € ðÜ�	‹?×"Ñ"Ó$Ô(<Ó(>×(FÑ(FÓ(HÒHØÝBá$¨Ö.øÜò Ùðús   ‚2A µA Á	AÁAc                ó´   — 	 ddl m} |j                  «       }|€y|dz  }|j	                  «       syt        |«       t        |d| ¬«       y# t        $ r Y yw xY w)zÌApply the managed-scope .env last, with override, so it beats user/shell. Does NOT stop the agent
    from later mutating os.environ (v1 relies on filesystem permissions). Fail-open: never blocks startup.r   )Úmanaged_scopeNrE   Trñ   )rõ   r  Úget_managed_dirrQ   r(   rè   r¿   )r›   r  Úmanaged_dirÚmanaged_envs       r$   rø   rø   ÷  sd   € ðÝ,à#×3Ñ3Ó5ˆð ÐØØ Ñ&€KØ×ÑÔØÜ  Ô-Ü˜{°TÀYÖOøô ò Ùðús   ‚A Á	AÁAc                óì  — t        t        | «      j                  «       «      }|t        v ry	 t	        | «      }|syt        d„ |j                  «       D «       «      }|sy	 ddlm	} 	  ||| «      }|j                  syt        j                  |«       |j                  r?t        «        |j                  j!                  «       D ]  \  }}|j"                  t$        |<   Œ i }t'        |j                  «      }	|j                  D ]  }
|	j)                  |
j*                  «       Œ |	D ]+  }|t,        j.                  v sŒt,        j.                  |   ||<   Œ- |r	|t0        |<   |j                  j!                  «       D ��ci c]  \  }}|j2                  sŒ||v sŒ|||   “Œ c}}t4        |<   |j                  D �]_  }
|
j6                  r[t9        d|
j:                  › dt=        |
j6                  «      › dt=        |
j6                  «      dk7  rd	nd
› �t>        j@                  ¬«       |
jB                  jD                  r™t9        d|
j:                  › d|
jB                  jD                  › �t>        j@                  ¬«       tG        |
jH                  |
jB                  jJ                  ||¬«      }|r+t9        d|
j:                  › d|› �t>        j@                  ¬«       |
jB                  jL                  D ]-  }t9        d|
j:                  › d|› �t>        j@                  ¬«       Œ/ �Œb |jN                  D ]   }t9        d|› �t>        j@                  ¬«       Œ" y# t
        $ r Y yw xY w# t        $ r Y yw xY w# t
        $ r Y yw xY wc c}}w )uo  Pull secrets from every enabled external source into env â€” AFTER dotenv (sources need .env bootstrap
    tokens), BEFORE Hermes reads credentials; failures never block startup. Precedence/conflicts/provenance
    live in ``registry.apply_all``; this wrapper owns the once-per-home guard, the post-apply ASCII sweep,
    the ``_SECRET_SOURCES`` map and status lines.Nc              3  óf   K  — | ])  }t        |t        «      xr |j                  d «      du –— Œ+ y­w)ÚenabledTN)Ú
isinstancer7   r/   )rL   Úvs     r$   rN   z1_apply_external_secret_sources.<locals>.<genexpr>   s-   è ø€ Ò]È1”j ¤DÓ)ÒF¨a¯e©e°IÓ.>À$Ð.FÓFÑ]ùs   ‚/1r   rC   z  z
: applied z secretr‰   rŠ   rl   r‹   z: ©Úscopeu   : â†’ z  Secret sources: )(r8   r   r9   r   rP   rQ   rŽ   re   rR   rD   rÊ   rV   rX   Úapplied_anyr™   rY   rS   rZ   r   r"   rT   Úskipped_existingr)   r*   r   Úauthoritativer   rf   r“   rq   r{   r”   r•   rJ   ÚerrorÚ_remediation_hintr^   Ú
error_kindÚwarningsÚ	conflicts)rú   r\   r]   Úany_enabledrD   rd   r^   rf   re   ÚsuppliedrM   ÚnÚaÚhintÚwarnÚconflicts                   r$   r÷   r÷   	  s  € ô
 ”4˜	“?×*Ñ*Ó,Ó-€HØ”>Ñ!Øð
Ü" 9Ó-ˆñ Øô
 Ñ]ÐPS×PZÑPZÓP\Ô]Ó]€KÙØðÝ;ðÙ˜3 	Ó*ˆð �>Š>Øô
 ×Ñ�xÔ à×ÒÜ$Ô&Ø#×.Ñ.×4Ñ4Ó6ò 	3‰MˆD�'Ø$+§N¡NŒO˜DÒ!ð	3ð  €FÜ�6×$Ñ$Ó%€HØ�~‰~ò .ˆØ�‰˜×,Ñ,Õ-ð.àò ,ˆØ”2—:‘:ÒÜŸ:™: dÑ+ˆF�4ŠLð,ñ Ø28Ô% hÑ/à!'×!2Ñ!2×!8Ñ!8Ó!:÷0_Ù˜˜A¸a¿o»oÐRSÐW]ÒR]ˆˆ6�!‰9‰ó0_Ô" 8Ñ,ð �~‰~ó 
=ˆØ�;Š;Ü�B�s—y‘y�k ¬C°·±Ó,<Ð+=ð >Ü"% c§k¡kÓ"2°aÒ"7™3¸RÐ@ðBÜHKÏ
É
õTà�:‰:×ÒÜ�B�s—y‘y�k  C§J¡J×$4Ñ$4Ð#5Ð6¼S¿Z¹ZÕHÜ$ S§X¡X¨s¯z©z×/DÑ/DÀcÐQYÔZˆDÙÜ˜˜3Ÿ9™9˜+ V¨D¨6Ð2¼¿¹ÕDØ—J‘J×'Ñ'ò 	=ˆDÜ�B�s—y‘y�k  D 6Ð*´·±Ö<ò	=ð
=ð ×$Ñ$ò @ˆÜÐ" 8 *Ð-´C·J±JÖ?ñ@øôE ò áðûô ò Ùðûô
 ò Ùðüó@0_sG   ­M ÁM Á&	M! Å7M0ÆM0ÆM0Í	MÍMÍ	MÍMÍ!	M-Í,M-r  c               óì   — 	 ddl m}  || |¬«      }|€y|j                  | «      }t        |t        «      r|ni }t        |j                  ||«      xs d«      j                  «       S # t        $ r Y yw xY w)zbThe failed source's one-line fix-it hint; a plugin remediation() could raise and startup must not.r   rn   r  rl   )	rR   ro   r/   r  r7   r8   ÚremediationÚstriprQ   )Úsource_namer  Úsecrets_cfgr  ro   rZ   Úsrc_cfgs          r$   r  r  ]  st   € ð
Ý<á˜K¨uÔ5ˆØˆ>ØØ—/‘/ +Ó.ˆÜ'¨´Ô6‘'¸BˆÜ�6×%Ñ% j°'Ó:Ò@¸bÓA×GÑGÓIÐIøÜò Ùðús   ‚A' •AA' Á'	A3Á2A3c                ó"  — | dz  }|j                  «       si S | t        «       k(  r'	 ddlm}  |«       xs i }|j	                  d«      xs i S 	 t        |«      xs i }|j	                  d«      xs i S # t
        $ r Y Œ0w xY w# t
        $ r i cY S w xY w)zeRead just the ``secrets:`` section of config.yaml, isolated so a malformed config can't break dotenv.zconfig.yamlr   )Úread_raw_configÚsecrets)r(   r  rÉ   r%  r/   rQ   r   )rú   Úconfig_pathr%  Údatas       r$   rP   rP   l  s§   € à˜mÑ+€KØ×ÑÔØˆ	ð Ô(Ó*Ò*ð	Ý9á"Ó$Ò*¨ˆDØ—8‘8˜IÓ&Ò,¨"Ð,ðÜ& {Ó3Ò9°rˆð �8‰8�IÓÒ$ "Ð$øô ò 	Ùð	ûô
 ò ØŠ	ðús#   ¦%A1 ÁB  Á1	A=Á<A=Â BÂBc                 ój   — 	 ddl m}   | «       S # t        $ r t        j                  «       dz  cY S w xY w)uÒ  The HERMES_HOME the running process was launched under.

    Must be the *true* process home, ignoring any context-local
    ``set_hermes_home_override`` a per-request task has installed. Both
    callers depend on that:

    * ``_reapply_terminal_config_bridge`` guards "only re-bridge config into
      the shared ``os.environ`` when THIS load is for the process's own
      profile". If this followed the task override, a per-turn handler scoped
      to a *secondary* profile (the multiplex dashboard serving every profile
      from one process) would satisfy the guard and bridge that profile's
      ``terminal.backend`` into the shared env â€” e.g. a ``local`` sibling
      profile clobbering the launch profile's ``TERMINAL_ENV=ssh`` while
      leaving its ``TERMINAL_SSH_*`` untouched, so the session silently runs
      commands locally (cross-profile terminal-backend leak).
    * ``_load_secrets_config`` uses it to decide whether the shared
      (mtime,size)-keyed config cache is safe to reuse; under an override it
      must fall through to an isolated parse of the scoped profile.

    ``hermes_constants.get_process_hermes_home()`` is the override-immune
    resolver built for exactly this; delegate to it.
    r   rì   z.hermes)ró   rí   rQ   r   r[   rì   s    r$   r  r  ƒ  s3   € ð.'Ý<á&Ó(Ð(øÜò 'Ü�y‰y‹{˜YÑ&Ò&ð'ús   ‚ � 2±2)r#   r   Úreturnr   )r#   r   r*  ÚNone)r0   r8   r*  ú
str | None)r*  ztuple[str, ...])r;   zstr | os.PathLiker*  r   )r[   r   r*  r   rI   )r;   ústr | os.PathLike | Noner*  r+  )r0   r8   r*  r8   )é   )r_   r8   r}   Úintr*  r8   )r*  r+  )r#   r   r³   Úboolr›   ú
int | Noner*  r+  )r;   r-  ré   r-  rê   r0  r*  z
list[Path])rú   r   r*  r+  )r›   r1  r*  r+  )r!  r8   r"  r7   r  r,  r*  r8   )rú   r   r*  r7   )r*  r   );Ú__doc__Ú
__future__r   r©   r­   Ú	itertoolsÚloggingr)   r”   Ú	threadingÚpathlibr   ÚdotenvÚutilsr   r   r   Ú	getLoggerÚ__name__rÍ   r�   r"   r   Ú__annotations__r   r   r   r   r   r   ÚRLockr>   r   Úcountr²   r°   Ú	frozensetr   r   r%   r-   r1   r5   r<   r@   r?   rj   rs   r€   r™   r¿   rè   rþ   rù   rø   r÷   r  rP   r  r4   r&   r$   ú<module>r@     sÄ  ðÚ Lå "ã Û 	Û Û Û 	Û 
Û Ý ó
 ß IÑ Ià	ˆ×	Ñ	˜8Ó	$€ð AÐ ñ ›€ˆhÓ Ù #£Ð �XÓ %Ù #£Ð �XÓ %ð #%€�Ó $à;=Ð Ð8Ó =à<>Ð Ð 9Ó >ñ ›5€�Ó  Ø+˜IŸO™OÓ-Ð ð =?Ð Ð9Ó >Ø �—‘Ó"€Øˆy�‰Ó €ñ *3Ð4TÐ3UÓ)VÐ ˜Ó Vñ -6ò 7ó -Ð ˜>ó ó$ó ó(ó"óYó
Bó5ôp7ó&ô&ó
ðB W[õ 4#ónDðR -1Ø,0Ø"&ñ	_à)ð_ð *ð_ð  ð	_ð
 ó_óDð 37õ Pó$Q@ðh _cõ ó%ô.'r&   