
    i%W                    h   d Z ddlmZ ddlZddlZddlmZ ddlmZm	Z	m
Z
mZ ddlmZmZ ddlZddlmZmZ ddlmZ erdd	lmZ dd
lmZ ddlmZ ddlmZmZmZ ddlm Z m!Z! ddl"m#Z# ddl$m%Z% ddl&m'Z'm(Z( ddl)m*Z*m+Z+ ddl,m-Z- ddl.m/Z/ ddl0m1Z1 ddZ2ddZ3ddZ4 G d de-      Z G d de      Z5y)z Resource template functionality.    )annotationsN)Callable)TYPE_CHECKINGAnyClassVaroverload)parse_qsunquote)AnnotationsIcon)SkipJsonSchema)Docket)	Execution)ResourceTemplate)Fieldfield_validatorvalidate_call)ResourceResourceResult)resolve_ui_mime_type)	AuthCheck)transform_context_annotationswithout_injected_parameters)
TaskConfigTaskMeta)FastMCPComponent)compress_schema)get_cached_typeadapterc                    t        j                  d|       }|r<|j                  d      j                  d      D ch c]  }|j	                          c}S t               S c c}w )zFExtract query parameter names from RFC 6570 `{?param1,param2}` syntax.z\{\?([^}]+)\}   ,)researchgroupsplitstripset)uri_templatematchps      j/Users/bowang/.openclaw/workspace/ChatDev/.venv/lib/python3.12/site-packages/fastmcp/resources/template.pyextract_query_paramsr,   &   sR    II&5E#(;;q>#7#7#<=#<a	#<==5L >s   Ac                r   t        j                  dd|       }t        j                  d|      }d}|D ]k  }|j                  d      r@|j	                  d      r/|dd }|j	                  d      r|d	d }|d
| dz  }J|d
| dz  }T|t        j
                  |      z  }m t        j                  d| d      S )a  Build regex pattern for URI template, handling RFC 6570 syntax.

    Supports:
    - `{var}` - simple path parameter
    - `{var*}` - wildcard path parameter (captures multiple segments)
    - `{?var1,var2}` - query parameters (ignored in path matching)
    z\{\?[^}]+\} z(\{[^}]+\}){}r    *Nz(?P<z>.+)z>[^/]+)^$)r"   subr%   
startswithendswithescapecompile)templatetemplate_without_querypartspatternpartnames         r+   build_regexr@   .   s      VVNBAHH^%;<EG??3DMM#$6":D}}S!CRyT$t,,T$w//ryy&G  ::'!n%%    c                L   | j                  d      \  }}}t        |      }|j                  |      }|sy|j                         j	                         D ci c]  \  }}|t        |       }	}}|r-t        |      }
t        |      }|
D ]  }||v s||   d   |	|<    |	S c c}}w )zMatch URI against template and extract both path and query parameters.

    Supports RFC 6570 URI templates:
    - Path params: `{var}`, `{var*}`
    - Query params: `{?var1,var2}`
    ?Nr   )	partitionr@   r)   	groupdictitemsr
   r,   r	   )urir(   uri_path_query_stringregexr)   kvparamsquery_param_namesparsed_queryr?   s                r+   match_uri_templaterQ   H   s     !$c 2Ha %EKK!E(-(9(?(?(AB(A1am(AFB 0>-%D|#+D1!4t &
 M Cs   B c                  >    e Zd ZU dZdZded<    ed      Zded<    ed	d
      Zded<    ed      Z	ded<    edd      Z
ded<    eddd      Zded<   d,dZe	 	 	 	 	 	 	 	 	 	 	 d-	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 d.d       Z edd      ed/d              Zd0dZd1dZd2d Ze	 d3	 	 	 	 	 	 	 d4d!       Ze	 	 	 	 	 	 	 	 d5d"       Z	 d3	 	 	 	 	 	 	 d6d#Zd7d$Z	 	 	 	 d8d%Zed9d&       Zed,d'       Zd:d(Zddd)	 	 	 	 	 	 	 	 	 	 	 d;d*Zd< fd+Z xZS )=r   .A template for dynamically creating resources.r:   zClassVar[str]
KEY_PREFIXz<URI template with parameters (e.g. weather://{city}/current))descriptionstrr(   
text/plainz!MIME type of the resource content)defaultrU   	mime_typez#JSON schema for function parametersdict[str, Any]
parametersNz2Optional annotations about the resource's behaviorAnnotations | Noner   z/Authorization checks for this resource templateT)rX   rU   excludez2SkipJsonSchema[AuthCheck | list[AuthCheck] | None]authc           
         | j                   j                   d| j                  d| j                  d| j                  d| j
                   d
S )Nz(uri_template=z, name=z, description=z, tags=))	__class____name__r(   r?   rU   tags)selfs    r+   __repr__zResourceTemplate.__repr__~   s~    ..))*.9J9J8MWUYU^U^Taaopt  qA  qA  pD  DK  LP  LU  LU  KV  VW  X  	XrA   c                F    t         j                  | |||||||||	|
||      S )Nfnr(   r?   versiontitlerU   iconsrY   rc   r   metataskr^   )FunctionResourceTemplatefrom_functionrg   s                r+   ro   zResourceTemplate.from_function   sC      (55%## 6 
 	
rA   beforemodec                    |r|S y)z&Set default MIME type if not provided.rW    )clsrY   s     r+   set_default_mime_typez&ResourceTemplate.set_default_mime_type   s     rA   c                .    t        || j                        S )z5Check if URI matches template and extract parameters.)rQ   r(   )rd   rG   s     r+   matcheszResourceTemplate.matches   s    !#t'8'899rA   c                    K   t        d      w)Read the resource content.z>Subclasses must implement read() or override create_resource()NotImplementedError)rd   	argumentss     r+   readzResourceTemplate.read   s     !L
 	
   c                <    t        |t              r|S t        |      S )an  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.
        )
isinstancer   )rd   	raw_values     r+   convert_resultzResourceTemplate.convert_result   s!     i0 i((rA   c                   K   y wNrt   rd   rG   rN   	task_metas       r+   _readzResourceTemplate._read            c                   K   y wr   rt   r   s       r+   r   zResourceTemplate._read         &)r   c                   K   ddl m}  || d||       d{   }|r|S | j                  ||       d{   }|j                          d{   }| j	                  |      S 7 K7 /7 w)a  Server entry point that handles task routing.

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

        Args:
            uri: The concrete URI being read
            params: Template parameters extracted from the URI
            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, FastMCPProviderResourceTemplate overrides to delegate to child
        middleware without submitting to Docket.
        r   check_background_taskr:   	component	task_typer}   r   N)fastmcp.server.tasks.routingr   create_resourcer~   r   )rd   rG   rN   r   r   task_resultresourceresults           r+   r   zResourceTemplate._read   st     0 	G1jFi
 
  --c6::}}&""6**
 ;&s1   A*A$A*A&A*A(A*&A*(A*c                    K   t        d      w)zCreate a resource from the template with the given parameters.

        The base implementation does not support background tasks.
        Use FunctionResourceTemplate for task support.
        z[Subclasses must implement create_resource(). Use FunctionResourceTemplate for task support.r{   )rd   rG   rN   s      r+   r   z ResourceTemplate.create_resource   s      "=
 	
r   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 )
z8Convert the resource template to an SDKResourceTemplate.r?   uriTemplaterU   mimeTyperj   rk   r   _meta)r?   r   rU   r   rj   rk   r   r   )
SDKResourceTemplategetr?   r(   rU   rY   rj   rk   r   get_meta)rd   	overridess     r+   to_mcp_templatez ResourceTemplate.to_mcp_template   s     #vtyy1!mT5F5FG!mT5E5EF]]:t~~>--4--4!mT5E5EF--
 	
rA   c                t     | |j                   |j                  |j                  |j                  xs di       S )zJCreates a FastMCP ResourceTemplate from a raw MCP ResourceTemplate object.rW   )r(   r?   rU   rY   r[   )r   r?   rU   r   )ru   mcp_templates     r+   from_mcp_templatez"ResourceTemplate.from_mcp_template  s=    
 %11""$00"++;|
 	
rA   c                b    | j                  | j                        }| d| j                  xs d S )z1The globally unique lookup key for this template.@r.   )make_keyr(   ri   )rd   base_keys     r+   keyzResourceTemplate.key  s3     ==!2!231T\\/R011rA   c                    | j                   j                         sy|j                  | j                  | j                  g       y)z<Register this template with docket for background execution.Nnames)task_configsupports_tasksregisterr~   r   rd   dockets     r+   register_with_docketz%ResourceTemplate.register_with_docket$  s1    ..0		$((4rA   fn_keytask_keyc               ~   K   |xs | j                   }|r||d<     |j                  |fi ||       d{   S 7 w)ak  Schedule this template for background execution via docket.

        Args:
            docket: The Docket instance
            params: Template parameters
            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rd   r   rN   r   r   kwargs
lookup_keys          r+   add_to_docketzResourceTemplate.add_to_docket*  sE     $ 'txx
$F5M5ZVZZ
5f5f====   4=;=c                ,    t         |          dddz  S )Nresource_templateLocalProvider)zfastmcp.component.typezfastmcp.provider.type)superget_span_attributes)rd   ra   s    r+   r   z$ResourceTemplate.get_span_attributesA  s#    w*,&9%40
 
 	
rA   )returnrV   NNNNNNNNNNNrh   zCallable[..., Any]r(   rV   r?   
str | Noneri   zstr | int | Nonerj   r   rU   r   rk   zlist[Icon] | NonerY   r   rc   zset[str] | Noner   r\   rl   dict[str, Any] | Nonerm   zbool | TaskConfig | Noner^   z"AuthCheck | list[AuthCheck] | Noner   rn   )rY   r   r   rV   )rG   rV   r   r   r}   rZ   r   str | bytes | ResourceResult)r   r   r   r   r   rG   rV   rN   rZ   r   Noner   r   rG   rV   rN   rZ   r   r   r   zmcp.types.CreateTaskResultrG   rV   rN   rZ   r   zTaskMeta | Noner   z+ResourceResult | mcp.types.CreateTaskResultrG   rV   rN   rZ   r   r   )r   r   r   r   )r   r   r   r   r   r   r   r   r   r   rN   rZ   r   r   r   r   r   r   r   r   )r   rZ   ) rb   
__module____qualname____doc__rT   __annotations__r   r(   rY   r[   r   r^   re   staticmethodro   r   classmethodrv   rx   r~   r   r   r   r   r   r   propertyr   r   r   r   __classcell__)ra   s   @r+   r   r   g   s   8 *J*RL#  *MIs  "'9"J  ',"V'K#  @EE@D
< X   $( "&#' $ $*.&*)-37


 
 "	

 
  
 !
 
 
 (
 $
 '
 1
 
"
 
> [x0  1:
)  BF .;?	  )) .);C)	#) )
 NR$+$+ .$+;J$+	4$+L	


 

& 

 

 2 2
5 "#>> >
 > > > 
>.
 
rA   r   c                     e Zd ZU dZded<   e	 d	 	 	 	 	 	 	 dd       Ze	 	 	 	 	 	 	 	 dd       Z	 d	 	 	 	 	 	 	 ddZddZdd	Zdd
Z	ddd	 	 	 	 	 	 	 	 	 	 	 ddZ
e	 	 	 	 	 	 	 	 	 	 	 d	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 dd       Zy)rn   rS   z"SkipJsonSchema[Callable[..., Any]]rh   Nc                   K   y wr   rt   r   s       r+   r   zFunctionResourceTemplate._readM  r   r   c                   K   y wr   rt   r   s       r+   r   zFunctionResourceTemplate._readR  r   r   c                   K   ddl m}  || d||       d{   }|r|S | j                  |       d{   }| j                  |      S 7 37 w)a  Optimized server entry point that skips ephemeral resource creation.

        For FunctionResourceTemplate, we can call read() directly instead of
        creating a temporary resource, which is more efficient.

        Args:
            uri: The concrete URI being read
            params: Template parameters extracted from the URI
            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.
        r   r   r:   r   Nr}   )r   r   r~   r   )rd   rG   rN   r   r   r   r   s          r+   r   zFunctionResourceTemplate._readW  s`     & 	G1jFi
 
  yy6y22""6**
 3s   AAAAAAc           
         K   d fd}t        j                  || j                   j                   j                   j
                   j                   j                        S w)z>Create a resource from the template with the given parameters.c                 H   K   j                         d {   } | S 7 w)Nr   )r~   )r   rN   rd   s    r+   resource_read_fnzBFunctionResourceTemplate.create_resource.<locals>.resource_read_fny  s$     99v966FM 7s   " ")rh   rG   r?   rU   rY   rc   rm   r^   )r   r   )r   ro   r?   rU   rY   rc   r   r^   )rd   rG   rN   r   s   ` ` r+   r   z(FunctionResourceTemplate.create_resourcev  sU     	
 %%((nn!!	
 		
s   A!A%c                  K   |j                         }t        j                  | j                        }t	        |j                               D ]  \  }}||j                  v st        |t              s&|j                  |   }|j                  }|t        j                  j                  u s|t        u rf	 |t        u rt        |      ||<   n4|t        u rt        |      ||<   n|t        u r|j                         dv ||<     | j                  di |}t        j$                  |      r
| d{   }|S # t         t"        f$ r Y w xY w7 w)rz   )true1yesNrt   )copyinspect	signaturerh   listrF   r[   r   rV   
annotation	Parameteremptyintfloatboollower
ValueErrorAttributeErrorisawaitable)	rd   r}   r   sig
param_nameparam_valueparamr   r   s	            r+   r~   zFunctionResourceTemplate.read  s0     !('+FLLN';#JS^^+
;0Lz2"--
!2!2!8!88J#<M!S(-0-=z*#u,-2;-?z*#t+-8->->-@DX-Xz* (<( "6"v&!\F #N3  "sD   AE	 E	1A E	2AD2=.E	+E,E	2EE	EE	c                    | j                   j                         sy|j                  | j                  | j                  g       y)zRegister this template with docket for background execution.

        FunctionResourceTemplate registers the underlying function, which has the
        user's Depends parameters for docket to resolve.
        Nr   )r   r   r   rh   r   r   s     r+   r   z-FunctionResourceTemplate.register_with_docket  s3     ..0z2rA   r   c               ~   K   |xs | j                   }|r||d<     |j                  |fi |di | d{   S 7 w)a  Schedule this template for background execution via docket.

        FunctionResourceTemplate splats the params dict since .fn expects **kwargs.

        Args:
            docket: The Docket instance
            params: Template parameters
            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   Nrt   r   r   s          r+   r   z&FunctionResourceTemplate.add_to_docket  sH     ( 'txx
$F5M5ZVZZ
5f5?????r   c                   |xs% t        |dd      xs |j                  j                  }|dk(  rt        d      t	        j
                  |      }|j                  j                         D ]4  }|j                  t        j                  j                  k(  s+t        d       t        t        j                  d|            }t        |      }||z  }|st        d      t        |      }t	        j
                  |      }t        |j                  j!                               }|D ch c]k  }|j                  |   j"                  t        j                  j$                  u r6|j                  |   j                  t        j                  j&                  k7  r|m }}|D ch c]k  }|j                  |   j"                  t        j                  j$                  ur6|j                  |   j                  t        j                  j&                  k7  r|m }}|r||z
  }|rt        d| d	      |j)                  |      st        d
| d|       t+        d |j                  j                         D              s"|j)                  |      st        d| d|       |xs t	        j,                  |      }|t/        d      }n(t1        |t2              rt/        j4                  |      }n|}|j7                  ||       t	        j8                  |      s|j:                  }t1        |t<              r|j>                  }tA        |      }t        |      }tC        |      }|jE                         }tG        |d      }tI        |      }tK        ||      } | |||tM        |      nd||||xs d|||	xs
 t               |
|||      S c c}w c c}w )z"Create a template from a function.rb   Nz<lambda>z,You must provide a name for lambda functionsz<Functions with *args are not supported as resource templatesz{(\w+)(?:\*)?}z0URI template must contain at least one parameterzQuery parameters z9 must be optional function parameters with default valueszRequired function arguments z- must be a subset of the URI path parameters c              3  j   K   | ]+  }|j                   t        j                  j                  k(   - y wr   )kindr   r   VAR_KEYWORD).0r   s     r+   	<genexpr>z9FunctionResourceTemplate.from_function.<locals>.<genexpr>  s-      
0 JJ'++7770s   13zURI parameters z- must be a subset of the function arguments: 	forbiddenrq   T)prune_titlesrW   )r(   r?   ri   rj   rU   rk   rY   rh   r[   rc   r   rl   r   r^   )'getattrra   rb   r   r   r   r[   valuesr   r   VAR_POSITIONALr'   r"   findallr,   r   keysrX   r   r   issubsetanygetdocr   r   r   	from_boolvalidate_function	isroutine__call__r   __func__r   r   json_schemar   r   r   rV   )ru   rh   r(   r?   ri   rj   rU   rk   rY   rc   r   rl   rm   r^   	func_namer   r   path_paramsquery_paramsall_uri_params
wrapper_fnuser_sigfunc_paramsr*   required_paramsoptional_paramsinvalid_query_paramsr   type_adapterr[   resolved_mimes                                  r+   ro   z&FunctionResourceTemplate.from_function  s   & RGB
D9RR\\=R=R	
"KLL #^^**,EzzW..=== R  - "**%6EF+L9$|3OPP 14
$$Z0(--2245
 !
 ""1%--1B1B1H1HH##A&++w/@/@/L/LL   	 
 !
 ""1%--W5F5F5L5LL##A&++w/@/@/L/LL   	 
 #//#A # '(<'==vw 
 ''4..??lmxlyz 
  
..0
 
 "**;7 %n%55bcnbop  "7W^^B%7 <$+6Kd#$..t4KK%%b)4   $Bb,'B +2.04
-j9!--/
$ZdC
 :& -\9E%$+$7CLT##3|!##
 	
M

s   #A0N8A0N=r   r   r   r   r   r   r   r   r   r   )rb   r   r   r   r   r   r   r   r~   r   r   r   ro   rt   rA   r+   rn   rn   H  s   8**BF .;?	  )) .);C)	#) )
 NR++ .+;J+	4+>
&>3 "#@@ @
 @ @ @ 
@2 
  $( "&#' $ $*.&*)-37B
B
 B
 	B

 "B
 B
  B
 !B
 B
 B
 (B
 $B
 'B
 1B
 
"B
 B
rA   rn   )r(   rV   r   zset[str])r:   rV   r   z
re.Pattern)rG   rV   r(   rV   r   zdict[str, str] | None)6r   
__future__r   r   r"   collections.abcr   typingr   r   r   r   urllib.parser	   r
   	mcp.typesmcpr   r   pydantic.json_schemar   r   r   docket.executionr   r   r   pydanticr   r   r   fastmcp.resources.resourcer   r   fastmcp.server.appsr   !fastmcp.server.auth.authorizationr   fastmcp.server.dependenciesr   r   fastmcp.server.tasks.configr   r   fastmcp.utilities.componentsr   fastmcp.utilities.json_schemar   fastmcp.utilities.typesr   r,   r@   rQ   rn   rt   rA   r+   <module>r,     s    & "  	 $ 9 9 *  ' /* =  @ 4 7 = 9 9 :&4>^
' ^
BF
/ F
rA   