+
    jHàj—  ã                   óŒ  a € R t#0 t R t^ RIt^ RIt^ RIt^ RIt^ RIt^ RIHt ^ RIH	t	H
t
Ht ^ RIHt ^ RIHt ]P                   ! ]4      t]P&                  ! 4       t/ t] ^ k ]P,                  ! R4      t]P,                  ! R4      tRR R	 lltR
 R ltR R ltR R ltR R ltR R ltR R ltR R lt R R lt!R R lt"R# )u,  Timezone-aware clock for Hermes.

``now()`` returns a tz-aware datetime in the user's configured IANA timezone. Resolution order:
``HERMES_TIMEZONE`` env var, then ``timezone`` in ``~/.hermes/config.yaml``, else server-local
time. Invalid timezone values log a warning and fall back â€” never crash.
N©Údatetime)ÚDictÚOptionalÚTuple)ÚZoneInfo)Úget_config_pathz[\ud800-\udfff]z[\x00-\x7f\udc80-\udcff]*c                óR   € V ^8„  d   QhR\         R\        \         ,          R\         /# )é   ÚtextÚencodingÚreturn)Ústrr   )Úformats   "Ú0/home/ubuntu/.hermes/hermes-agent/hermes_time.pyÚ__annotate__r   #   s%   € ÷ -ñ -œSð -¬H´S­Mð -ÄSñ -ó    c                óv  € V P                  4       '       g   \        P                  V 4      '       g   V # \        P	                  V 4      '       d@    V P                  RR4      P                  T;'       g    \        P                  ! 4       4      # \        P                  RV 4      #   \        \        3 d     L)i ; i)a¨  Make locale text JSON/UTF-8 safe; a no-op (same object) on valid text.

Windows hands back zone names in the ANSI code page (``heure d'\xe9t\xe9``) but a UTF-8
``LC_CTYPE`` (UTF-8 mode, or a library flipping the process locale mid-run) decodes those
bytes with ``surrogateescape`` into lone surrogates. Recover the bytes and decode them with
the ANSI code page; when that is not possible, replace each surrogate with U+FFFD.ÚasciiÚsurrogateescapeu   ï¿½)ÚisasciiÚ_SURROGATE_REÚsearchÚ_ESCAPED_BYTES_REÚ	fullmatchÚencodeÚdecodeÚlocaleÚgetencodingÚLookupErrorÚUnicodeErrorÚsub)r   r   s   &&r   Ú_repair_surrogatesr"   #   s–   € ð ‡|�|‡~‚~œ]×1Ñ1°$×7Ò7ØˆÜ×"Ñ" 4×(Ò(ð	Ø—;‘;˜wÐ(9Ó:×AÑAÀ(×BbÐBbÌf×N`ÒN`ÓNbÓcÐcô ×Ñ˜X tÓ,Ð,øô œ\Ð*ô 	Ùð	ús   Á#B$ Á4B$ Â$B8Â7B8c                ó<   € V ^8„  d   QhR\         R\        R\        /# )r
   ÚvalueÚfmtr   )r   r   )r   s   "r   r   r   4   s&   € ÷ Uñ Uœð U¬ð U´ñ Ur   c           
     ó*  a€  \        V P                  V4      4      #   \         dk    \        T P                  4       ;'       g    R4      P	                  RR4      o\        T P                  \
        P                  ! RT3R lT4      4      4      u # i ; i)aÌ  ``value.strftime(fmt)`` that never raises or returns lone surrogates over locale text.

``datetime.strftime`` splices ``tzname()`` into the format as UTF-8, so a zone name carrying
surrogates (see ``_repair_surrogates``) raises ``UnicodeEncodeError`` before any string exists
(#102910). On that failure ``%Z`` is rendered from the repaired name instead. Output for valid
locale text is byte-identical to ``strftime`` (the system prompt must stay cache-stable).Ú Ú%ú%%z%([%Z])c                 ó8   <€ V P                  ^4      R8X  d   S# R# )é   ÚZr)   )Úgroup)ÚmÚzones   &€r   Ú<lambda>Úsafe_strftime.<locals>.<lambda>@   s   ø€ °·±¸³¸sÔ1B¨Ð)LÈÐ)Lr   )r"   ÚstrftimeÚUnicodeEncodeErrorÚtznameÚreplaceÚrer!   )r$   r%   r/   s   &&@r   Úsafe_strftimer7   4   s   ø€ ðUÜ! %§.¡.°Ó"5Ó6Ð6øÜô UÜ! %§,¡,£.×"6Ð"6°BÓ7×?Ñ?ÀÀTÓJˆÜ! %§.¡.Ü�FŠF�:ÔLÈcÓRó#Tó Uò 	UðUús   ƒ �&BÁABÂBc                ó$   € V ^8„  d   QhR\         /# ©r
   r   ©r   )r   s   "r   r   r   C   s   € ÷ 4ñ 4”sñ 4r   c                 óv   € ^ RI Hp  V ! 4       '       d   R# \        P                  ! RR4      P	                  4       # )zø``HERMES_TIMEZONE`` when it may speak for the active profile. Under the multiplexed
gateway the env var holds only the DEFAULT profile's value (bridged from its config.yaml at
startup), so every routed profile must read its own config.yaml instead.©Úis_multiplex_activer'   ÚHERMES_TIMEZONE)Úagent.secret_scoper=   ÚosÚgetenvÚstripr<   s    r   Ú_env_timezonerC   C   s.   € õ 7á×ÒÙÜ�9Š9Ð&¨Ó+×1Ñ1Ó3Ð3r   c                óF   € V ^8„  d   QhR\         \        \        3,          /# r9   )Útupler   )r   s   "r   r   r   N   s   € ÷ Uñ U¤%¬¬S¨¥/ñ Ur   c                  óX   € \        4       p V '       d   R V 3# R\        \        4       4      3# )ÚenvironmentÚconfig)rC   r   r   )Útz_envs    r   Ú_timezone_cache_identityrJ   N   s(   € Ü‹_€Fß&,ˆM˜6Ð"ÐT°8¼SÄÓARÓ=SÐ2TÐTr   c                ó$   € V ^8„  d   QhR\         /# r9   r:   )r   s   "r   r   r   S   s   € ÷ ñ ¤ñ r   c                 óò  € \        4       p V '       d   V #   ^ RIHp V! \        4       4      pV'       dO   VP                  RR4      p\        V\        4      '       d'   VP                  4       '       d   VP                  4       # R#   \         dU    ^ RIp\        4       pTP                  4       '       d,   TP                  TP                  RR7      4      ;'       g    / M/ p L¶i ; i  \         d     R# i ; i)uV   Read the configured IANA timezone string (or ``""``). Does file I/O â€” callers cache.)Úload_user_config_effectiveNzutf-8)r   Útimezoner'   )rC   Úhermes_cli.config_effectiverM   r   Ú	ExceptionÚhermes_yamlÚexistsÚ	safe_loadÚ	read_textÚgetÚ
isinstancer   rB   )rI   rM   ÚcfgÚyamlÚconfig_pathÚtz_cfgs         r   Ú_resolve_timezone_namer[   S   sÓ   € ä‹_€FßØˆðð
	rÝNÙ,¬_Ó->Ó?ˆC÷
 Ø—W‘W˜Z¨Ó,ˆFÜ˜&¤#×&Ò&¨6¯<©<¯>ª>Ø—|‘|“~Ð%ñ øô ô 	rÛ&Ü)Ó+ˆKØU`×UgÑUg×UiÒUi�4—>‘> +×"7Ñ"7ÀÐ"7Ó"IÓJ×PÐPÈbøÐoqŠCð	rûô ô ØÙðús@   —B ­C' µ=C' Á3C' ÂAC$ÃC$Ã!C' Ã#C$Ã$C' Ã'C6Ã5C6c                ó\   € V ^8„  d   QhR\         \        \        \        ,          3,          /# r9   )rE   r   r   r   )r   s   "r   r   r   m   s%   € ÷ @ñ @œœs¤H¬XÕ$6Ð6Õ7ñ @r   c                 óÚ  € \        4       p \        ;_uu_ 4        \        P                  V 4      pVe   VuuRRR4       #  RRR4       \	        4       pRpV'       d    \        V4      p\        ;_uu_ 4        \        P                  WV34      uuRRR4       #   + '       g   i     L`; i  \         d!   p\        P                  RY$4        Rp?LiRp?ii ; i  + '       g   i     R# ; i)zECached ``(configured name, ZoneInfo | None)`` for the active profile.Nz=Invalid timezone '%s': %s. Falling back to server local time.)
rJ   Ú_cache_lockÚ	_tz_cacherU   r[   r   rP   ÚloggerÚwarningÚ
setdefault)Úcache_identityÚentryÚnameÚtzÚexcs        r   Ú_timezone_entryrh   m   s¬   € ä-Ó/€Nß	ŽÜ—‘˜nÓ-ˆØÒØ÷ 
Šà÷ 
ô "Ó#€DØ	€Bßð	gÜ˜$“ˆB÷ 
ŽÜ×#Ñ# N¸2°JÓ?÷ 
Š÷ 
�ûô ô 	gÜ�N‰NÐZÐ\`×fÑfûð	gúç	�ˆús/   ™BÁB+ Á6CÂB(	Â+CÂ6CÃCÃC*	c                ó:   € V ^8„  d   QhR\         \        ,          /# r9   )r   r   )r   s   "r   r   r   �   s   € ÷  ñ  ”hœxÕ(ñ  r   c                 ó$   € \        4       ^,          # )zHReturn the active profile's configured ZoneInfo, or None (server-local).©rh   © r   r   Úget_timezonerm   �   s   € äÓ˜QÕÐr   c                ó$   € V ^8„  d   QhR\         /# r9   r:   )r   s   "r   r   r   †   s   € ÷  ñ  œ3ñ  r   c                 ó$   € \        4       ^ ,          # )z¬The active profile's configured IANA timezone string, or ``""`` (server-local). Same
resolution and cache as :func:`get_timezone`; for handing ``TZ`` to sandboxed children.rk   rl   r   r   Úget_timezone_namerp   †   s   € ô Ó˜QÕÐr   c                ó   € V ^8„  d   QhRR/# )r
   r   Nrl   )r   s   "r   r   r   Œ   s   € ÷ ñ �Tñ r   c                 ó„   € \         ;_uu_ 4        \        P                  4        RRR4       R#   + '       g   i     R# ; i)zUClear the cached timezone so the next call re-resolves it (after config/env changes).N)r^   r_   Úclearrl   r   r   Úreset_cachert   Œ   s   € ç	ŽÜ�‰Ô÷ 
��Šús   �.®?	c                ó$   € V ^8„  d   QhR\         /# r9   r   )r   s   "r   r   r   ’   s   € ÷ Oñ OŒXñ Or   c                 ó�   € \        4       p V e   \        P                  ! V 4      # \        P                  ! 4       P                  4       # )zHCurrent time as a tz-aware datetime: configured zone, else server-local.)rm   r   ÚnowÚ
astimezone)rf   s    r   rw   rw   ’   s0   € ä	‹€BØ!š~Œ8�<Š<˜ÓÐN´8·<²<³>×3LÑ3LÓ3NÐNr   c                ó¼   € V ^8„  d   Qh/ ^ \         9   dH   \        \        \        \        3,          \        \        \        \
        ,          3,          3,          ;R&   # )r
   r_   )Ú__conditional_annotations__ÚdictrE   r   r   r   )r   s   "r   r   r      s@   € ÷ ñ ÷6 FÒ EŒ4””cœ3�h•¤¤s¬H´XÕ,>Ð'>Õ!?Ð?Õ@Ñ Eò7r   )N)$rz   Ú__doc__r   Úloggingr@   r6   Ú	threadingr   Útypingr   r   r   Úzoneinfor   Úhermes_constantsr   Ú	getLoggerÚ__name__r`   ÚLockr^   r_   Úcompiler   r   r"   r7   rC   rJ   r[   rh   rm   rp   rt   rw   r   )rz   s   @r   Ú<module>r†      s¦   øðöó Û Û 	Û 	Û Ý ß (Ñ (Ý å ,à	×	Ò	˜8Ó	$€ð �nŠnÓ€ØCE€	Ó Eà—
’
Ð-Ó.€à—J’JÐ;Ó<Ð ÷-õ"Uõ4õUõ
õ4@õ( õ
 õ÷Or   