
    iG@                    z   d Z ddlmZ ddlZddlmZ ddlmZmZm	Z	m
Z
mZ ddlZerddlmZ ddlm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 ddlmZmZmZmZmZmZ ddl m!Z! ddl"m#Z# ddl$m%Z% ddl&m'Z'm(Z( ddl)m*Z*  G d dejV                        Z, G d dejV                        Z- G d de*      Zg dZ.ddZ/y)z2Base classes and interfaces for FastMCP resources.    )annotationsN)Callable)TYPE_CHECKING	AnnotatedAnyClassVaroverload)Docket)	ExecutionFunctionResource)AnnotationsIcon)Resource)AnyUrl
ConfigDictFieldUrlConstraintsfield_validatormodel_validator)SkipJsonSchema)Self)	AuthCheck)
TaskConfigTaskMeta)FastMCPComponentc                  l     e Zd ZU dZded<   dZded<   dZded<   	 	 d	 	 	 	 	 d fd	Z	 	 	 	 dd
Z xZ	S )ResourceContentaf  Wrapper for resource content with optional MIME type and metadata.

    Accepts any value for content - strings and bytes pass through directly,
    other types (dict, list, BaseModel, etc.) are automatically JSON-serialized.

    Example:
        ```python
        from fastmcp.resources import ResourceContent

        # String content
        ResourceContent("plain text")

        # Binary content
        ResourceContent(b"binary data", mime_type="application/octet-stream")

        # Auto-serialized to JSON
        ResourceContent({"key": "value"})
        ResourceContent(["a", "b", "c"])
        ```
    zstr | bytescontentN
str | None	mime_typedict[str, Any] | Nonemetac                    t        |t              r	|}|xs d}nHt        |t              r	|}|xs d}n/t        j                  |t              j                         }|xs d}t        |   |||       y)u  Create ResourceContent with automatic serialization.

        Args:
            content: The content value. str and bytes pass through directly.
                     Other types (dict, list, BaseModel) are JSON-serialized.
            mime_type: Optional MIME type. Defaults based on content type:
                       str → "text/plain", bytes → "application/octet-stream",
                       other → "application/json"
            meta: Optional metadata dictionary.
        
text/plainapplication/octet-stream)fallbackzapplication/json)r   r!   r#   N)
isinstancestrbytespydantic_coreto_jsondecodesuper__init__)selfr   r!   r#   normalized_content	__class__s        j/Users/bowang/.openclaw/workspace/ChatDev/.venv/lib/python3.12/site-packages/fastmcp/resources/resource.pyr/   zResourceContent.__init__?   sx      gs#.5!1\I'!(!?%?I "/!6!6w!M!T!T!V!7%7I!3ytT    c                   t        | j                  t              r`t        j                  j                  t        |t              rt        |      n|| j                  | j                  xs d| j                        S t        j                  j                  t        |t              rt        |      n|t        j                  | j                        j                         | j                  xs d| j                        S )zConvert to MCP resource contents type.

        Args:
            uri: The URI of the resource (required by MCP types)

        Returns:
            TextResourceContents for str content, BlobResourceContents for bytes
        r%   )uritextmimeType_metar&   )r6   blobr8   r9   )r(   r   r)   mcptypesTextResourceContentsr   r!   r#   BlobResourceContentsbase64	b64encoder-   )r0   r6   s     r3   to_mcp_resource_contentsz(ResourceContent.to_mcp_resource_contents\   s     dllC(9911#-c3#7F3KS\\7<ii	 2   9911#-c3#7F3KS%%dll3::<E+Eii	 2  r4   )NN)r   r   r!   r    r#   r"   )r6   AnyUrl | strreturnz?mcp.types.TextResourceContents | mcp.types.BlobResourceContents)
__name__
__module____qualname____doc____annotations__r!   r#   r/   rA   __classcell__r2   s   @r3   r   r   %   sg    *  Iz "&D
&
 !%&*	UU U $	U:	Hr4   r   c                  j     e Zd ZU dZded<   dZded<   	 d
	 	 	 d fdZe	 	 	 	 dd       Zdd	Z	 xZ
S )ResourceResulta  Canonical result type for resource reads.

    Provides explicit control over resource responses: multiple content items,
    per-item MIME types, and metadata at both the item and result level.

    Accepts:
        - str: Wrapped as single ResourceContent (text/plain)
        - bytes: Wrapped as single ResourceContent (application/octet-stream)
        - list[ResourceContent]: Used directly for multiple items or custom MIME types

    Example:
        ```python
        from fastmcp import FastMCP
        from fastmcp.resources import ResourceResult, ResourceContent

        mcp = FastMCP()

        # Simple string content
        @mcp.resource("data://simple")
        def get_simple() -> ResourceResult:
            return ResourceResult("hello world")

        # Multiple items with custom MIME types
        @mcp.resource("data://items")
        def get_items() -> ResourceResult:
            return ResourceResult(
                contents=[
                    ResourceContent({"key": "value"}),  # auto-serialized to JSON
                    ResourceContent(b"binary data"),
                ],
                meta={"count": 2}
            )
        ```
    list[ResourceContent]contentsNr"   r#   c                J    | j                  |      }t        | 	  ||       y)zCreate ResourceResult.

        Args:
            contents: String, bytes, or list of ResourceContent objects.
            meta: Optional metadata about the resource result.
        )rN   r#   N)_normalize_contentsr.   r/   )r0   rN   r#   
normalizedr2   s       r3   r/   zResourceResult.__init__   s'     --h7
*48r4   c           
     n   t        | t              rt        |       gS t        | t              rt        |       gS t        | t              rMt        |       D ]=  \  }}t        |t              rt        d| dt        |      j                   d|d       | S t        dt        |       j                         )z)Normalize input to list[ResourceContent].z	contents[z] must be ResourceContent, got z. Use ResourceContent(z) to wrap the value.z;contents must be str, bytes, or list[ResourceContent], got )	r(   r)   r   r*   list	enumerate	TypeErrortyperD   )rN   iitems      r3   rP   z"ResourceResult._normalize_contents   s    
 h$#H-..h&#H-..h%$X.4!$8##A3&Ed4jFYFYEZ [//3h6JL  / OI$x.JaJaIbc
 	
r4   c                    | j                   D cg c]  }|j                  |       }}t        j                  j	                  || j
                        S c c}w )zConvert to MCP ReadResourceResult.

        Args:
            uri: The URI of the resource (required by MCP types)

        Returns:
            MCP ReadResourceResult with converted contents
        )rN   r9   )rN   rA   r;   r<   ReadResourceResultr#   )r0   r6   rX   mcp_contentss       r3   to_mcp_resultzResourceResult.to_mcp_result   sU     HL}}U}t55c:}Uyy++!)) , 
 	
 Vs   AN)rN   #str | bytes | list[ResourceContent]r#   r"   )rN   r^   rC   rM   )r6   rB   rC   zmcp.types.ReadResourceResult)rD   rE   rF   rG   rH   r#   r/   staticmethodrP   r\   rI   rJ   s   @r3   rL   rL   w   sa    !F $#"&D
&
 '+959 $9 
5
	
 
*
r4   rL   c                  
    e Zd ZU dZdZded<    ed      Z edd	      Z	d
ed<    edd	      Z
ded<    edd	      Zded<   dZded<   dZded<   edddddddddddd	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 d+d       Z edd      ed,d              Z ed      d-d       Z	 	 d.dZd/d Zed0d1d!       Zed2d"       Z	 d0	 	 	 d3d#Z	 	 	 	 d4d$Zd5d%Zed5d&       Zd6d'Zddd(	 	 	 	 	 	 	 	 	 d7d)Zd8 fd*Z xZS )9r   zBase class for all resources.resourcezClassVar[str]
KEY_PREFIXT)validate_default.zURI of the resource)defaultdescriptionz6Annotated[AnyUrl, UrlConstraints(host_required=False)]r6    zName of the resourcer)   namer%   z!MIME type of the resource contentr!   NzfAnnotated[Annotations | None, Field(description="Optional annotations about the resource's behavior")]r   zAnnotated[SkipJsonSchema[AuthCheck | list[AuthCheck] | None], Field(description='Authorization checks for this resource', exclude=True)]auth)rg   versiontitlere   iconsr!   tagsr   r#   taskrh   c               L    ddl m}  |j                  |||||||||	|
|||      S )Nr   r   )fnr6   rg   ri   rj   re   rk   r!   rl   r   r#   rm   rh   )#fastmcp.resources.function_resourcer   from_function)clsro   r6   rg   ri   rj   re   rk   r!   rl   r   r#   rm   rh   r   s                  r3   rq   zResource.from_function   sF    $	
 .--##
 	
r4   before)modec                    |r|S y)z&Set default MIME type if not provided.r%    )rr   r!   s     r3   set_default_mime_typezResource.set_default_mime_type  s     r4   afterc                    | j                   r	 | S | j                  rt        | j                        | _         | S t        d      )z*Set default name from URI if not provided.z#Either name or uri must be provided)rg   r6   r)   
ValueErrorr0   s    r3   set_default_namezResource.set_default_name  sB     99
 	 XXDHHDI  BCCr4   c                    K   t        d      w)a
  Read the resource content.

        Subclasses implement this to return resource data. Supported return types:
            - str: Text content
            - bytes: Binary content
            - ResourceResult: Full control over contents and result-level meta
        z Subclasses must implement read())NotImplementedErrorr{   s    r3   readzResource.read#  s      ""DEEs   c                    t        |t              r|S t        |t        t        f      r,t        t	        || j
                  | j                        g      S t        |      S )a$  Convert a raw result to ResourceResult.

        This is used in two contexts:
        1. In _read() to convert user function return values to ResourceResult
        2. In tasks_result_handler() to convert Docket task results to ResourceResult

        Handles ResourceResult passthrough and converts raw values using
        ResourceResult's normalization.  When the raw value is a plain
        string or bytes, the resource's own ``mime_type`` is forwarded so
        that ``ui://`` resources (and others with non-default MIME types)
        don't fall back to ``text/plain``.

        The resource's component-level ``meta`` (e.g. ``ui`` metadata for
        MCP Apps CSP/permissions) is propagated to each content item so
        that hosts can read it from the ``resources/read`` response.
        )r!   r#   )r(   rL   r)   r*   r   r!   r#   )r0   	raw_values     r3   convert_resultzResource.convert_result/  sU    " i0
 i#u.! dnn499UV 
 i((r4   c                   K   y wr]   rv   r0   	task_metas     r3   _readzResource._readN  s	     EH   c                   K   y wr]   rv   r   s     r3   r   zResource._readQ  s	     NQr   c                   K   ddl m}  || dd|       d{   }|r|S | j                          d{   }| j                  |      S 7 17 w)a  Server entry point that handles task routing.

        This allows ANY Resource subclass to support background execution by setting
        task_config.mode to "supported" or "required". The server calls this
        method instead of read() directly.

        Args:
            task_meta: If provided, execute as a background task and return
                CreateTaskResult. If None (default), execute synchronously and
                return ResourceResult.

        Returns:
            ResourceResult when task_meta is None.
            CreateTaskResult when task_meta is provided.

        Subclasses can override this to customize task routing behavior.
        For example, FastMCPProviderResource overrides to delegate to child
        middleware without submitting to Docket.
        r   )check_background_taskra   N)	component	task_type	argumentsr   )fastmcp.server.tasks.routingr   r   r   )r0   r   r   task_resultresults        r3   r   zResource._readT  s[     , 	G1jDI
 
  yy{"""6**
 #s   AA
AAAAc                   t        |j                  d| j                        |j                  d| j                        |j                  d| j                        |j                  d| j
                        |j                  d| j                        |j                  d| j                        |j                  d| j                        |j                  d| j                               	      S )
z'Convert the resource to an SDKResource.rg   r6   re   r8   rj   rk   r   r9   )rg   r6   re   r8   rj   rk   r   r9   )
SDKResourcegetrg   r6   re   r!   rj   rk   r   get_meta)r0   	overridess     r3   to_mcp_resourcezResource.to_mcp_resourcev  s     vtyy1eTXX.!mT5E5EF]]:t~~>--4--4!mT5E5EF--
 	
r4   c           
         | j                   j                   d| j                  d| j                  d| j                  d| j
                   d
S )Nz(uri=z, name=z, description=z, tags=))r2   rD   r6   rg   re   rl   r{   s    r3   __repr__zResource.__repr__  sb    ..))*%|7499-~^b^n^n]qqxy}  zC  zC  yD  DE  F  	Fr4   c                t    | j                  t        | j                              }| d| j                  xs d S )z1The globally unique lookup key for this resource.@rf   )make_keyr)   r6   ri   )r0   base_keys     r3   keyzResource.key  s5     ==TXX/1T\\/R011r4   c                    | j                   j                         sy|j                  | j                  | j                  g       y)z<Register this resource with docket for background execution.N)names)task_configsupports_tasksregisterr   r   )r0   dockets     r3   register_with_docketzResource.register_with_docket  s1    ..0		$((4r4   )fn_keytask_keyc               |   K   |xs | j                   }|r||d<     |j                  |fi |        d{   S 7 w)aC  Schedule this resource for background execution via docket.

        Args:
            docket: The Docket instance
            fn_key: Function lookup key in Docket registry (defaults to self.key)
            task_key: Redis storage key for the result
            **kwargs: Additional kwargs passed to docket.add()
        r   N)r   add)r0   r   r   r   kwargs
lookup_keys         r3   add_to_docketzResource.add_to_docket  sC       'txx
$F5M5ZVZZ
5f57777s   3<:<c                ,    t         |          dddz  S )Nra   LocalProvider)zfastmcp.component.typezfastmcp.provider.type)r.   get_span_attributes)r0   r2   s    r3   r   zResource.get_span_attributes  s#    w*,&0%40
 
 	
r4   )ro   zCallable[..., Any]r6   zstr | AnyUrlrg   r    ri   zstr | int | Nonerj   r    re   r    rk   zlist[Icon] | Noner!   r    rl   zset[str] | Noner   zAnnotations | Noner#   r"   rm   zbool | TaskConfig | Nonerh   z"AuthCheck | list[AuthCheck] | NonerC   r   )r!   r    rC   r)   )rC   r   )rC   zstr | bytes | ResourceResult)r   r   rC   rL   r]   )r   NonerC   rL   )r   r   rC   zmcp.types.CreateTaskResult)r   zTaskMeta | NonerC   z+ResourceResult | mcp.types.CreateTaskResult)r   r   rC   r   )rC   r)   )r   r
   rC   r   )
r   r
   r   r    r   r    r   r   rC   r   )rC   zdict[str, Any]) rD   rE   rF   rG   rb   rH   r   model_configr   r6   rg   r!   r   rh   classmethodrq   r   rw   r   r|   r   r   r	   r   r   r   propertyr   r   r   r   rI   rJ   s   @r3   r   r      sN   ' *J*t4LBG!6CC	?  b.DED#E7Is  	    	 	  
   $( "&#' $ $*.&*)-37#
#
 #

 #
 "#
 #
  #
 !#
 #
 #
 (#
 $#
 '#
 1#
  
!#
 #
J [x0  1 '" #
F	%
F)> H HQ Q ,0 +( +	4 +D

 

&F 2 2
5 "#88 	8
 8 8 
8*
 
r4   r   )r   r   rL   c                    ddd}| |v rLddl }ddl}|j                  j                  r|j	                  d|  dt
        d	       dd
lm} t        ||       S t        dt        d|       )z2Deprecated re-exports for backwards compatibility.r   ra   )r   ra   r   Nz
Importing zh from fastmcp.resources.resource is deprecated. Import from fastmcp.resources.function_resource instead.   )
stacklevel)function_resourcezmodule z has no attribute )warningsfastmcpsettingsdeprecation_warningswarnDeprecationWarningfastmcp.resourcesr   getattrAttributeErrorrD   )rg   deprecated_exportsr   r   r   s        r3   __getattr__r     s     /
 !!00MMTF #K L"	   	8($//
78,.@I
JJr4   )rg   r)   rC   r   )0rG   
__future__r   r?   collections.abcr   typingr   r   r   r   r	   	mcp.typesr;   r   r
   docket.executionr   rp   r   pydanticr+   r   r   r   r   r   r   r   r   r   r   pydantic.json_schemar   typing_extensionsr   !fastmcp.server.auth.authorizationr   fastmcp.server.tasks.configr   r   fastmcp.utilities.componentsr   	BaseModelr   rL   __all__r   rv   r4   r3   <module>r      s    8 "  $ D D *D   ' -  0 " 7 < 9Oh(( OdX
X'' X
v_
 _
DKr4   