
    #JjJ                        S r SSKJr  SSKrSSKJrJr  SSKJr  SSKJ	r	J
r
  SSKJr  SSKJr  SS	KJrJrJr  SS
KJr  \" S5      rSqSqSqSS jrSSS jjrSSS jjrg)a+  Heartbeat: periodic liveness + light metrics to the Central API.

The heartbeat must be resilient: if the API is unavailable the agent logs the
failure and keeps running, retrying on the next interval. It never crashes the
service and never blocks indefinitely (the API client has its own timeout).
    )annotationsN)datetimetimezone)Any)	ApiClientApiError)Config)system)load_agent_tokensave_statussave_last_error)
get_logger	heartbeatg        Fc                z   [         R                   " 5       n[        U SS5      n[        b  U[        -
  U:  a  [        [        4$  SSKJn  U" X5      nUb  UR                  qUR                  qUq[        c  U R                  S4$ [        [        4$ ! [         a   n[        R                  SU5         S nANFS nAff = f)Nheartbeat_interval<   r   )checkz0Silent ignore of update manifest fetch error: %sF)timegetattr_cached_latest_version_last_fetch_time_cached_update_availableupdater   latestupdate_available	Exceptionlogwarningagent_version)config
api_clientnowintervalcheck_updateinfoexcs          3D:\Programs\laragon\www\wolf\agent\src\heartbeat.pyget_update_statusr(      s     ))+Cv3R8H)s5E/E/P%'???M0F/%)[["'+'<'<$" %##U**!#;;;  MFLLMs   +B 
B:B55B:c           	        [        X5      u  p4 SSKnUR                  U R                  S9  UR	                  5       nU R                  UUUU R                  [        R                  " 5       [        R                  " [        R                  5      R!                  5       US.$ ! [
         a"  n[        R                  SU5        0 n SnANSnAff = f)a  Assemble the heartbeat payload.

The heartbeat contract requires `agent_version`, `update_available`,
`latest_version`, and `status`; the agent is identified by its
X-Agent-Token header, not the body. Light metrics are sent as additional
informational fields.
r   N)r#   zFailed to collect telemetry: %s)r   r   latest_versionstatus	server_idhostname	timestampmetrics)r(   r/   start_updaterr   get_metricsr   r   r   r   r,   r
   r-   r   r"   r   utc	isoformat)r    r!   r+   r*   r   r/   collected_metricsr&   s           r'   build_payloadr5   4   s     (9'L$Nv'@'@A#//1  --,(%%OO%\\(,,/99;$	 		  5s;s   -B 
C
(CC
c                @   U R                   S:X  a  [        R                  S5        g[        XU5      n UR	                  U[        U 5      5        [        R                  SU5        [        U S5        SSKnU R                  S-  nUR                  5       (       Ga   [        US5       nUR                  U5      nSSS5        WR                  S	5      nU(       aE  [        R                  S
U5        UR                  USSSU R                   3S.S.[        U 5      5        UR                  S5      n	U	(       aN  SSKJn
  SSKnU
" U	5      nUR'                  5       (       a'  UR)                  U5        [        R                  SU5        UR+                  5         [        R                  S5        SSKnUR2                  R                  S5      nU(       a=   [        US5       nUR5                  S5        SSS5        [        R                  SU5        UR2                  R                  S5      nU(       aR  SSKn [9        US5      (       a;  UR;                  [=        U5      UR>                  5        [        R                  SU5        gg! , (       d  f       GN= f! [,         a!  n[        R/                  SU5         SnAGNSnAff = f! , (       d  f       N= f! [,         a   n[        R/                  SU5         SnANSnAff = f! [,         a   n[        R/                  SU5         SnAgSnAff = f! [@         ag  n[        U [C        U5      5        URD                  S:X  a"  [G        U S5        [        R                  S5        O[        R                  S U5         SnAgSnAff = f)!u   Send a single heartbeat. Returns True on success, False on failure.

Never raises — transport errors are caught and reported so the caller's
loop continues.
revokedz$Heartbeat skipped: Agent is revoked.Fzheartbeat ok (status=%s)Nr   zupdate_state.jsonrjob_idz>Reporting self-update command success to backend for job_id=%s	succeededTzSuccessfully updated to )successmessage)r+   result
backup_dir)PathzCleaned up backup directory %szDeleted update state filez2Failed to complete update reporting or cleanup: %sWOLFPANEL_UPDATE_FLAG_FILEwOKz"Wrote update success flag file: %sz$Failed to write update flag file: %sWOLFPANEL_UPDATE_PARENT_PIDSIGUSR1zSent SIGUSR1 to parent PID: %szFailed to signal parent: %si  z3Heartbeat rejected by Central; marked agent revokedz.heartbeat failed, will retry next interval: %s)$r+   r   r   r5   r   r   r%   r   jsonvar_diris_fileopenloadgetpost_command_resultr   pathlibr?   shutilexistsrmtreeunlinkr   errorosenvironwritesignalhasattrkillintrD   r   strstatus_coder   )r    r!   r+   payloadrE   
state_filefupdate_stater9   backup_dir_pathr?   rM   bderR   	flag_file
parent_pidrU   r&   s                      r'   	send_oncerd   R   s    }}	!:;F7GAW&6v&>?+V4% 	^^&99
S*c*a#'99Q<L + &))(3HH]_ef22#.dYqrx  sG  sG  rH  XI  ;J  K(0 #/"2"2<"@",!o.Byy{{b)!A2F !!#45 	JJNN#?@	E)S)QGGDM *=yI ZZ^^$AB
<69--GGC
OV^^<HH=zJ _ +*2  S		NPQRRS *)  E		@!DDE  <		7;;<  C)??c!	*KKMNKKH#Ns   A&L, J 'J9C0J )&L, K K.K &L, 3AK? 
JJ 
J>J93L, 9J>>L, 
KK 
K<K72L, 7K<<L, ?
L)	L$L, $L))L, ,
N6ANN)r    r	   r!   r   returnztuple[str, bool])online)r    r	   r!   r   r+   rY   re   zdict[str, Any])r    r	   r!   r   r+   rY   re   bool)__doc__
__future__r   r   r   r   typingr   r!   r   r   r    r	   	discoveryr
   identityr   r   r   loggerr   r   r   r   r   r(   r5   rd        r'   <module>rp      sV    #  '  *   C C     <2<Lro   