
    `gja+                       U d Z ddlmZ ddlZddlZddlZddlZddlmZ ddl	m
Z
mZmZmZ ddlmZ  ej"                  e      Zi Zded	<    ej,                         Zd
Z ej2                  d      ZddZddZddZddZddZddZ ddZ!	 	 	 	 	 	 d	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 d dZ"	 	 	 d!	 	 	 	 	 	 	 	 	 d"dZ#dZ$d#dZ%d$dZ&d%dZ'y)&u  disk-cleanup plugin — auto-cleanup of ephemeral Hermes session files.

Wires three behaviours:

1. ``post_tool_call`` hook — inspects ``write_file`` and ``terminal``
   tool results for newly-created paths matching test/temp patterns
   under ``HERMES_HOME`` and tracks them silently.  Zero agent
   compliance required.

2. ``on_session_end`` hook — when any test files were auto-tracked
   during the just-finished turn, runs :func:`disk_cleanup.quick` and
   logs a single line to ``$HERMES_HOME/disk-cleanup/cleanup.log``.

3. ``/disk-cleanup`` slash command — manual ``status``, ``dry-run``,
   ``quick``, ``deep``, ``track``, ``forget``.

Replaces PR #12212's skill-plus-script design: the agent no longer
needs to remember to run commands.
    )annotationsN)Path)AnyDictOptionalSet   )disk_cleanupzDict[str, Set[str]]_recent_test_trackspathz#(?:^|\s)(/[^\s'\"`]+|\~/[^\s'\"`]+)c                    | xs |xs dS )Ndefault )task_id
session_ids     P/root/.hermes/venv/lib/python3.12/site-packages/plugins/disk-cleanup/__init__.py_tracker_keyr   4   s    -j-I-    c                    |dk7  ryt        | |      }t        5  t        j                  |t	                     j                  t        |             ddd       y# 1 sw Y   yxY w)z=Record that we tracked *path* as *category* during this turn.testN)r   _lockr   
setdefaultsetaddstr)r   r   r   categorykeys        r   _record_trackr   8   sV    6
w

+C	 B&&sCE266s4yAB B Bs   7AA"c                    t        | |      }t        5  t        j                  |t	                     cddd       S # 1 sw Y   yxY w)z3Pop the set of test paths tracked during this turn.N)r   r   r   popr   )r   r   r   s      r   _drainr!   A   s8    
w

+C	 3"&&sCE23 3 3s	   ;Ac                   	 t        |       j                         }|j                         syt	        j
                  |      }|yt	        j                  t        |      |d      }|rt        ||||       yy# t        $ r Y yw xY w)z%Best-effort auto-track. Never raises.NTsilent)	r   
expanduser	Exceptionexistsdgguess_categorytrackr   r   )path_strr   r   pr   newlys         r   _attempt_trackr.   H   s    N%%' 88:  #HHHSVXd3Egz1h7   s   A7 7	BBc                j    | j                  t              }t        |t              r|r|hS t	               S )N)get_WRITE_FILE_PATH_KEY
isinstancer   r   argsr   s     r   _extract_paths_from_write_filer5   X   s+    88()Dc*tD6>>r   c                b    | j                  d      }t        |t              r|r|hS t               S )Nr   )r0   r2   r   r   r3   s     r   _extract_paths_from_patchr7   ]   s,     88FDc*tD6>>r   c                   t               }| j                  d      xs d}t        |t              rC|rA	 t	        j
                  |d      D ]%  }|j                  d      s|j                  |       ' 	 t        |t              r9t        |      dk  r+t        j                  |      D ]  }|j                  |        |S # t        $ r Y Vw xY w)zBest-effort: pull candidate filesystem paths from a terminal command
    and its output, then let ``guess_category`` / ``is_safe_path`` filter.
    command T)posix)/~i   )r   r0   r2   r   shlexsplit
startswithr   
ValueErrorlen_TERMINAL_PATH_REGEXfindall)r4   resultpathscmdtokmatchs         r   _extract_paths_from_terminalrJ   g   s     eE
((9

#C#s	{{3d3 #>>*-IIcN# &#3v;#5)11&9 	EIIe	L  		s   +B> B> >	C
	C
c                    t        |t              syt               }| dk(  rt        |      }n6| dk(  rt	        |      }n%| dk(  rt        |t        |t              r|nd      }ny|D ]  }t        |||        y)z8Auto-track ephemeral files created by recent tool calls.N
write_filepatchterminalr:   )r2   dictr   r5   r7   rJ   r   r.   )		tool_namer4   rE   r   r   tool_call_id_
candidatesr+   s	            r   _on_post_tool_callrT      s{     dD!5JL 3D9
	g	.t4
	j	 1$*VUXBY_ab
 6x*56r   c                   t        d|       }t        5  t        t        j	                               }ddd       D ]!  }|s|| k7  st        j                  |d       # |s|sy	 t        j                         }|d   s|d   r;t        j                  d|d    d|d    dt        j                  |d	                 yy# 1 sw Y   xY w# t        $ r }t        j                  d|       Y d}~yd}~ww xY w)
zBRun quick cleanup if any test files were tracked during this turn.r:   Nz%disk-cleanup quick cleanup failed: %sdeleted
empty_dirsz"AUTO_QUICK (session_end): deleted=z dirs=z freed=freed)r!   r   listr   keysr    r(   quickr&   loggerdebug_logfmt_size)	r   	completedinterruptedrR   drained_sessiontask_bucketsr   summaryexcs	            r   _on_session_endrf      s     R,O
 
 8/44678 /3*$##C./ <((*
 yW\2
01C0D EL)*'"++gg>N2O1PR	
 38 8  <cBs#   B?%C ?C	C4C//C4u  /disk-cleanup — ephemeral-file cleanup

Subcommands:
  status                     Per-category breakdown + top-10 largest
  dry-run                    Preview what quick/deep would delete
  quick                      Run safe cleanup now (no prompts)
  deep                       Run quick, then list items that need prompts
  track <path> <category>    Manually add a path to tracking
  forget <path>              Stop tracking a path (does not delete)

Categories: temp | test | research | download | chrome-profile | cron-output | other

All operations are scoped to HERMES_HOME and /tmp/hermes-*.
Test files are auto-tracked on write_file / terminal and auto-cleaned at session end.
c           	         d| d    d| d    dt        j                  | d          d}| j                  d      r|d	t        | d          d
z  }|S )Nz[disk-cleanup] Cleaned rV   z	 files + rW   z empty dirs, freed rX   .errorsz
  z error(s); see cleanup.log.)r(   r_   r0   rB   )rd   bases     r   _fmt_summaryrk      sr    
!')"4!5Y< 
!!4R[[AQ5R4SST	V 	 {{8$s78,-..IJJKr   c                n   | j                         j                         }|r|d   dv rt        S |d   }|dk(  r't        j                  t        j
                               S |dk(  rt        j                         \  }}t        d |D              }t        d |D              }ddt        |       d	t        j                  |       d
g}|D ]  }|j                  d|d    d|d           ! |j                  dt        |       d	t        j                  |       d
       |D ]  }|j                  d|d    d|d           ! |j                  dt        j                  ||z                 dj                  |      S |dk(  rt        t        j                               S |dk(  rt        j                         }	t        j                         \  }
}t        |	      g}|r{t        d |D              }|j                  dt        |       dt        j                  |       d       |D ]  }|j                  d|d    d|d           ! |j                  d       dj                  |      S |dk(  rpt        |      dk  ry|d   }|d   }|t        j                  vrd| dt        t        j                         S t        j                   ||d !      r	d"| d#| d$S d%| S |d&k(  rGt        |      dk  ry't        j"                  |d         }|rd(| d)|dk(  rd*nd+ d,|d    d-S d.|d    S d/| d0t         S )1Nr   >   -h--helphelpstatuszdry-runc              3  &   K   | ]	  }|d      ywsizeNr   .0is     r   	<genexpr>z _handle_slash.<locals>.<genexpr>   s     0a&	0   c              3  &   K   | ]	  }|d      ywrr   r   rt   s     r   rw   z _handle_slash.<locals>.<genexpr>   s     4!F)4rx   z"Dry-run preview (nothing deleted):z  Auto-delete : z files ()z    [r   z] r   z  Needs prompt: z
  Total potential: 
r[   deepc              3  &   K   | ]	  }|d      ywrr   r   rt   s     r   rw   z _handle_slash.<locals>.<genexpr>  s     7Qqy7rx   z item(s) need confirmation (z):z  [zL
Run `/disk-cleanup forget <path>` to skip, or delete manually via terminal.r*      z,Usage: /disk-cleanup track <path> <category>r	      zUnknown category 'z'. Allowed: Tr#   zTracked z as 'z'.z@Not tracked (already present, missing, or outside HERMES_HOME): forgetz"Usage: /disk-cleanup forget <path>zRemoved z tracking entryiesz for rh   zNot found in tracking: zUnknown subcommand: z

)stripr?   
_HELP_TEXTr(   format_statusrp   dry_runsumrB   r_   appendjoinrk   r[   ALLOWED_CATEGORIESsortedr*   r   )raw_argsargvsubautoprompt	auto_sizeprompt_sizelinesitemquick_summary_autoprompt_itemsrs   path_argr   ns                   r   _handle_slashr      s   >>!!#D4766
q'C
h		,,
izz|f0400	4V440s4yk"++i2H1IK
  	EDLL5j!1 2"T&\NCD	Es6{m8BKK4L3MQO	
  	EDLL5j!1 2"T&\NCD	E#BKK	K0G$H#IJ	
 yy
g~BHHJ''
f} 
 jjl|m,-7,77DLLS&' (KK%&b* % Gs4
#3"4BtF|nEFGLL) yy
g~t9q=A772000$XJ /"2#8#89:< 88Hht4hZuXJb99Nj	

 ht9q=7IId1g  qcqAv5'AtAwiqQ	
/Qy9	

 "#d:,77r   c                    | j                  dt               | j                  dt               | j                  dt        d       y )Npost_tool_callon_session_endzdisk-cleanupz2Track and clean up ephemeral Hermes session files.)handlerdescription)register_hookrT   rf   register_commandr   )ctxs    r   registerr   5  sA    &(:;&8H  r   )r   r   r   r   returnr   )
r   r   r   r   r   r   r   r   r   None)r   r   r   r   r   Set[str])r+   r   r   r   r   r   r   r   )r4   Dict[str, Any]r   r   )r4   r   rE   r   r   r   )r:   NNr:   r:   r:   )rP   r   r4   zOptional[Dict[str, Any]]rE   r   r   r   r   r   rQ   r   rR   r   r   r   )r:   TF)
r   r   r`   boolra   r   rR   r   r   r   )rd   r   r   r   )r   r   r   zOptional[str])r   r   )(__doc__
__future__r   loggingrer>   	threadingpathlibr   typingr   r   r   r   r:   r
   r(   	getLogger__name__r\   r   __annotations__Lockr   r1   compilerC   r   r   r!   r.   r5   r7   rJ   rT   rf   r   rk   r   r   r   r   r   <module>r      sO  ( #  	    + +  			8	$ ,. ( -	  !rzz"HI .B38 ?
?4 %)66
"6 6 	6
 6 6 
6 
68 !
!
!
 !
 
	!

 
!
P
$O8lr   