
    Ji	W              	       Z   d 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n # e$ r dZ	 ddl	Z	n# e$ r dZ	Y nw xY wY nw xY wddl
mZ ddlmZ ddlmZ ddlmZ ddlmZ  ej        e          Zej                            d e ee          j        j                             ddlmZmZm Z m!Z! d	Z" e            Z#e#d
z  Z$e$dz  Z%de&dee&         fdZ'de&dee&         fdZ(de&deddfdZ)de&defdZ*de&de+e,eeee         f         fdZ-dde,de.fdZ/edk    r e/d           dS dS )a  
Cron job scheduler - executes due jobs.

Provides tick() which checks for due jobs and runs them. The gateway
calls this every 60 seconds from a background thread.

Uses a file-based lock (~/.hermes/cron/.tick.lock) so only one tick
runs at a time if multiple processes overlap.
    N)Path)get_hermes_home)load_config)Optional)now)get_due_jobsmark_job_runsave_job_outputadvance_next_runz[SILENT]cronz
.tick.lockjobreturnc                     |                      d          }|sdS |                     d          }|                     d          }|r|r|S dS )zFExtract origin info from a job, preserving any extra routing metadata.originNplatformchat_id)get)r   r   r   r   s       +/home/ubuntu/hermes-agent/cron/scheduler.py_resolve_originr   6   s[    WWXF tzz*%%Hjj##G G 4    c                 ^   |                      dd          }t          |           }|dk    rdS |dk    r6|sdS |d         t          |d                   |                     d          dS d	|v r|                    d	d
          \  }}d	|v r|                    d	d
          \  }}n|d}}	 ddlm} |}|                    d          r2d|v r.|                    dd
          d                                         } ||	                                |          }	|	r|	}n# t          $ r Y nw xY w|||dS |}|rE|                     d          |k    r,|t          |d                   |                     d          dS t          j        |                                 dd          }|sdS ||ddS )zAResolve the concrete auto-delivery target for a cron job, if any.deliverlocalNr   r   r   	thread_id)r   r   r   :   r   )resolve_channel_name)z (_HOME_CHANNEL )r   r   strsplitgateway.channel_directoryr   endswithrsplitstriplower	Exceptionosgetenvupper)
r   r   r   platform_namerestr   r   r   targetresolveds
             r   _resolve_delivery_targetr0   B   s6   ggi))GS!!F't( 	4z*6),--K00
 
 	
 g~~%mmC33t$;;!%C!3!3GYY!%tYG

	FFFFFFFs## ;tQ//288::++M,?,?,A,A6JJH #" 	 	 	D	 &"
 
 	
 M 
&**Z((M99%6),--K00
 
 	
 i=..00???DDG t "  s   *A1D 
D)(D)contentc                 4   t          |           }|sR|                     dd          dk    r6t                              d| d         |                     dd                     dS |d         }|d         }|                    d          }d	d
lm} d	dlm}m} |j	        |j
        |j        |j        |j        |j        |j        |j        |j        |j        |j        |j        |j        d}	|	                    |                                          }
|
s$t                              d| d         |           dS 	  |            }n:# t.          $ r-}t                              d| d         |           Y d}~dS d}~ww xY w|j                            |
          }|r|j        s$t                              d| d         |           dS d}	 t7                      }|                    di                               dd          }n# t.          $ r Y nw xY w|r&|                     d| d                   }d| d| d}n|} ||
||||          }	 t9          j        |          }n# t<          $ r |                                 d	dl }|j!        "                    d          5 }|#                    t8          j         ||
||||                    }|$                    d          }ddd           n# 1 swxY w Y   Y n;t.          $ r/}t                              d| d         |||           Y d}~dS d}~ww xY w|r?|                    d          r*t                              d| d         |d                    dS t          %                    d| d         ||           dS ) z
    Deliver job output to the configured target (origin chat, specific platform, etc.).

    Uses the standalone platform send functions from send_message_tool so delivery
    works whether or not the gateway is running.
    r   r   zEJob '%s' deliver=%s but no concrete delivery target could be resolvedidNr   r   r   r   )_send_to_platform)load_gateway_configPlatform)telegramdiscordslackwhatsappsignalmatrix
mattermosthomeassistantdingtalkfeishuwecomemailsmsz,Job '%s': unknown platform '%s' for deliveryz8Job '%s': failed to load gateway config for delivery: %sz.Job '%s': platform '%s' not configured/enabledTr   wrap_responsenamezCronjob Response: z
-------------

zN

Note: The agent cannot see this message, and therefore cannot respond to it.)r   r   )max_workers   )timeoutz&Job '%s': delivery to %s:%s failed: %serrorzJob '%s': delivery error: %szJob '%s': delivered to %s:%s)&r0   r   loggerwarningtools.send_message_toolr4   gateway.configr5   r6   TELEGRAMDISCORDSLACKWHATSAPPSIGNALMATRIX
MATTERMOSTHOMEASSISTANTDINGTALKFEISHUWECOMEMAILSMSr'   r(   rI   	platformsenabledr   asynciorunRuntimeErrorcloseconcurrent.futuresfuturesThreadPoolExecutorsubmitresultinfo)r   r1   r.   r,   r   r   r4   r5   r6   platform_mapr   configepconfigrD   user_cfg	task_namedelivery_contentcorore   
concurrentpoolfutures                          r   _deliver_resultrr      s    &c**F 779g&&'11NNWD		7++  
 	:&MYG

;''I999999<<<<<<<< %#%//)!/%/| L  3 3 5 566H Es4yR_```$$&&   OQTUYQZ\]^^^ ""8,,G '/ GTTabbb
 M== VR0044_dKK     	#GGFCI..	\ \ \\ \ \ 	 # Xw9IU^___DT"" 	/ 	/ 	/
 	

!!!!22q2AA 	/T[[.?.?'SZ\l  yB  /C  /C  /C  D  DF]]2]..F	/ 	/ 	/ 	/ 	/ 	/ 	/ 	/ 	/ 	/ 	/ 	/ 	/ 	/ 	/    =s4y-Y`bcddd  W&**W%% W3SYwPPPPP2CI}gVVVVVsm   6
E 
E8"E33E88G> >
H
H	I =L1AK, L1,K0	0L13K0	4L19	L1$L,,L1c           
         |                      dd          }|                      d          }d}||z   }||                      d          }|r|gng }d |D             }|s|S dd	lm} g }g }|D ]}	t          j         ||	                    }
|
                     d
          st|
                     d          pd|	 d}t
                              d|                      d|                      d                    |           |                    |	           t          |
                     d          pd          	                                }|r|                    d           |
                    d|	 dd|g           |rEdd                    |           dd                    |           d}|                    d|           |r|
                    dd| g           d                    |          S )zWBuild the effective prompt for a cron job, optionally loading one or more skills first.promptr    skillsuo  [SYSTEM: If you have a meaningful status report or findings, send them — that is the whole point of this job. Only respond with exactly "[SILENT]" (nothing else) when there is genuinely nothing new to report. [SILENT] suppresses delivery to the user. Never combine [SILENT] with content — either report your findings normally, or say [SILENT] and nothing more.]

Nskillc                     g | ]D}t          |                                          #t          |                                          ES  )r!   r&   ).0rE   s     r   
<listcomp>z%_build_job_prompt.<locals>.<listcomp>   s=    MMM3t99??;L;LM3t99??$$MMMr   r   )
skill_viewsuccessrI   zFailed to load skill ''u/   Cron job '%s': skill not found, skipping — %srE   r3   r1   z#[SYSTEM: The user has invoked the "zf" skill, indicating they want you to follow its instructions. The full skill content is loaded below.]zb[SYSTEM: The following skill(s) were listed for this job but could not be found and were skipped: z, un   . Start your response with a brief notice so the user is aware, e.g.: '⚠️ Skill(s) not found and skipped: z']zPThe user has provided the following instruction alongside the skill invocation: 
)r   tools.skills_toolr{   jsonloadsrJ   rK   appendr!   r&   extendjoininsert)r   rt   ru   silent_hintlegacyskill_namesr{   partsskipped
skill_nameloadedrI   r1   notices                 r   _build_job_promptr      sr   WWXr""FWWXF
	D  6!F~!!#+&MMMMMK ,,,,,,EG! 
 

JJz2233zz)$$ 	JJw''Q+QJ+Q+Q+QENNLcggV\^a^e^efj^k^kNlNlnstttNN:&&&fjj++1r2288:: 	LL ij  i  i  i	
 	
 	
 	
   N!%7!3!3N N 8<yy7I7IN N N 	 	Q xbumsuuvwww99Ur   c                    ddl m} d}	 ddlm}  |            }nG# t          $ r:}t
                              d|                     dd          |           Y d}~nd}~ww xY w| d         }| d         }t          |           }t          |           }d	| d
t                                          d           }	t
                              d||           t
                              d|dd                    |ra|d         t          j        d<   t          |d                   t          j        d<   |                    d          r|d         t          j        d<   	 ddlm}
 	  |
t          t$          dz            dd           n3# t&          $ r&  |
t          t$          dz            dd           Y nw xY wt)          |           }|rn|d         t          j        d<   t          |d                   t          j        d<   |                    d          "t          |d                   t          j        d<   |                     d          pt          j        d           pd!}i }	 ddl}t          t$          d"z            }t          j                            |          rt3          |          5 }|                    |          pi }ddd           n# 1 swxY w Y   |                    di           }|                     d          sCt7          |t                    r|}n+t7          |t8                    r|                    d#|          }n3# t          $ r&}t
                              d$||           Y d}~nd}~ww xY wdd%lm} t          j        d&d!          }|sIt          |                    d'i                               d(d!                                                     } ||          }d}t          j        d)d!          p|                    d*d!          }|rddl!}tE          |          #                                }|$                                s
t$          |z  }|                                r	 t3          |d+d,          5 }|%                    |          }ddd           n# 1 swxY w Y   t7          |tL                    sd}n6# t          $ r)}t
                              d-|||           d}Y d}~nd}~ww xY w|                    d'i                               d.          p|                    d.          pd/}|                    d0i           }|                    d1i           pi }dd2l'm(}m)} 	 d3|                     d4          pt          j        d5          i}|                     d6          r|                     d6          |d7<    |dki |} n-# t          $ r }! ||!          }"tU          |"          |!d}!~!ww xY wdd8l+m,}#  |#||||                     d9          |                     d6          |                     d4          |                     d:          |                     d;          tM          |                     d<          pg           d=          }$ |dki d|$d         d9|$d>                             d9          d6|$d>                             d6          d4|$d>                             d4          d:|$d>                             d:          d?|$d>                             d;          d@|$d>                             d<          dA|dB|dC|dD|                    dE          dF|                    dG          dH|                    dI          dJ|                    dK          dLg dMdNddOdddPdQ|	dR|}%|%-                    |          }&|&                    dSd!          pd!}'|'r|'ndT}(dU| dV| dWt                                          dX           dY|                     dZd[           d\| d]|( d^})t
                              d_|           d|)|'dfd`D ]"}*t          j        .                    |*d           #|r	 |/                    |	da           n:# t          t`          f$ r&}t
                              db||           Y d}~nd}~ww xY w	 |1                                 S # t          t`          f$ r&}t
                              dc||           Y d}~S d}~ww xY wS # t          $ rw}te          |          j3         ddt          |           }+t
          4                    de||+           dU| df| dWt                                          dX           dY|                     dZd[           d\| dg|+ dhtk          j6                     di})dj|)d!|+fcY d}~d`D ]"}*t          j        .                    |*d           #|r	 |/                    |	da           n:# t          t`          f$ r&}t
                              db||           Y d}~nd}~ww xY w	 |1                                 S # t          t`          f$ r&}t
                              dc||           Y d}~S d}~ww xY wS d}~ww xY w# d`D ]"}*t          j        .                    |*d           #|r	 |/                    |	da           n:# t          t`          f$ r&}t
                              db||           Y d}~nd}~ww xY w	 |1                                 w # t          t`          f$ r&}t
                              dc||           Y d}~w d}~ww xY ww xY w)lz
    Execute a single cron job.
    
    Returns:
        Tuple of (success, full_output_doc, final_response, error_message)
    r   )AIAgentN)	SessionDBz0Job '%s': SQLite session store not available: %sr3   ?rE   cron__z%Y%m%d_%H%M%SzRunning job '%s' (ID: %s)z
Prompt: %sd   r   HERMES_SESSION_PLATFORMr   HERMES_SESSION_CHAT_ID	chat_nameHERMES_SESSION_CHAT_NAME)load_dotenvz.envTzutf-8)overrideencodingzlatin-1!HERMES_CRON_AUTO_DELIVER_PLATFORM HERMES_CRON_AUTO_DELIVER_CHAT_IDr   "HERMES_CRON_AUTO_DELIVER_THREAD_IDmodelHERMES_MODELr    zconfig.yamldefaultz8Job '%s': failed to load config.yaml, using defaults: %s)parse_reasoning_effortHERMES_REASONING_EFFORTagentreasoning_effortHERMES_PREFILL_MESSAGES_FILEprefill_messages_filer)r   z8Job '%s': failed to parse prefill messages file '%s': %s	max_turnsZ   provider_routingsmart_model_routing)resolve_runtime_providerformat_runtime_provider_error	requestedproviderHERMES_INFERENCE_PROVIDERbase_urlexplicit_base_url)resolve_turn_routeapi_keyapi_modecommandargs)r   r   r   r   r   r   r   runtimeacp_commandacp_argsmax_iterationsreasoning_configprefill_messagesproviders_allowedonlyproviders_ignoredignoreproviders_orderorderprovider_sortsortdisabled_toolsets)cronjob	messagingclarify
quiet_modeskip_memoryr   
session_id
session_dbfinal_responsez(No response generated)z# Cron Job: z

**Job ID:** z
**Run Time:** z%Y-%m-%d %H:%M:%Sz
**Schedule:** schedule_displayzN/Az

## Prompt

z

## Response

r~   zJob '%s' completed successfully)r   r   r   r   r   r   cron_completez#Job '%s': failed to end session: %sz2Job '%s': failed to close SQLite session store: %sz: zJob '%s' failed: %sz (FAILED)

**Job ID:** z

## Error

```
z

z
```
Frx   )7	run_agentr   hermes_stater   r(   rJ   debugr   r   r   _hermes_nowstrftimerf   r)   environr!   dotenvr   _hermes_homeUnicodeDecodeErrorr0   r*   yamlpathexistsopen	safe_load
isinstancedictrK   hermes_constantsr   r&   r   r   
expanduseris_absoluteloadlisthermes_cli.runtime_providerr   r   r_   agent.smart_model_routingr   run_conversationpopend_sessionKeyboardInterruptr`   type__name__rI   	traceback
format_exc),r   r   _session_dbr   ri   job_idjob_namert   r   _cron_session_idr   delivery_targetr   _cfgr   	_cfg_path_f
_model_cfgr   effortr   r   prefill_file_jsonpfpath_pfr   prsmart_routingr   r   runtime_kwargsr   excmessager   
turn_router   re   r   logged_responseoutputkey	error_msgs,                                               r   run_jobr
  $  s    "!!!!! K`******ikk ` ` `GQUWZI[I[]^________` YF6{Hs##FS!!FQvQQ(>(>(O(OQQ
KK+Xv>>>
KKfTcTl+++  I06z0B
,-/26)3D/E/E
+,::k"" 	I5;K5HBJ12|^ 	'&&&&&	WKL6122TGTTTTT! 	W 	W 	WKL6122TIVVVVVV	W 3377 	e>Mj>YBJ:;=@QZA[=\=\BJ9:"";//;CFWbGcCdCd
?@  CBIn$=$=C 	bKKKL=899Iw~~i(( A)__ 4>>"--3D4 4 4 4 4 4 4 4 4 4 4 4 4 4 4!XXgr22
www'' A!*c22 A *#J55 A *y% @ @ 	b 	b 	bNNUW]_`aaaaaaaa	b 	<;;;;;4b99 	T'2..223ErJJKKQQSSF11&99  y!?DDmQhjlHmHm 	,    ,''2244F%%'' /%.}} ,,fcG<<< ;+0::c??(; ; ; ; ; ; ; ; ; ; ; ; ; ; ;%&6== 0+/(  , , ,NN#]_egmopqqq'+$$$$$$,
 '2..22;??^488KCXCX^\^ XX("--!6;;Ar	
 	
 	
 	
 	
 	
 	
 	
		1SWWZ00ZBI>Y4Z4ZN wwz"" J69ggj6I6I23..@@@@GG 	1 	1 	133C88Gw''S0	1 	A@@@@@''";;y11#KK
33#KK
33#KK
33";;y11W[[006B77 
 

  
 
 
W%%
y)--i888
  	*..z:::
  	*..z:::	

  	*..z:::
 #9-11)<<<
  	*..v666
 *>
 .-
 .-
 !ffVnnn
 !ffX...
 FF7OOO
 &&...
 BAAA
  t!
" #
$ V%
& (''
( #{)
. ''//$4b99?R -;Y..@Y(    }}%%&9::  ww)511	       	5x@@@V^T18
 	& 	&C JNN3%%%% 	^O''(8/JJJJ01 O O OBFANNNNNNNNO^!!####01 ^ ^ ^QSY[\]]]]]]]]^	^G  , , ,Aww'333q6633	*Hi@@@(    }}%%&9::  ww)511	        $ fb)++++++
 	& 	&C JNN3%%%% 	^O''(8/JJJJ01 O O OBFANNNNNNNNO^!!####01 ^ ^ ^QSY[\]]]]]]]]^	^G,4
 	& 	&C JNN3%%%% 	^O''(8/JJJJ01 O O OBFANNNNNNNNO^!!####01 ^ ^ ^QSY[\]]]]]]]]^	^s   
A0AAd6 !#F d6 -F52d6 4F55B/d6 %A	M .KM KM KA1M d6 
M<M72d6 7M<<C:d6 7S 	R+S +R//S 2R/3S d6 
TS<7d6 <TA9d6 ;A W d6 
X&XXI&d6 b++c"<cc"&c;;d2d--d26j8B#j3$j8%j; h((i9ii#i88j/	j**j/3j88j; ;(n$k;:n;l2l-(n-l22n6m
nnm=8n=nnTverbosec           	       
   t                               dd           d}	 t          t          d          }t          r-t	          j        |t          j        t          j        z             n9t          r2t          j	        |
                                t          j        d           nH# t          t          f$ r4 t                              d           ||                                 Y dS w xY w	 t#                      }| r|st                              dt'                                          d	                     	 t          r t	          j        |t          j                   nRt          rK	 t          j	        |
                                t          j        d           n# t          t          f$ r Y nw xY w|                                 dS | rHt                              d
t'                                          d	          t/          |                     d}|D ]}	 t1          |d                    t3          |          \  }}}}t5          |d         |          }	| rt                              d|	           |r|n!d|                    d|d                    d| }
t9          |
          }|ri|rg|
                                                                                    t@                    r)t                              d|d         t@                     d}|rK	 tC          ||
           n9# tD          $ r,}t          #                    d|d         |           Y d}~nd}~ww xY wtI          |d         ||           |dz  }k# tD          $ rQ}t          #                    d|d         |           tI          |d         dtK          |                     Y d}~d}~ww xY w|t          r t	          j        |t          j                   nRt          rK	 t          j	        |
                                t          j        d           n# t          t          f$ r Y nw xY w|                                 S # t          r t	          j        |t          j                   nRt          rK	 t          j	        |
                                t          j        d           n# t          t          f$ r Y nw xY w|                                 w xY w)aV  
    Check and run all due jobs.
    
    Uses a file lock so only one tick runs at a time, even if the gateway's
    in-process ticker and a standalone daemon or manual tick overlap.
    
    Args:
        verbose: Whether to print status messages
    
    Returns:
        Number of jobs executed (0 if another tick is already running)
    T)parentsexist_okNwr   u0   Tick skipped — another instance holds the lockr   z%s - No jobs duez%H:%M:%Sz%s - %s job(s) duer3   zOutput saved to: %su   ⚠️ Cron job 'rE   z
' failed:
u1   Job '%s': agent returned %s — skipping deliveryFzDelivery failed for job %s: %szError processing job %s: %s)&	_LOCK_DIRmkdirr   
_LOCK_FILEfcntlflockLOCK_EXLOCK_NBmsvcrtlockingfilenoLK_NBLCKOSErrorIOErrorrJ   r   r`   r   rf   r   r   LOCK_UNLK_UNLCKlenr   r
  r
   r   boolr&   r+   
startswithSILENT_MARKERrr   r(   rI   r	   r!   )r  lock_fddue_jobsexecutedr   r|   r  r   rI   output_filedeliver_contentshould_deliverderi   s                 r   tickr*    s     OOD4O000 G
z3'' 	AK!>???? 	AN7>>++V_a@@@W   GHHHMMOOOqq	8>> 	8 	KK*KMM,B,B:,N,NOOOX  	K//// 	w~~//!DDDDW%   c  	aKK,kmm.D.DZ.P.PRUV^R_R_``` "	7 "	7C!7
 !T+++9@6-c$i@@ DKK 5{CCC
 5<  #D..  BDUXU\U\]cehimenUoUo  BD  BD  }B  BD  BD!%o!6!6! +g +/2G2G2I2I2O2O2Q2Q2\2\]j2k2k +KK SUXY]U^`mnnn%*N! VV'_====$ V V V%Es4yRTUUUUUUUUV SY777A 7 7 7:CIqIIISYs1vv666666667  	K//// 	w~~//!DDDDW%     	K//// 	w~~//!DDDDW%   s   BB# #AC('C(,AQ. (2F F/.F/AQ. C>NL*)N*
M 4"MNM  N?Q. 
OAOQ. OQ. 2QQQ./S=2SS=S%"S=$S%%S=__main__)r  )T)0__doc__r]   r   loggingr)   sysr   r  ImportErrorr  pathlibr   r   r   hermes_cli.configr   typingr   hermes_timer   r   	getLoggerr   rJ   r   r   r!   __file__parent	cron.jobsr   r	   r
   r   r"  r   r  r  r   r   r0   rr   r   tupler   r
  intr*  rx   r   r   <module>r:     s       				 



    LLLL   E   	       , , , , , , ) ) ) ) ) )       * * * * * *		8	$	$ 33ttH~~,344 5 5 5 S S S S S S S S S S S S
     6!	%
	 	(4. 	 	 	 	>$ >8D> > > > >BaW aW aW aW aW aW aWH:4 :C : : : :z^^ ^^%c3 => ^^ ^^ ^^ ^^BU U$ U# U U U Up zD s$   ! >.>8>8>>