
    g3fi1                        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
 ddlmZ ddlmZ ddlmZ dd	lmZ dd
ZddZddZ G d de      ZdgZy)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                ^    d| v rd| vryg dfd	  |        S # t         $ r Y yw xY w)z=Expand brace patterns like `*.{py,pyi}` into a list of globs.}{Nc                   | j                  d      }|dk(  rj                  |        y | j                  d|      }|dk(  rt        | d | }| |dz   d  }| |dz   | }|st        |j                  d      D ]  } ||z   |z           y )Nr   r      ,)findappend
ValueErrorsplit)	currentstartendprefixsuffixinneroption_expandexpandeds	          e/var/www/auto_recruiter/arenv/lib/python3.12/site-packages/langchain/agents/middleware/file_search.pyr   z)_expand_include_patterns.<locals>._expand   s    S!B;OOG$ll3&"9%q#	C(kk#& 	.FFVOf,-	.    )r   strreturnNone)r   )patternr   r   s    @@r   _expand_include_patternsr%      sF    
g~#W,H.& O  s     	,,c                      syt         fddD              ryt               }|y	 |D ]*  }t        j                  t	        j
                  |             , 	 y# t        j                  $ r Y yw xY w)z/Validate glob pattern used for include filters.Fc              3  &   K   | ]  }|v  
 y wN ).0charr$   s     r   	<genexpr>z,_is_valid_include_pattern.<locals>.<genexpr>>   s     
<t47?
<s   ) 
T)anyr%   recompilefnmatch	translateerror)r$   r   	candidates   `  r   _is_valid_include_patternr7   9   sv    

<';
<<'0H! 	5IJJw((34	5
  88 s   /A A0/A0c                H     t        |      }|syt         fd|D              S )z8Return True if the basename matches the include pattern.Fc              3  J   K   | ]  }t        j                   |        y wr(   )r3   )r*   r6   basenames     r   r,   z)_match_include_pattern.<locals>.<genexpr>T   s     N	wx3Ns    #)r%   r0   )r:   r$   r   s   `  r   _match_include_patternr;   N   s$    '0HNXNNNr    c                  z    e Zd ZdZddd	 	 	 	 	 	 	 ddZddZ	 	 	 	 	 	 	 	 ddZ	 	 	 	 	 	 	 	 ddZ	 	 	 	 	 	 dd	Zy
)FilesystemFileSearchMiddlewarea  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=[],  # Add tools as needed
            middleware=[
                FilesystemFileSearchMiddleware(root_path="/workspace"),
            ],
        )
        ```
    T
   )use_ripgrepmax_file_size_mbc                    t        |      j                          _        | _        |dz  dz   _        t
        dd fd       }t
        	 	 	 d	 	 	 	 	 	 	 	 	 d fd       }| _        | _        ||g _        y)	a)  Initialize the search middleware.

        Args:
            root_path: Root directory to search.
            use_ripgrep: Whether to use `ripgrep` for search.

                Falls back to Python if `ripgrep` unavailable.
            max_file_size_mb: Maximum file size to search in MB.
        i   c                D   	 j                  |      }|j                         r|j                         syg }|j	                  |       D ]  }|j                         sdt        |j                  j                              z   }|j                         }t        j                  |j                  t        j                        j                         }|j!                  ||f        |sy|D 	cg c]  \  }}	|	 }
}}	dj#                  |
      S # t        $ r Y yw xY wc c}	}w )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/)tzr.   )_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_pathrL   modified_atp_
file_pathsselfs              r   glob_searchz<FilesystemFileSearchMiddleware.__init__.<locals>.glob_search   s   &( ;;DA	 ##%Y-=-=-?' /1H"0 A==?#&U->->t~~-N)O#OL ::<D"*"8"88<<"X"b"b"dKOO\;$?@A '(011!1J199Z(()  ('(& 2s   D -D	DDNc                   	 t        j                  |        |rt        |      syd}j                  rIt        t        t        j                  t        j                        5  j                  | ||      }ddd       |j                  | ||      }|syj                  ||      S # t         j                  $ r}d| cY d}~S d}~ww xY w# 1 sw Y   XxY w)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
                    - `'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)r1   r2   r5   r7   r?   r   FileNotFoundError
subprocessCalledProcessErrorTimeoutExpired_ripgrep_search_python_search_format_grep_results)r$   rR   includeoutput_modeeresultsr[   s         r   grep_searchz<FilesystemFileSearchMiddleware.__init__.<locals>.grep_search   s    65

7# 8A0 G%11-- K
 #227D'JGK --gtWE) ,,WkBB1 88 50445K Ks)   B' !C'C	:C>C	C	C)rC   )r$   r!   rR   r!   r"   r!   )rC   Nfiles_with_matches)
r$   r!   rR   r!   re   
str | Nonerf   z1Literal['files_with_matches', 'content', 'count']r"   r!   )	r   resolverK   r?   max_file_size_bytesr	   r\   ri   tools)r[   rK   r?   r@   r\   ri   s   `     r   __init__z'FilesystemFileSearchMiddleware.__init__p   s      i002&#3d#:T#A  
(	) 
(	)T 
 "&Ma	4	C4	C4	C  4	C K	4	C
 4	C 
4	Cl '&!;/
r    c                ,   |j                  d      sd|z   }d|v sd|v rd}t        |      |j                  d      }| j                  |z  j	                         }	 |j                  | j                         |S # t        $ r d| }t        |      dw xY w)z7Validate and resolve a virtual path to filesystem path.rC   z..~zPath traversal not allowedzPath outside root directory: N)
startswithr   lstriprK   rl   rJ   )r[   rR   msgrelative	full_paths        r   rE   z9FilesystemFileSearchMiddleware._validate_and_resolve_path   s     s#:D 4<3$;.CS/! ;;s#^^h.779		,!!$..1
 	  	,1$8CS/t+	,s   A8 8Bc                *   	 | j                  |      }|j                         si S ddg}|r|j                  d|g       |j                  d|t	        |      g       	 t        j                  |dddd      }i }|j                  j                         D ]  }	 t        j                  |      }	|	d	   d
k(  r||	d   d   d   }
dt	        t        |
      j                  | j                               z   }|	d   d   }|	d   d   d   j#                  d      }||vrg ||<   ||   j%                  ||f        |S # t        $ r i cY S w xY w# t
        j                  t        f$ r | j                  |||      cY S w xY w# t        j&                  t(        f$ r Y w xY w)z Search using ripgrep subprocess.rgz--jsonz--globz--T   F)capture_outputtexttimeoutchecktyperU   datarR   r{   rC   line_numberlinesr.   )rE   r   rF   extendr!   r_   runra   r^   rc   stdout
splitlinesjsonloadsr   rJ   rK   rstripr   JSONDecodeErrorKeyError)r[   r$   	base_pathre   rS   cmdresultrh   liner   rR   rV   line_num	line_texts                 r   rb   z.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#7202-L)00(I1FG	  [  	I	. ))+<= 	D&&w	7CC	D& (((3 s6   D3 E BE63E E,E32E36FFc                   	 | j                  |      }|j                         si S t        j                  |      }i }|j                  d      D ]  }|j                         s|rt        |j                  |      s-|j                         j                  | j                  kD  rU	 |j                         }t        |j!                         d      D ]]  \  }	}
|j#                  |
      sdt%        |j'                  | j(                              z   }||vrg ||<   ||   j+                  |	|
f       _  |S # t        $ r i cY S w xY w# t        t        f$ r Y w xY w)z%Search using Python regex (fallback).*r   rC   )rE   r   rF   r1   r2   rglobrI   r;   namerL   st_sizerm   	read_textUnicodeDecodeErrorPermissionError	enumerater   searchr!   rJ   rK   r   )r[   r$   r   re   rS   regexrh   	file_pathcontentr   r   rV   s               r   rc   z-FilesystemFileSearchMiddleware._python_search8  sb   	77	BI !I

7#46 #- 	CI$$& 5inngN ~~''$*B*BB#--/
 #,G,>,>,@!"D C$<<%#&Y-B-B4>>-R)S#SL#7202-L)00(D1ABC%	C2 G  	I	0 '8 s#   D1 #E1D?>D?EEc           	        |dk(  r(dj                  t        |j                                     S |dk(  rWg }t        |j                               D ](  }||   D ]  \  }}|j                  | d| d|          * dj                  |      S |dk(  rUg }t        |j                               D ]&  }t	        ||         }|j                  | d|        ( dj                  |      S dj                  t        |j                                     S )z)Format grep results based on output mode.rj   r.   r   :count)rQ   sortedkeysr   len)r[   rh   rf   r   r   r   r   r   s           r   rd   z3FilesystemFileSearchMiddleware._format_grep_resultsc  s    ..99VGLLN344)#E#GLLN3 C	&-i&8 CNHdLLI;az4&!ABCC 99U##'!E#GLLN3 5	GI./	{!E7345 99U## yy/00r    N)rK   r!   r?   boolr@   intr"   r#   )rR   r!   r"   r   )r$   r!   r   r!   re   rk   r"    dict[str, list[tuple[int, str]]])rh   r   rf   r!   r"   r!   )	__name__
__module____qualname____doc__ro   rE   rb   rc   rd   r)   r    r   r=   r=   W   s    8 ! "y0 y0 	y0
 y0 
y0v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   r3   r   r1   r_   
contextlibr   r   r   pathlibr   typingr   langchain_core.toolsr	   !langchain.agents.middleware.typesr
   r%   r7   r;   r=   __all__r)   r    r   <module>r      sY    #   	   '   % =D*Og1_ g1V	 %r    