
    iD                         d Z ddlmZ ddlZddlmZ ddlmZ ddlm	Z	 ddl
mZ ddlmZ dd	lmZ dd
lmZ ddlmZ ddlmZ ddlmZ ddlmZ  ee      Z G d de      Zy)a  FileSystemProvider for filesystem-based component discovery.

FileSystemProvider scans a directory for Python files, imports them, and
registers any Tool, Resource, ResourceTemplate, or Prompt objects found.

Components are created using the standalone decorators from fastmcp.tools,
fastmcp.resources, and fastmcp.prompts:

Example:
    ```python
    # In mcp/tools.py
    from fastmcp.tools import tool

    @tool
    def greet(name: str) -> str:
        return f"Hello, {name}!"

    # In main.py
    from pathlib import Path

    from fastmcp import FastMCP
    from fastmcp.server.providers import FileSystemProvider

    mcp = FastMCP("MyServer", providers=[FileSystemProvider(Path(__file__).parent / "mcp")])
    ```
    )annotationsN)Sequence)Path)Prompt)Resource)ResourceTemplate)discover_and_import)LocalProvider)Tool)FastMCPComponent)
get_logger)VersionSpecc                       e Zd ZdZ	 	 d	 	 	 	 	 d fdZddZddZddZd fdZ	 d	 	 	 	 	 d fdZ	d fdZ
	 d	 	 	 	 	 d fd	Zd fd
Z	 d	 	 	 	 	 d fdZd fdZ	 d	 	 	 	 	 d fdZddZ xZS )FileSystemProvidera  Provider that discovers components from the filesystem.

    Scans a directory for Python files and registers any Tool, Resource,
    ResourceTemplate, or Prompt objects found. Components are created using
    the standalone decorators:
    - @tool from fastmcp.tools
    - @resource from fastmcp.resources
    - @prompt from fastmcp.prompts

    Args:
        root: Root directory to scan. Defaults to current directory.
        reload: If True, re-scan files on every request (dev mode).
            Defaults to False (scan once at init, cache results).

    Example:
        ```python
        # In mcp/tools.py
        from fastmcp.tools import tool

        @tool
        def greet(name: str) -> str:
            return f"Hello, {name}!"

        # In main.py
        from pathlib import Path

        from fastmcp import FastMCP
        from fastmcp.server.providers import FileSystemProvider

        # Path relative to this file
        mcp = FastMCP("MyServer", providers=[FileSystemProvider(Path(__file__).parent / "mcp")])

        # Dev mode - re-scan on every request
        mcp = FastMCP("MyServer", providers=[FileSystemProvider(Path(__file__).parent / "mcp", reload=True)])
        ```
    c                    t         |   d       t        |      j                         | _        || _        d| _        i | _        d | _        | j                          y )Nreplace)on_duplicateF)
super__init__r   resolve_root_reload_loaded_warned_files_reload_lock_load_components)selfrootreload	__class__s      s/Users/bowang/.openclaw/workspace/ChatDev/.venv/lib/python3.12/site-packages/fastmcp/server/providers/filesystem.pyr   zFileSystemProvider.__init__U   sW    
 	i0$Z'')
 1315 	    c                ~   | j                   r| j                  j                          t        | j                        }|j
                  j                         D ]m  \  }}	 |j                         j                  }| j                  j                  |      }|||k7  sDt        j                  d| d|        || j                  |<   o |j                  D ch c]  \  }}|	 }}}|D ]  }| j                  j                  |d         |j                  D ]  \  }}		 | j!                  |	        d| _         t        j+                  dt-        | j                         d	| j                          y# t        $ r d}Y w xY wc c}}w # t"        $ r. t        j%                  dt'        |	dt)        |	            |       Y w xY w)
z9Discover and register all components from the filesystem.g        NzFailed to import z: zFailed to register %s from %snameTzFileSystemProvider loaded z components from )r   _componentsclearr	   r   failed_filesitemsstatst_mtimeOSErrorr   getloggerwarning
componentspop_register_component	Exception	exceptiongetattrreprdebuglen)
r   result	file_patherrorcurrent_mtimelast_warned_mtimefp_successful_files	components
             r!   r   z#FileSystemProvider._load_componentsg   s    <<""$$TZZ0 !' 3 3 9 9 ;Iu$ ) 0 9 9
 !% 2 2 6 6y A (,=,N!29+RwGH0=""9- !< -3,=,=>,=52qB,=>"B""2t, # %+$5$5 Iy((3 %6 (T-=-=)>(??PQUQ[Q[P\]	
3  $ #$ ?    3IvtI?s*   E-E?F-E<;E<4F<;F<c                R   t        |t              r| j                  |       yt        |t              r| j	                  |       yt        |t
              r| j                  |       yt        |t              r| j                  |       yt        j                  dt        |             y)z.Register a single component based on its type.z#Ignoring unknown component type: %rN)
isinstancer   add_toolr   add_templater   add_resourcer   
add_promptr-   r6   type)r   r@   s     r!   r1   z&FileSystemProvider._register_component   sr    i&MM)$	#34i(	8,i(	6*OOI&LL>YPr"   c                  K   | j                   s| j                  ry| j                  t        j                         | _        | j                  4 d{    | j                   s| j                  s't        j
                  | j                         d{    ddd      d{    y7 T7 7 	# 1 d{  7  sw Y   yxY ww)zEnsure components are loaded, reloading if in reload mode.

        Uses a lock to serialize concurrent reload operations and runs
        filesystem I/O off the event loop using asyncio.to_thread.
        N)r   r   r   asyncioLock	to_threadr   r   s    r!   _ensure_loadedz!FileSystemProvider._ensure_loaded   s      || $ 'D$$$||4<<''(=(=>>> %$$ ? %$$$sZ   ACB&C;B,B(B,C B*!C(B,*C,B>2B53B>:Cc                p   K   | j                          d{    t        | 	          d{   S 7 7 w)z.Return all tools, reloading if in reload mode.N)rM   r   _list_toolsr   r    s    r!   rO   zFileSystemProvider._list_tools   s3     !!###W(*** 	$*   626466c                t   K   | j                          d{    t        | 	  ||       d{   S 7 7 w)z0Get a tool by name, reloading if in reload mode.N)rM   r   	_get_toolr   r$   versionr    s      r!   rS   zFileSystemProvider._get_tool   s9      !!###W&tW555 	$5   848688c                p   K   | j                          d{    t        | 	          d{   S 7 7 w)z2Return all resources, reloading if in reload mode.N)rM   r   _list_resourcesrP   s    r!   rX   z"FileSystemProvider._list_resources   s3     !!###W,... 	$.rQ   c                t   K   | j                          d{    t        | 	  ||       d{   S 7 7 w)z3Get a resource by URI, reloading if in reload mode.N)rM   r   _get_resourcer   urirU   r    s      r!   rZ   z FileSystemProvider._get_resource   s9      !!###W*3888 	$8rV   c                p   K   | j                          d{    t        | 	          d{   S 7 7 w)z;Return all resource templates, reloading if in reload mode.N)rM   r   _list_resource_templatesrP   s    r!   r^   z+FileSystemProvider._list_resource_templates   s3     !!###W5777 	$7rQ   c                t   K   | j                          d{    t        | 	  ||       d{   S 7 7 w)z5Get a resource template, reloading if in reload mode.N)rM   r   _get_resource_templater[   s      r!   r`   z)FileSystemProvider._get_resource_template   s9      !!###W3CAAA 	$ArV   c                p   K   | j                          d{    t        | 	          d{   S 7 7 w)z0Return all prompts, reloading if in reload mode.N)rM   r   _list_promptsrP   s    r!   rb   z FileSystemProvider._list_prompts   s3     !!###W*,,, 	$,rQ   c                t   K   | j                          d{    t        | 	  ||       d{   S 7 7 w)z2Get a prompt by name, reloading if in reload mode.N)rM   r   _get_promptrT   s      r!   rd   zFileSystemProvider._get_prompt   s9      !!###W(w777 	$7rV   c                <    d| j                   d| j                   dS )NzFileSystemProvider(root=z	, reload=))r   r   rL   s    r!   __repr__zFileSystemProvider.__repr__   s    )$**yaPPr"   ).F)r   z
str | Pathr   boolreturnNone)rj   rk   )r@   r   rj   rk   )rj   zSequence[Tool])N)r$   strrU   VersionSpec | Nonerj   zTool | None)rj   zSequence[Resource])r\   rl   rU   rm   rj   zResource | None)rj   zSequence[ResourceTemplate])r\   rl   rU   rm   rj   zResourceTemplate | None)rj   zSequence[Prompt])r$   rl   rU   rm   rj   zPrompt | None)rj   rl   )__name__
__module____qualname____doc__r   r   r1   rM   rO   rS   rX   rZ   r^   r`   rb   rd   rg   __classcell__)r    s   @r!   r   r   /   s    #N      
	 $'
RQ?(+ 8<66"46	6/ 7;99!39	98 7;BB!3B	 B- 8<88"48	8Qr"   r   )rq   
__future__r   rI   collections.abcr   pathlibr   fastmcp.prompts.promptr   fastmcp.resources.resourcer   fastmcp.resources.templater   -fastmcp.server.providers.filesystem_discoveryr	   'fastmcp.server.providers.local_providerr
   fastmcp.tools.toolr   fastmcp.utilities.componentsr   fastmcp.utilities.loggingr   fastmcp.utilities.versionsr   rn   r-   r    r"   r!   <module>r      sM   6 #  $  ) / 7 M A # 9 0 2	H	sQ sQr"   