+
    ƒWÝj  ã                  óD  a € 0 t $ R t^ RIHt ^ RIt^ RIt^ RIHt ^ RIH	t	 ^ RI
HtHtHtHtHt ^ RIHt ^ RIHt RtR]R	&   R t^€tR!t]P4                  ! 4       tR
 R ltR R ltR R lt]R R l4       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%  Per-job durable KV notepad (cursors, watermarks) carried across cron wake-ups; profile-local
SQLite next to the executions ledger (same connection/pragma pattern as ``cron/executions.py``).

Caps are a documented contract: ``MAX_VALUE_BYTES`` (16 KB per value, UTF-8) and
``MAX_JOB_TOTAL_BYTES`` (64 KB per job, key+value). Oversized writes raise ``ValueError`` and leave
the store untouched â€” the notepad is prompt-injected each run. Write path is the CLI
(``hermes cron notepad <job_id> set ...``) via the terminal tool; no model tool is added.
)ÚannotationsN)Úcontextmanager)ÚPath)ÚAnyÚDictÚIteratorÚListÚOptional)Úget_hermes_home)ÚnowzOptional[Path]ÚNOTEPAD_FILEc               ó   € V ^8„  d   QhRR/# )é   Úreturnr   © )Úformats   "Ú@C:\Users\johnn\AppData\Local\hermes\hermes-agent\cron\notepad.pyÚ__annotate__r       s   € ÷ Qñ Q˜tñ Qó    c                 ój   € \         ;'       g'    \        4       P                  4       R ,          R,          # )Úcronz
notepad.db)r   r
   Úresolver   r   r   Ú_current_notepad_filer       s&   € Ü×PÐPœOÓ-×5Ñ5Ó7¸&Õ@À<ÕOÐPr   c               ó   € V ^8„  d   QhRR/# )r   r   úsqlite3.Connectionr   )r   s   "r   r   r   $   s   € ÷ 	Tñ 	TÐ$ñ 	Tr   c                 óp   € ^ RI Hp  ^ RIHp \	        4       pV ! VP
                  4       V! VR\        R7      # )é    )Ú_ensure_cron_dir)Úopen_dbzcron/notepad.db)Údb_labelÚ
initialize)Ú	cron.jobsr   Úhermes_cli.sqlite_utilr   r   ÚparentÚ_initialize_schema)r   r   Úpaths      r   Ú_connectr&   $   s/   € õ +Ý.ä Ó"€DÙ�T—[‘[Ô!Ù�4Ð"3Ô@RÔSÐSr   c               ó    € V ^8„  d   QhRRRR/# )r   Úconnr   r   ÚNoner   )r   s   "r   r   r   0   s   € ÷ 	ñ 	Ð/ð 	°Dñ 	r   c                ó(   € V P                  R 4       R# )zéCREATE TABLE IF NOT EXISTS cron_notepad (
             job_id TEXT NOT NULL,
             key TEXT NOT NULL,
             value TEXT NOT NULL,
             updated_at TEXT NOT NULL,
             PRIMARY KEY (job_id, key)
           )N)Úexecute)r(   s   &r   r$   r$   0   s   € Ø‡L�Lð	ör   c               ó   € V ^8„  d   QhRR/# )r   r   zIterator[sqlite3.Connection]r   )r   s   "r   r   r   =   s   € ÷ ñ Ð2ñ r   c            	   #  óà   "  € ^ RI Hp  \        ;_uu_ 4        V ! \        4       4      ;_uu_ 4       pVx € RRR4       RRR4       R#   + '       g   i     L; i  + '       g   i     R# ; i5i)r   )ÚtransactionN)r"   r.   Ú_lockr&   )r.   r(   s     r   Ú_transactionr0   <   s6   é € å2ç	Ž‘œH›J×'Ô'¨4ØŠ
÷ (�‰×'×'ú��ˆüs1   ‚A.—A°A	µA½
A.ÁAÁAÁA+	Á%	A.c               ó(   € V ^8„  d   QhRRRRRRRR/# )r   Újob_idÚstrÚkeyÚvaluer   r)   r   )r   s   "r   r   r   D   s.   € ÷ Sñ S�cð S ð S¨Cð S°Dñ Sr   c                ó  € \        V 4      '       g   \        R 4      hV'       g   \        R4      h\        V4      \        8”  d   \        R\         R24      h\        VP	                  R4      4      \
        8”  d   \        R\
         R24      hR# )zjob_id must be non-emptyzkey must be non-emptyzkey too long (max z characters)úutf-8zvalue too large (max z bytes per key)N)r3   Ú
ValueErrorÚlenÚMAX_KEY_CHARSÚencodeÚMAX_VALUE_BYTES)r2   r4   r5   s   &&&r   Ú	_validater=   D   sx   € Üˆv�;Š;ÜÐ3Ó4Ð4ßÜÐ0Ó1Ð1Ü
ˆ3ƒx”-ÔÜÐ-¬m¨_¸LÐIÓJÐJÜ
ˆ5�<‰<˜Ó Ó!¤OÔ3ÜÐ0´Ð0AÀÐQÓRÐRñ 4r   c               ó(   € V ^8„  d   QhRRRRRRRR/# )r   r2   r3   r4   r5   r   zdict[str, Any]r   )r   s   "r   r   r   O   s.   € ÷ Mñ M�Sð M˜sð M¨3ð M°>ñ Mr   c           	     óH  € \        V 4      \        V4      \        V4      r!p \        WV4       \        4       P                  4       p\	        4       ;_uu_ 4       pVP                  RW34      P                  4       p\        V^ ,          4      p\        VP                  R4      4      \        VP                  R4      4      ,           pWg,           \        8”  d   \        RV  R\         R24      hVP                  RWW#34       RRR4       RV R	VR
VRV/#   + '       g   i     L; i)zDUpsert one key. Raises ValueError when a size cap would be exceeded.zœSELECT COALESCE(SUM(LENGTH(CAST(key AS BLOB))
                 + LENGTH(CAST(value AS BLOB))), 0)
               FROM cron_notepad WHERE job_id=? AND key<>?r7   znotepad full: job 'z' would exceed z& bytes total; delete unused keys firstzÖINSERT INTO cron_notepad (job_id, key, value, updated_at)
               VALUES (?, ?, ?, ?)
               ON CONFLICT(job_id, key)
               DO UPDATE SET value=excluded.value, updated_at=excluded.updated_atNr2   r4   r5   Ú
updated_at)r3   r=   Ú_hermes_nowÚ	isoformatr0   r+   ÚfetchoneÚintr9   r;   ÚMAX_JOB_TOTAL_BYTESr8   )r2   r4   r5   r   r(   ÚrowÚother_bytesÚentry_bytess   &&&     r   Úset_noterI   O   s  € ä˜V›¤c¨#£h´°E³
�€FÜˆf˜5Ô!Ü
‹-×
!Ñ
!Ó
#€CÜ	�Œ˜4Ø�l‰lð>ð ˆMó	
÷
 ‰(‹*ð 	ô ˜#˜a�&“kˆÜ˜#Ÿ*™* WÓ-Ó.´°U·\±\À'Ó5JÓ1KÕKˆØÕ$Ô':Ô:ÜØ% f X¨_Ü&Ð'Ð'MðOóð ð 	�‰ðUð ˜%Ð%ô	
÷ 
ð* �f˜e S¨'°5¸,ÈÐLÐL÷+ 
�ús   ÁB(DÄD!	c               ó$   € V ^8„  d   QhRRRRRR/# )r   r2   r3   r4   r   zOptional[str]r   )r   s   "r   r   r   l   s!   € ÷ 1ñ 1�Sð 1˜sð 1 }ñ 1r   c           	     óä   € \        4       ;_uu_ 4       pVP                  R \        V 4      \        V4      34      P                  4       pRRR4       Xf   R# VR,          #   + '       g   i     L; i)z7SELECT value FROM cron_notepad WHERE job_id=? AND key=?Nr5   )r0   r+   r3   rC   )r2   r4   r(   rF   s   &&  r   Úget_noterL   l   sZ   € Ü	�Œ˜4Ø�l‰lØEÜ�‹[œ#˜c›(Ð#ó
÷ ‰(‹*ð 	÷ 
ð
 ’;ˆ4Ð0 C¨¥LÐ0÷ 
�ús   “5AÁA/	c               ó$   € V ^8„  d   QhRRRRRR/# )r   r2   r3   r4   r   Úboolr   )r   s   "r   r   r   u   s!   € ÷ ñ ˜ð  #ð ¨$ñ r   c           	     óÈ   € \        4       ;_uu_ 4       pVP                  R \        V 4      \        V4      34      pRRR4       XP                  ^ 8„  #   + '       g   i     L; i)z1DELETE FROM cron_notepad WHERE job_id=? AND key=?N)r0   r+   r3   Úrowcount)r2   r4   r(   Úcurs   &&  r   Údelete_noterR   u   sJ   € Ü	�Œ˜4Ø�l‰lØ?Ü�‹[œ#˜c›(Ð#ó
ˆ÷ 
ð
 �<‰<˜!ÑÐ÷ 
�ús   “'AÁA!	c               ó    € V ^8„  d   QhRRRR/# )r   r2   r3   r   zlist[dict[str, Any]]r   )r   s   "r   r   r   ~   s   € ÷ 'ñ '�sð 'Ð3ñ 'r   c                óò   € \        4       ;_uu_ 4       pVP                  R\        V 4      34      P                  4       pRRR4       X Uu. uF  p\	        V4      NK  	  up#   + '       g   i     L+; iu upi )z'All entries for one job, sorted by key.zSSELECT job_id, key, value, updated_at FROM cron_notepad WHERE job_id=? ORDER BY keyN)r0   r+   r3   ÚfetchallÚdict)r2   r(   ÚrowsrF   s   &   r   Ú
list_notesrX   ~   s_   € ä	�Œ˜4Ø�|‰|ð*ä�‹[ˆNó
÷ ‰(‹*ð	 	÷ 
ñ "&Ó&¡˜#ŒD�ŽI¡Ñ&Ð&÷ 
�üò 's   “+A!Á
A4Á!A1	c               ó    € V ^8„  d   QhRRRR/# )r   r2   r3   r   rD   r   )r   s   "r   r   r   ‰   s   € ÷ 	ñ 	˜#ð 	 #ñ 	r   c                ó  € \        4       P                  4       '       g   ^ # \        4       ;_uu_ 4       pVP                  R\	        V 4      34      pRRR4       VP
                  #   + '       g   i     XP
                  # ; i)z—Delete every key for one job (called from ``cron.jobs.remove_job``). Returns row count;
no-ops without creating the DB when no notepad file exists yet.z'DELETE FROM cron_notepad WHERE job_id=?N)r   Úexistsr0   r+   r3   rP   )r2   r(   rQ   s   &  r   Úclear_notepadr\   ‰   s`   € ô !Ó"×)Ñ)×+Ò+ÙÜ	�Œ˜4Ø�l‰lØ5¼¸F»°~ó
ˆ÷ 
ð �<‰<Ð÷	 
Žð �<‰<Ðús   ³A$Á$A?	c               ó    € V ^8„  d   QhRRRR/# )r   r2   r3   r   r   )r   s   "r   r   r   •   s   € ÷ ñ  3ð ¨3ñ r   c                óò   €  \        V 4      pT'       g   R# T Uu. uF  pRTR,           RTR,           2NK  	  ppRT  RT  R2R	P                  T4      ,           R
,           #   \         d     R# i ; iu upi )z©Render a job's notepad as a prompt section. An empty notepad MUST return '' so jobs that
never use the feature get a byte-identical prompt (prompt-cache + drift safety).Ú z- r4   z: r5   zŸ## Job notepad (persistent across runs)
This durable scratchpad survives between scheduled runs of this job. Update it via the CLI, e.g.:
`hermes cron notepad zA set <key> <value>` (also: get/delete/list; `hermes cron notepad z# delete <key>` removes an entry).

Ú
z

)rX   Ú	ExceptionÚjoin)r2   ÚnotesÚnoteÚliness   &   r   Úrender_notepad_sectionrf   •   s    € ðÜ˜6Ó"ˆ÷ ÙÙ=BÓC¹U°Tˆr�$�u•+�˜b  g¥ Ó0¹U€EÐCð	 ð !'˜xð (8Ø8>°xð @(ð		(ð
 +/¯)©)°EÓ*:õ	;ð
 >Dõ	Dðøô ô Úðüò Ds   ‚A" ›A4Á"A1Á0A1i @  i   )'Ú__conditional_annotations__Ú__doc__Ú
__future__r   Úsqlite3Ú	threadingÚ
contextlibr   Úpathlibr   Útypingr   r   r   r   r	   Úhermes_constantsr
   Úhermes_timer   rA   r   Ú__annotations__r<   r:   rE   ÚRLockr/   r   r&   r$   r0   r=   rI   rL   rR   rX   r\   rf   )rg   s   @r   Ú<module>rs      sš   øðôõ #ã Û Ý %Ý ß 6Õ 6å ,Ý *ð  $€ˆnÓ #Ø€Ø€ØÐ Ø�ŠÓ€õQõ	Tõ	ð ôó ðõSõMõ:1õõ'õ	÷r   