o
    +i+                     @  s   d Z ddlmZ ddlZddlZddlmZmZ ddlm	Z	m
Z
mZ e	r*ddlmZ ddlmZ ddlmZmZ dd	lmZ dddZdddZdddZG dd deZdgZdS )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)PathPurePosixPath)TYPE_CHECKINGLiteralcast)Any)AgentMiddleware)ToolRuntimetool)AnthropicToolsStatepatternstrreturnlist[str] | Nonec                   sL   d| v r
d| vr
dS g d
 fdd	 z |  W S  t y%   Y dS w )z?Expand brace patterns like ``*.{py,pyi}`` into a list of globs.}{Ncurrentr   r   Nonec                   s   |  d}|dkr|  d S |  d|}|dkrt| d | }| |d d  }| |d | }|s6t|dD ]
} || |  q;d S )Nr   r      ,)findappend
ValueErrorsplit)r   startendprefixsuffixinneroption_expandexpanded g/var/www/html/psymed-ai/venv/lib/python3.10/site-packages/langchain_anthropic/middleware/file_search.pyr#      s   

z)_expand_include_patterns.<locals>._expand)r   r   r   r   )r   r   r%   r"   r&   _expand_include_patterns   s   
r(   boolc                   sn    sdS t  fdddD rdS t }|du rdS z|D ]
}tt| qW dS  tjy6   Y dS w )z/Validate glob pattern used for include filters.Fc                 3  s    | ]}| v V  qd S Nr%   ).0charr'   r%   r&   	<genexpr>>   s    z,_is_valid_include_pattern.<locals>.<genexpr>) 
NT)anyr(   recompilefnmatch	translateerror)r   r$   	candidater%   r'   r&   _is_valid_include_pattern9   s   r8   basenamec                   s&   t |}|sdS t fdd|D S )z8Return True if the basename matches the include pattern.Fc                 3  s    | ]	}t   |V  qd S r*   )r4   )r+   r7   r9   r%   r&   r-   T   s    z)_match_include_pattern.<locals>.<genexpr>)r(   r1   )r9   r   r$   r%   r:   r&   _match_include_patternN   s   r;   c                   @  sB   e Zd ZdZeZddddd	ZdddZdddZdddZ	dS )StateFileSearchMiddlewarea  Provides Glob and Grep search over state-based files.

    This middleware adds two tools that search through virtual files in state:
    - Glob: Fast file pattern matching by file path
    - Grep: Fast content search using regular expressions

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

        agent = create_agent(
            model=model,
            tools=[],
            middleware=[
                StateTextEditorToolMiddleware(),
                StateFileSearchMiddleware(),
            ],
        )
        ```
    text_editor_files)	state_keyr>   r   r   r   c                  sP   | _ t	dd fdd	}t		
	dd fdd}| _| _||g _d
S )zInitialize the search middleware.

        Args:
            state_key: State key to search (default: "text_editor_files").
                Use "memory_files" to search memory tool files.
        /runtime&ToolRuntime[None, AnthropicToolsState]r   r   pathr   c                   s     ||| jS )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.
            )_handle_glob_searchstate)r@   r   rB   selfr%   r&   glob_search   s   z7StateFileSearchMiddleware.__init__.<locals>.glob_searchNfiles_with_matchesinclude
str | Noneoutput_mode1Literal['files_with_matches', 'content', 'count']c                   s     ||||| jS )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.
            )_handle_grep_searchrD   )r@   r   rB   rI   rK   rE   r%   r&   grep_search   s   z7StateFileSearchMiddleware.__init__.<locals>.grep_search)r?   )r@   rA   r   r   rB   r   r   r   )r?   NrH   )r@   rA   r   r   rB   r   rI   rJ   rK   rL   r   r   )r>   r   rG   rN   tools)rF   r>   rG   rN   r%   rE   r&   __init__s   s   z"StateFileSearchMiddleware.__init__r   rB   rD   r   c                 C  s  | dr|nd| }td|| ji }g }| D ]U\}}| |rp|dkr/|dd }	n||kr9t|j}	n| |d rK|t|d d }	nqt|		|}
|
se| dret|		|dd }
|
rp|
||d f q|sudS |jd	d
 dd dd |D }d|S )a  Handle glob search operation.

        Args:
            pattern: The glob pattern to match files against.
            path: The directory to search in.
            state: The current agent state.

        Returns:
            Newline-separated list of matching file paths, sorted by modification
            time (most recently modified first). Returns "No files found" if no
            matches.
        r?   dict[str, Any]r   Nz**/   modified_atzNo files foundc                 S  s   | d S )Nr   r%   )xr%   r%   r&   <lambda>   s    z?StateFileSearchMiddleware._handle_glob_search.<locals>.<lambda>T)keyreversec                 S  s   g | ]\}}|qS r%   r%   )r+   rB   _r%   r%   r&   
<listcomp>   s    zAStateFileSearchMiddleware._handle_glob_search.<locals>.<listcomp>r/   )
startswithr   getr>   itemsr   namelenr   matchr   sortjoin)rF   r   rB   rD   	base_pathfilesmatches	file_path	file_datarelativeis_match
file_pathsr%   r%   r&   rC      s.   

z-StateFileSearchMiddleware._handle_glob_searchrI   rJ   rK   c              
   C  s  | dr|nd| }zt|}W n tjy* } zd| W  Y d}~S d}~ww |r3t|s3dS td|| ji }	i }
|	 D ]9\}}| |sMqC|rZt	|j
}t||sZqCt|d dD ]\}}||r{||
vrrg |
|< |
| ||f qaqC|
sdS | |
|S )	a  Handle grep search operation.

        Args:
            pattern: The regular expression pattern to search for in file contents.
            path: The directory to search in.
            include: File pattern to filter (e.g., "*.js", "*.{ts,tsx}").
            output_mode: Output format.
            state: The current agent state.

        Returns:
            Search results formatted according to output_mode. Returns "No matches
            found" if no results.
        r?   zInvalid regex pattern: NzInvalid include patternrQ   contentr   zNo matches found)rZ   r2   r3   r6   r8   r   r[   r>   r\   r   r]   r;   	enumeratesearchr   _format_grep_results)rF   r   rB   rI   rK   rD   rb   regexerc   resultsre   rf   r9   line_numliner%   r%   r&   rM      s8   



z-StateFileSearchMiddleware._handle_grep_searchrp    dict[str, list[tuple[int, str]]]c              	   C  s   |dkrd t| S |dkr7g }t| D ]}|| D ]\}}|| d| d|  qqd |S |dkr[g }t| D ]}t|| }|| d|  qCd |S d t| S )z)Format grep results based on output mode.rH   r/   rj   :count)ra   sortedkeysr   r^   )rF   rp   rK   linesre   rq   rr   ru   r%   r%   r&   rm   3  s    

z.StateFileSearchMiddleware._format_grep_resultsN)r>   r   r   r   )r   r   rB   r   rD   r   r   r   )r   r   rB   r   rI   rJ   rK   r   rD   r   r   r   )rp   rs   rK   r   r   r   )
__name__
__module____qualname____doc__r   state_schemarP   rC   rM   rm   r%   r%   r%   r&   r<   W   s    
I
;<r<   )r   r   r   r   )r   r   r   r)   )r9   r   r   r   r   r)   )r|   
__future__r   r4   r2   pathlibr   r   typingr   r   r   r   !langchain.agents.middleware.typesr	   langchain.toolsr
   r   .langchain_anthropic.middleware.anthropic_toolsr   r(   r8   r;   r<   __all__r%   r%   r%   r&   <module>   s$    

"
	 |