
    i1                        S r SSKJr  SSKrSSKrSSKrSSK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  SS	KJr  SS
 jrSS jrSS jr " S S\5      rS/rg)zFile search middleware for Anthropic text editor and memory tools.

This module provides Glob and Grep search tools that operate on files stored
in state or filesystem.
    )annotationsN)suppress)datetimetimezone)Path)Literal)tool)AgentMiddlewarec                l   ^^ SU ;   a  SU ;  a  g/ mSUU4S jjm T" U 5        T$ ! [          a     gf = f)z?Expand brace patterns like ``*.{py,pyi}`` into a list of globs.}{Nc                  > U R                  S5      nUS:X  a  TR                  U 5        g U R                  SU5      nUS:X  a  [        eU S U nXS-   S  nXS-   U nU(       d  [        eUR                  S5       H  nT" X6-   U-   5        M     g )Nr   r      ,)findappend
ValueErrorsplit)	currentstartendprefixsuffixinneroption_expandexpandeds	          a/home/james-whalen/.local/lib/python3.13/site-packages/langchain/agents/middleware/file_search.pyr   )_expand_include_patterns.<locals>._expand   s    S!B;OOG$ll3&"9%q#	C(kk#&FFOf,- '    )r   strreturnNone)r   )patternr   r   s    @@r   _expand_include_patternsr&      sK    
g~#W,H. .& O  s   & 
33c                  ^  T (       d  g[        U 4S jS 5       5      (       a  g[        T 5      nUc  g U H-  n[        R                  " [        R
                  " U5      5        M/     g! [        R                   a     gf = f)z/Validate glob pattern used for include filters.Fc              3  ,   >#    U  H	  oT;   v   M     g 7fN ).0charr%   s     r   	<genexpr>,_is_valid_include_pattern.<locals>.<genexpr>>   s     
<';t7?';s   ) 
T)anyr&   recompilefnmatch	translateerror)r%   r   	candidates   `  r   _is_valid_include_patternr9   9   st    

<';
<<<'0H!IJJw((34 "
  88 s   3A) )B ?B c                T   ^  [        U5      nU(       d  g[        U 4S jU 5       5      $ )z8Return True if the basename matches the include pattern.Fc              3  R   >#    U  H  n[         R                   " TU5      v   M     g 7fr)   )r5   )r+   r8   basenames     r   r-   )_match_include_pattern.<locals>.<genexpr>T   s     NX	wx33Xs   $')r&   r2   )r<   r%   r   s   `  r   _match_include_patternr>   N   s$    '0HNXNNNr!   c                      \ rS rSrSrSSS.       SS jjrSS jr        SS jr        SS	 jr      SS
 jr	Sr
g)FilesystemFileSearchMiddlewareW   a>  Provides Glob and Grep search over filesystem files.

This middleware adds two tools that search through local filesystem:
- Glob: Fast file pattern matching by file path
- Grep: Fast content search using ripgrep or Python fallback

Example:
    ```python
    from langchain.agents import create_agent
    from langchain.agents.middleware import (
        FilesystemFileSearchMiddleware,
    )

    agent = create_agent(
        model=model,
        tools=[],
        middleware=[
            FilesystemFileSearchMiddleware(root_path="/workspace"),
        ],
    )
    ```
T
   )use_ripgrepmax_file_size_mbc                  ^  [        U5      R                  5       T l        UT l        US-  S-  T l        [
        SSU 4S jjj5       n[
           S         SU 4S jjj5       nUT l        UT l        XE/T l        g)	a  Initialize the search middleware.

Args:
    root_path: Root directory to search.
    use_ripgrep: Whether to use ripgrep for search (default: True).
        Falls back to Python if ripgrep unavailable.
    max_file_size_mb: Maximum file size to search in MB (default: 10).
i   c                r  >  TR                  U5      nUR                  5       (       a  UR                  5       (       d  g/ nUR	                  U 5       H  nUR                  5       (       d  M  S[        UR                  TR                  5      5      -   nUR                  5       n[        R                  " UR                  [        R                  S9R                  5       nUR!                  XW45        M     U(       d  gU VV	s/ s H  u  pUPM	     n
nn	SR#                  U
5      $ ! [         a     gf = fs  sn	nf )a  Fast file pattern matching tool that works with any codebase size.

Supports glob patterns like **/*.js or src/**/*.ts.
Returns matching file paths sorted by modification time.
Use this tool when you need to find files by name patterns.

Args:
    pattern: The glob pattern to match files against.
    path: The directory to search in. If not specified, searches from root.

Returns:
    Newline-separated list of matching file paths, sorted by modification
    time (most recently modified first). Returns "No files found" if no
    matches.
zNo files found/)tzr0   )_validate_and_resolve_pathr   existsis_dirglobis_filer"   relative_to	root_pathstatr   fromtimestampst_mtimer   utc	isoformatr   join)r%   path	base_fullmatchingmatchvirtual_pathrP   modified_atp_
file_pathsselfs              r   glob_search<FilesystemFileSearchMiddleware.__init__.<locals>.glob_search   s    "( ;;DA	 ##%%Y-=-=-?-?' /1H"0==??#&U->->t~~-N)O#OL ::<D"*"8"88<<"X"b"b"dKOO\$?@ 1 '(01!J199Z(()  ('(& 2s   D# D3#
D0/D0Nc                  >  [         R                  " U 5        U(       a  [        U5      (       d  gSnTR                  (       aH  [        [        [        R                  [        R                  5         TR                  XU5      nSSS5        Uc  TR                  XU5      nU(       d  gTR                  XS5      $ ! [         R                   a  nSU 3s SnA$ SnAff = f! , (       d  f       Nb= f)a  Fast content search tool that works with any codebase size.

Searches file contents using regular expressions. Supports full regex
syntax and filters files by pattern with the include parameter.

Args:
    pattern: The regular expression pattern to search for in file contents.
    path: The directory to search in. If not specified, searches from root.
    include: File pattern to filter (e.g., "*.js", "*.{ts,tsx}").
    output_mode: Output format:
        - "files_with_matches": Only file paths containing matches (default)
        - "content": Matching lines with file:line:content format
        - "count": Count of matches per file

Returns:
    Search results formatted according to output_mode. Returns "No matches
    found" if no results.
zInvalid regex pattern: NzInvalid include patternzNo matches found)r3   r4   r7   r9   rC   r   FileNotFoundError
subprocessCalledProcessErrorTimeoutExpired_ripgrep_search_python_search_format_grep_results)r%   rV   includeoutput_modeeresultsr_   s         r   grep_search<FilesystemFileSearchMiddleware.__init__.<locals>.grep_search   s    45

7# 8AA0 G%11--
 #227'JG --gWE) ,,WBB1 88 50445 s)   B: 1C :CCCC 
C.)rG   )r%   r"   rV   r"   r#   r"   )rG   Nfiles_with_matches)
r%   r"   rV   r"   rj   
str | Nonerk   z1Literal['files_with_matches', 'content', 'count']r#   r"   )	r   resolverO   rC   max_file_size_bytesr	   r`   rn   tools)r_   rO   rC   rD   r`   rn   s   `     r   __init__'FilesystemFileSearchMiddleware.__init__o   s     i002&#3d#:T#A  
&	) &	) 
&	)P 
 "&Ma	3	C3	C3	C  3	C K	3	C
 3	C 
3	Cj '&!/
r!   c                @   UR                  S5      (       d  SU-   nSU;   d  SU;   a  Sn[        U5      eUR                  S5      nU R                  U-  R	                  5       n UR                  U R                  5        U$ ! [         a    SU 3n[        U5      Sef = f)z7Validate and resolve a virtual path to filesystem path.rG   z..~zPath traversal not allowedzPath outside root directory: N)
startswithr   lstriprO   rr   rN   )r_   rV   msgrelative	full_paths        r   rI   9FilesystemFileSearchMiddleware._validate_and_resolve_path   s     s##:D 4<3$;.CS/! ;;s#^^h.779		,!!$..1
 	  	,1$8CS/t+	,s   $B Bc                J    U R                  U5      nUR                  5       (       d  0 $ SS/nU(       a  UR                  SU/5        UR                  SU[	        U5      /5         [
        R                  " USSSSS9n0 nUR                  R                  5        H  n [        R                  " U5      n	U	S	   S
:X  a|  U	S   S   S   n
S[	        [        U
5      R                  U R                   5      5      -   nU	S   S   nU	S   S   S   R#                  S5      nX;  a  / X{'   X{   R%                  X45        M  M     U$ ! [         a    0 s $ f = f! [
        R                  [        4 a    U R                  XU5      s $ f = f! [        R&                  [(        4 a     GM  f = f)z Search using ripgrep subprocess.rgz--jsonz--globz--T   F)capture_outputtexttimeoutchecktyperY   datarV   r   rG   line_numberlinesr0   )rI   r   rJ   extendr"   rd   runrf   rc   rh   stdout
splitlinesjsonloadsr   rN   rO   rstripr   JSONDecodeErrorKeyError)r_   r%   	base_pathrj   rW   cmdresultrm   liner   rV   rZ   line_num	line_texts                 r   rg   .FilesystemFileSearchMiddleware._ripgrep_search   s   	77	BI !!I XJJ'*+

D'3y>23
	D^^#F 57MM,,.Dzz$'<7*</7D#&T$Z-C-CDNN-S)T#TL#F|M:H $VW 5f = D DT JI#202-)00(1FG + /  [  	I	. ))+<= 	D&&w7CC	D& (((3 s6   D? &E BF?EE,F ?F F"!F"c                    U R                  U5      nUR                  5       (       d  0 $ [        R                  " U5      n0 nUR                  S5       H  nUR                  5       (       d  M  U(       a  [        UR                  U5      (       d  M>  UR                  5       R                  U R                  :  a  Mh   UR                  5       n[        UR!                  5       S5       Ha  u  pUR#                  U
5      (       d  M  S[%        UR'                  U R(                  5      5      -   nX;  a  / Xk'   Xk   R+                  X45        Mc     M     U$ ! [         a    0 s $ f = f! [        [        4 a     GM$  f = f)z%Search using Python regex (fallback).*r   rG   )rI   r   rJ   r3   r4   rglobrM   r>   namerP   st_sizers   	read_textUnicodeDecodeErrorPermissionError	enumerater   searchr"   rN   rO   r   )r_   r%   r   rj   rW   regexrm   	file_pathcontentr   r   rZ   s               r   rh   -FilesystemFileSearchMiddleware._python_search3  sW   	77	BI !!I

7#46 #-I$$&& 5inngNN ~~''$*B*BB#--/
 #,G,>,>,@!"D<<%%#&Y-B-B4>>-R)S#SL#202-)00(1AB #E% .2 G  	I	0 '8 s#   E <E#E E #E87E8c           	     $   US:X  a(  SR                  [        UR                  5       5      5      $ US:X  aY  / n[        UR                  5       5       H)  nX    H  u  pVUR                  U SU SU 35        M      M+     SR                  U5      $ US:X  aV  / n[        UR                  5       5       H&  n[	        X   5      nUR                  U SU 35        M(     SR                  U5      $ SR                  [        UR                  5       5      5      $ )z)Format grep results based on output mode.rp   r0   r   :count)rU   sortedkeysr   len)r_   rm   rk   r   r   r   r   r   s           r   ri   3FilesystemFileSearchMiddleware._format_grep_results^  s     ..99VGLLN344)#E#GLLN3	&-&8NHLLI;az4&!AB '9 4 99U##'!E#GLLN3	G./	{!E734 4 99U## yy/00r!   )r`   rn   rs   rO   rt   rC   N)rO   r"   rC   boolrD   intr#   r$   )rV   r"   r#   r   )r%   r"   r   r"   rj   rq   r#    dict[str, list[tuple[int, str]]])rm   r   rk   r"   r#   r"   )__name__
__module____qualname____firstlineno____doc__ru   rI   rg   rh   ri   __static_attributes__r*   r!   r   r@   r@   W   s    6 ! "u0 u0 	u0
 u0 
u0n033'*35?3	)3j))'*)5?)	))V111 1 
	1r!   r@   )r%   r"   r#   zlist[str] | None)r%   r"   r#   r   )r<   r"   r%   r"   r#   r   )r   
__future__r   r5   r   r3   rd   
contextlibr   r   r   pathlibr   typingr   langchain_core.toolsr	   !langchain.agents.middleware.typesr
   r&   r9   r>   r@   __all__r*   r!   r   <module>r      sY    #   	   '   % =D*Ob1_ b1L	 %r!   