+
    jHàj‡,  ã                  ó°  a € 0 t $ R t^ RIHt ^ RIt^ RIt^ RIt^ RIHt ^ RI	H
t
HtHtHtHtHtHt ]P"                  ! ]4      tR%t^<t^t^<tRt]P2                  ! 4       t]P6                  ! 4       tRsR]R&   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/R R llt&R]RRRR/R R llt'R R lt(RRR ]R]RR/R! R" llt)R&R# R$ llt*R# )'z9Background keepalive for long-lived Nous Portal sessions.)ÚannotationsN)ÚOptional)Ú!ACCESS_TOKEN_REFRESH_SKEW_SECONDSÚNOUS_INVOKE_JWT_MIN_TTL_SECONDSÚ	AuthErrorÚ_agent_key_is_usableÚ_is_expiringÚget_provider_auth_stateÚ resolve_nous_runtime_credentialsÚkeepalive_interval_secondsúOptional[threading.Thread]Ú_keepalive_threadc               ó    € V ^8„  d   QhRRRR/# )é   ÚvalueúOptional[float]ÚreturnÚfloat© )Úformats   "ÚC/home/ubuntu/.hermes/hermes-agent/hermes_cli/nous_auth_keepalive.pyÚ__annotate__r   )   s   € ÷ ñ ˜Oð °ñ ó    c                ó’   € V e   \        V 4      #  \        \        P                  ! RR4      4      #   \        \        3 d     R# i ; i)NÚHERMES_NOUS_TIMEOUT_SECONDSÚ15g      .@)r   ÚosÚgetenvÚ	TypeErrorÚ
ValueError)r   s   &r   Ú_timeout_secondsr    )   sE   € ØÒÜ�U‹|ÐðÜ”R—Y’YÐ<¸dÓCÓDÐDøÜ”zÐ"ô Úðús   ‘1 ±AÁAc               ó   € V ^8„  d   QhRR/# )r   r   Údictr   )r   s   "r   r   r   2   s   € ÷ ñ �dñ r   c                 ó–   €  ^ RI Hp  V ! 4       P                  R4      p\        V\        4      '       d   V# / #   \
         d    / u # i ; i)z[The ``nous:`` section of config.yaml, or {} on any failure (config loader imported lazily).)Úload_configÚnous)Úhermes_cli.configr$   ÚgetÚ
isinstancer"   Ú	Exception)r$   Úsections     r   Ú_nous_configr+   2   sG   € ðÝ1á“-×#Ñ# FÓ+ˆÜ$ W¬d×3Ò3ˆwÐ;¸Ð;øÜô ØŠ	ðús   ‚38 ¶8 ¸AÁAc               ó    € V ^8„  d   QhRRRR/# )r   r   úOptional[int]r   Úintr   )r   s   "r   r   r   =   s   € ÷ 4ñ 4˜]ð 4¨sñ 4r   c                ó¦  € V e    \        V 4      # \	        4       P                  \        4      pVe-   \        V\        4      '       d   VP                  4       '       g   \        #  \        \        V4      4      #   \        \        3 d
    \        u # i ; i  \        \        3 d*    \        P                  R\        T\        4       \        u # i ; i)z¹Tick interval: explicit argument, then ``nous.keepalive_interval_seconds`` in config.yaml,
then the module default. Non-positive disables the keepalive thread (the documented way off).
z&Ignoring invalid nous.%s=%r; using %ds)r.   r   r   Ú$NOUS_AUTH_KEEPALIVE_INTERVAL_SECONDSr+   r'   Ú'NOUS_AUTH_KEEPALIVE_INTERVAL_CONFIG_KEYr(   ÚstrÚstripr   ÚloggerÚwarning)r   Úraws   & r   Ú_interval_secondsr7   =   s²   € ð Òð	8Ü�u“:Ðô ‹.×
Ñ
ÔDÓ
E€CØ
‚{”z #¤s×+Ò+°C·I±I·K²KÜ3Ð3ð4Ü”5˜“:‹Ðøô œ:Ð&ô 	8Ü7Ò7ð	8ûô ”zÐ"ô 4Ü�‰Ø4Ü3°SÔ:^ô	
ô 4Ò3ð4ús#   †
A9 Á%B Á9BÂBÂ7CÃCc               ó   € V ^8„  d   QhRR/# )r   r   r-   r   )r   s   "r   r   r   S   s   € ÷ (ñ ( Mñ (r   c                 ó  € \        R4      ;'       g    / p . pR FA  p \        \        V P                  V4      4      4      pT^ 8”  g   K0  TP                  T4       KC  	  \        VRR7      #   \        \
        3 d     Kf  i ; i)z¨Server-issued lifetime (seconds) of the current Nous credentials; the shorter of the access
token and the invoke agent key governs. None when nothing usable is stored.
r%   N)Údefault)Ú
expires_inÚagent_key_expires_in)r	   r.   r   r'   r   r   ÚappendÚmin)ÚstateÚ	lifetimesÚkeyr   s       r   Ú_observed_lifetime_secondsrB   S   s€   € ô $ FÓ+×1Ð1¨r€EØ€IÛ5ˆð	Üœ˜eŸi™i¨›nÓ-Ó.ˆEð �1Ž9Ø×Ñ˜UÖ#ñ 6ô ˆy $Ô'Ð'øô	 œ:Ð&ô 	Úð	ús   ž#A,Á,BÂ Bc               ó$   € V ^8„  d   QhRRRRRR/# )r   Úconfigured_intervalr.   Úlifetimer-   r   r   )r   s   "r   r   r   c   s&   € ÷ \ñ \ sð \°mð \Èñ \r   c                óp   € V'       d   V^ 8:  d   V # V\         ,          p\        \        \        W4      4      # )zBTick fast enough to refresh several times per credential lifetime.)Ú&NOUS_AUTH_KEEPALIVE_TICKS_PER_LIFETIMEÚmaxÚ(NOUS_AUTH_KEEPALIVE_MIN_INTERVAL_SECONDSr>   )rD   rE   Úderiveds   && r   Ú_tick_secondsrK   c   s0   € ç�x 1”}Ø"Ð"ØÔ@Õ@€GÜÔ7¼Ð=PÓ9ZÓ[Ð[r   c               ó$   € V ^8„  d   QhRRRRRR/# )r   Útick_secondsr.   Úfloor_secondsr   r   )r   s   "r   r   r   k   s&   € ÷ Pñ P¨3ð P¸sð PÀsñ Pr   c                ó.   € \        W\        ,           4      # )z®Life a credential needs to be left alone this tick: it must survive until the next tick
(nothing looks at it again before then), hence tick + skew rather than the bare skew.
)rH   r   )rM   rN   s   &&r   Ú_refresh_horizon_secondsrP   k   s   € ô ˆ}Ô-NÕNÓOÐOr   c               ó    € V ^8„  d   QhRRRR/# )r   ÚentryÚobjectr   r"   r   )r   s   "r   r   r   r   s   € ÷ `ñ `˜ð ` 4ñ `r   c           	     óD   € R Uu/ uF  q\        WR4      bK  	  up# u upi )Ú	agent_keyN)rU   Úagent_key_expires_atÚscope)Úgetattr)rR   Úks   & r   Ú_entry_staterZ   r   s&   € Ù0^Ó_Ñ0^¨1Œw�u Ó&Ò&Ñ0^Ñ_Ð_ùÒ_s   …Úmin_access_ttl_secondsc               ó$   € V ^8„  d   QhRRRRRR/# )r   Úmin_key_ttl_secondsr.   r[   r-   r   zOptional[bool]r   )r   s   "r   r   r   v   s#   € ÷ ñ ¸ð ÐVcð Ðo}ñ r   c                ó,  €  ^ RI Hp V! R4      pT'       d   TP                  4       '       g   R#  TP                  4       pTf   R# Tf   \        p\        \        TRR4      T4      p\        \        T4      T 4      pT'       g	   T'       g*   TP                  4       f   R# \        P	                  R4       R	#   \         d"   p\        P	                  RT4        Rp?R# Rp?ii ; i  \         d"   p\        P	                  RT4        Rp?R# Rp?ii ; i)
z‚Refresh the current pool entry when stale. True = usable/refreshed; False = pool exists but
no usable entry; None = no Nous pool.
)Ú	load_poolr%   z4Nous auth keepalive: credential pool unavailable: %sNz9Nous auth keepalive: credential pool selection failed: %sFÚ
expires_atz4Nous auth keepalive: refreshed credential pool entryT)Úagent.credential_poolr_   r)   r4   ÚdebugÚhas_credentialsÚselectr   r   rX   r   rZ   Útry_refresh_current)r]   r[   r_   ÚpoolÚexcrR   Úaccess_expiringÚ
key_usables   $$      r   Ú_refresh_selected_pool_entryrj   v   sç   € ðÝ3á˜Ó ˆ÷ �t×+Ñ+×-Ò-ÙðØ—‘“ˆð ‚}ÙØÒ%Ü!BÐÜ"¤7¨5°,ÀÓ#EÐG]Ó^€OÜ%¤l°5Ó&9Ð;NÓO€JßŸjØ×#Ñ#Ó%Ò-ÙÜ�‰ÐKÔLÙøô) ô Ü�‰ÐKÈSÔQÝûðûô ô Ü�‰ÐPÐRUÔVÝûðús.   ‚B8 ±C' Â8C$ÃCÃC$Ã'DÃ2DÄDr]   Útimeout_secondsc               ó(   € V ^8„  d   QhRRRRRRRR/# )	r   r]   r.   r[   r-   rk   r   r   Úboolr   )r   s   "r   r   r   •   s.   € ÷ &ñ &Øð&à)ð&àCRð&ð 
ñ&r   c           
     óê  € ^ RI Hp V! 4       ;_uu_ 4        \        \        ^<\	        V 4      4      VR7      pVe   VuuRRR4       # \        R4      pV'       g    RRR4       R# ^ RIHp V! V4      '       d    RRR4       R#  ^ RIH	p V! 4       ;_uu_ 4        \        \        V4      R7       RRR4       \        P                  R	4        RRR4       R
#   + '       g   i     L0; i  \         di   p\        T\         4      '       d*   TP"                  '       d   \        P%                  RT4       M\        P                  RT4        Rp?RRR4       R# Rp?ii ; i  + '       g   i     R# ; i)z^Refresh Nous auth once if credentials are configured (pool entry first, then singleton state).)Ú#launch_profile_scope_if_multiplexed)r]   r[   Nr%   F©Úis_guest_state)Úbackground_caller)rk   z3Nous auth keepalive: refreshed singleton auth stateTz)Nous auth keepalive requires re-login: %szNous auth keepalive failed: %s)Ú!tui_gateway.launch_profile_policyro   rj   rH   r.   r	   Úhermes_cli.anon_authrq   Úhermes_cli.anon_challengerr   r
   r    r4   rb   r)   r(   r   Úrelogin_requiredÚinfo)	r]   r[   rk   ro   Úpool_resultr?   rq   rr   rg   s	   $$$      r   Ú refresh_nous_auth_keepalive_oncery   •   s  € õ Vá	,×	.Õ	.Ü2Ü # B¬Ð,?Ó(@Ó AÐZpô
ˆð Ò"Ø÷ 
/Ò	.ô (¨Ó/ˆßØ÷ 
/Ñ	.õ 	8Ù˜%× Ò Ø÷ 
/Ñ	.ð	õ DÙ"×$Õ$Ü0ÔAQÐRaÓAbÕc÷ %ä�L‰LÐNÔOØ÷- 
/Ñ	.÷& %×$ûô ô 	Ü˜#œy×)Ò)¨c×.B×.BÐ.BÜ—‘ÐGÈÕMä—‘Ð=¸sÔCÛ÷9 
/Ñ	.ûð.	ú÷/ 
/×	.Ð	.ús_   –&E!ÁE!Á%E!Á9E!ÂC+ÂC	Â0C+ÃC(Ã#C+Ã+EÃ6'EÄ-EÅE!ÅEÅE!Å!E2	c               ó0   € V ^8„  d   QhRRRRRRRRRRR	R
/# )r   Ú
stop_eventzthreading.EventÚinterval_secondsr.   Úinitial_delay_secondsr]   rk   r   r   ÚNoner   )r   s   "r   r   r   ¾   s>   € ÷ ñ ØðØ69ðØRUðàðà/>ðð 
ñr   c               óð   € V^ 8”  d   V P                  V4      '       d   R# V P                  4       '       g@   \        V\        4       4      p\	        WS4      p\        WfVR7       V P                  V4       KU  R# )é    N)r]   r[   rk   )ÚwaitÚis_setrK   rB   rP   ry   )r{   r|   r}   r]   rk   ÚtickÚhorizons   &$$$$  r   Ú_keepalive_loopr…   ¾   sk   € ð ˜qÔ  Z§_¡_Ð5J×%KÒ%KÙØ×Ñ×!Ò!ô Ð-Ô/IÓ/KÓLˆÜ*¨4ÓEˆÜ(Ø 'ÐYhõ	
ð 	�‰˜Öñ "r   r|   r}   c          
     ó,   € V ^8„  d   QhRRRRRRRRRR	/# )
r   r|   r-   r}   r.   r]   rk   r   r   r   r   )r   s   "r   r   r   Ï   s<   € ÷ &!ñ &!Ø&ð&!àð&!ð ð&!ð Rað&!ð  ñ	&!r   c                óÌ  € ^ RI Hp V! 4        \        V 4      p V ^ 8:  d   R# ^ RIHp  V! \        R4      4      '       d   \        P                  R4       R#  \        ;_uu_ 4        \        e+   \        P                  4       '       d   \        uuRRR4       # \        P                  4        \        P                  ! \         \        3RRR\#        V 4      R	\%        ^ \#        V4      4      R
\%        ^<\#        V4      4      RV/R7      s
\        P'                  4        \        P                  R4       \        uuRRR4       #   \         d     Löi ; i  + '       g   i     R# ; i)zSStart the process-wide Nous auth keepalive thread (idempotent; None when disabled).)Ústart_workerNrp   r%   z;Nous auth keepalive skipped: free tier has no refresh tokenTznous-auth-keepaliver|   r}   r]   rk   )ÚtargetÚargsÚdaemonÚnameÚkwargszNous auth keepalive started)Úhermes_cli.guest_handoffrˆ   r7   rt   rq   r	   r4   rb   r)   Ú_keepalive_lockr   Úis_aliveÚ_keepalive_stopÚclearÚ	threadingÚThreadr…   r.   rH   Ústart)r|   r}   r]   rk   rˆ   rq   s   $$$$  r   Ústart_nous_auth_keepaliver–   Ï   s!  € õ 6Ù„NÜ(Ð)9Ó:ÐØ˜1ÔÙõ 4ðÙÔ1°&Ó9×:Ò:Ü�L‰LÐVÔWÙð ;÷ 
ŽÜÒ(Ô->×-GÑ-G×-IÒ-IÜ$÷ 
Šô 	×ÑÔÜ%×,Ò,Ü"¬/Ð);ÀDÐOdà"¤CÐ(8Ó$9Ø'¬¨Q´Ð4IÓ0JÓ)KØ%¤s¨2¬sÐ3FÓ/GÓ'HØ! ?ð	ô
Ðô 	×ÑÔ!Ü�‰Ð2Ô3Ü ÷ 
Šøô ô Ùðú÷ 
�ˆús*   ©,E Á&"EÂ	EÂBEÅEÅEÅE#	c               ó    € V ^8„  d   QhRRRR/# )r   Útimeoutr   r   r~   r   )r   s   "r   r   r   ø   s   € ÷ %ñ % eð %°dñ %r   c                óp  € ^ RI Hp V! V 4       \        ;_uu_ 4        \        p\        P                  4        RRR4       Xe)   VP                  4       '       d   VP                  V R7       \        ;_uu_ 4        \        VJ d   RsRRR4       R#   + '       g   i     La; i  + '       g   i     R# ; i)z@Stop the keepalive thread. Intended for graceful shutdown/tests.)Ústop_workerN)r˜   )rŽ   rš   r�   r   r‘   Úsetr�   Újoin)r˜   rš   Úthreads   &  r   Ústop_nous_auth_keepaliverž   ø   sv   € å4Ù�Ôç	ŽÜ"ˆÜ×ÑÔ÷ 
ð Ò˜fŸo™o×/Ò/Ø�‰˜GˆÔ$ß	ŽÜ Ó&Ø $Ð÷ 
‰÷ 
�ú÷
 
�ˆús   �BÁ:B$ÂB!	Â$B5	i„  )g      @)+Ú__conditional_annotations__Ú__doc__Ú
__future__r   Úloggingr   r“   Útypingr   Úhermes_cli.authr   r   r   r   r   r	   r
   Ú	getLoggerÚ__name__r4   r0   rI   rG   Ú)NOUS_AUTH_KEEPALIVE_INITIAL_DELAY_SECONDSr1   ÚLockr�   ÚEventr‘   r   Ú__annotations__r    r+   r7   rB   rK   rP   rZ   rj   ry   r…   r–   rž   )rŸ   s   @r   Ú<module>r«      s	  øðÜ ?å "ã Û 	Û Ý ÷÷ ñ ð 
×	Ò	˜8Ó	$€ð (/Ð $Ø+-Ð (à)*Ð &Ø,.Ð )Ø*FÐ 'à—.’.Ó"€Ø—/’/Ó#€Ø04Ð Ð-Ó 4õõõ4õ,(õ \õPõ`ðÐfj÷ ð>&Ø"Að&à,0ð&àUY÷&õRð"&!Ø)-ð&!à!Jð&!ð  ?ð&!ð dh÷&!÷R%ñ %r   