
    $j]                       d Z ddlm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
mZmZ ddlmZ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'm(Z( ddl)m*Z*m+Z+ ddl,m-Z- ddl.m/Z/ ddl0m1Z1 ddl2m3Z3 d'dZ4d(dZ5d)dZ6d*d"Z7 G d# d$e-          Z G d% d&e          Z8dS )+z Resource template functionality.    )annotationsN)Callable)TYPE_CHECKINGAnyClassVaroverload)parse_qsquoteunquote)AnnotationsIcon)SkipJsonSchema)Docket)	Execution)ResourceTemplate)Fieldfield_validatorvalidate_call)ResourceResourceResult)	AuthCheck)transform_context_annotationswithout_injected_parameters)
TaskConfigTaskMeta)FastMCPComponent)compress_schema)resolve_ui_mime_type)get_cached_typeadapteruri_templatestrreturnset[str]c                    t          j        d|           }|r2d |                    d                              d          D             S t	                      S )zFExtract query parameter names from RFC 6570 `{?param1,param2}` syntax.\{\?([^}]+)\}c                6    h | ]}|                                 S  strip).0ps     b/home/rurouni/.hermes/hermes-agent/venv/lib/python3.11/site-packages/fastmcp/resources/template.py	<setcomp>z'extract_query_params.<locals>.<setcomp>+   s     ===a		===       ,)researchgroupsplitset)r    matchs     r,   extract_query_paramsr7   '   sQ    I&55E >==5;;q>>#7#7#<#<====55Lr.   templatere.Pattern[str] | Nonec                   t          j        dd|           }t          j        d|          }d}|D ]}|                    d          rR|                    d          r=|dd         }|                    d          r|d	d         }|d
| dz  }_|d
| dz  }i|t          j        |          z  }	 t          j        d| d          S # t           j        $ r Y d	S w xY w)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)

    Returns None if the template produces an invalid regex (e.g. parameter
    names with hyphens, leading digits, or duplicates from a remote server).
    z\{\?[^}]+\} z(\{[^}]+\}){}r/   *Nz(?P<z>.+)z>[^/]+)^$)r1   subr4   
startswithendswithescapecompileerror)r8   template_without_querypartspatternpartnames         r,   build_regexrM   /   s     VNBAAH^%;<<EG 	' 	'??3 	'DMM#$6$6 	'":D}}S!! 0CRCy,$,,,,/$////ry&GGz.g...)))8   tts   2C
 
CCuridict[str, str] | Nonec                d   |                      d          \  }}}t          |          }|dS |                    |          }|sdS d |                                                                D             }|r8t          |          }t          |          }	|D ]}
|
|	v r|	|
         d         ||
<   |S )zMatch URI against template and extract both path and query parameters.

    Supports RFC 6570 URI templates:
    - Path params: `{var}`, `{var*}`
    - Query params: `{?var1,var2}`
    ?Nc                4    i | ]\  }}|t          |          S r'   )r   )r*   kvs      r,   
<dictcomp>z&match_uri_template.<locals>.<dictcomp>a   s$    BBB1aBBBr.   r   )	partitionrM   r6   	groupdictitemsr7   r	   )rN   r    uri_path_query_stringregexr6   paramsquery_param_namesparsed_queryrL   s              r,   match_uri_templater`   O   s     !$c 2 2Ha %%E}tKK!!E tBB(9(9(?(?(A(ABBBF  50>>--% 	5 	5D|##+D1!4tMr.   r]   dict[str, Any]c                    | }                                 D ]H\  }}t          |          }|                    d| d|          }|                    d| d|          }Id
fd}t          j        d	||          }|S )u   Expand a URI template with parameters — inverse of `match_uri_template`.

    Supports the same RFC 6570 subset:
    - Path params: `{var}`, `{var*}`
    - Query params: `{?var1,var2}`
    r<   r=   z*}r6   re.Match[str]r"   r!   c                    d |                      d                              d          D             }fd|D             }|rdd                    |          z   S dS )Nc                6    g | ]}|                                 S r'   r(   )r*   ns     r,   
<listcomp>zDexpand_uri_template.<locals>._expand_query_block.<locals>.<listcomp>   s     >>>q>>>r.   r/   r0   c           
         g | ]:}|v t          |           d t          t          |                              ;S )=)r
   r!   )r*   rL   r]   s     r,   rg   zDexpand_uri_template.<locals>._expand_query_block.<locals>.<listcomp>   sR     
 
 
v~~ T{{77U3vd|#4#45577~~r.   rQ   &r;   )r3   r4   join)r6   namesrI   r]   s      r,   _expand_query_blockz0expand_uri_template.<locals>._expand_query_block   sz    >>EKKNN$8$8$=$=>>>
 
 
 

 
 

  	)%((rr.   r%   )r6   rc   r"   r!   )rX   r!   replacer1   rB   )r    r]   resultkeyvalue	value_strrm   s    `     r,   expand_uri_templaters   p   s     F llnn : :
UJJ	Si88Sy99	 	 	 	 	 	 V$&96BBFMr.   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<   dVdZe	 	 	 	 	 	 	 	 	 	 	 dWdXd-            Z edd./          edYd0                        ZdZd2Zd[d5Zd\d9Ze	 d]d^d=            Zed_d@            Z	 d]d`dCZdadEZdbdHZedcdJ            ZedVdK            ZdddNZdddOdedTZdf fdUZ xZS )gr   .A template for dynamically creating resources.r8   zClassVar[str]
KEY_PREFIXz<URI template with parameters (e.g. weather://{city}/current))descriptionr!   r    
text/plainz!MIME type of the resource content)defaultrw   	mime_typez#JSON schema for function parametersra   
parametersNz2Optional annotations about the resource's behaviorAnnotations | Noner   z/Authorization checks for this resource templateT)ry   rw   excludez2SkipJsonSchema[AuthCheck | list[AuthCheck] | None]authr"   c           
     `    | j         j         d| j        d| j        d| j        d| j         d
S )Nz(uri_template=z, name=z, description=z, tags=))	__class____name__r    rL   rw   tags)selfs    r,   __repr__zResourceTemplate.__repr__   su    .)  X  X9J  X  XUYU^  X  Xpt  qA  X  X  LP  LU  X  X  X  	Xr.   fnCallable[..., Any]rL   
str | Noneversionstr | int | Nonetitlerw   iconslist[Icon] | Noner   set[str] | Nonemetadict[str, Any] | Nonetaskbool | TaskConfig | None"AuthCheck | list[AuthCheck] | NoneFunctionResourceTemplatec                P    t                               | |||||||||	|
||          S )Nr   r    rL   r   r   rw   r   rz   r   r   r   r   r~   )r   from_functionr   s                r,   r   zResourceTemplate.from_function   sH      (55%## 6 
 
 	
r.   beforemodec                    |r|S dS )z&Set default MIME type if not provided.rx   r'   )clsrz   s     r,   set_default_mime_typez&ResourceTemplate.set_default_mime_type   s      	|r.   rN   c                ,    t          || j                  S )z5Check if URI matches template and extract parameters.)r`   r    )r   rN   s     r,   matcheszResourceTemplate.matches   s    !#t'8999r.   	argumentsstr | bytes | ResourceResultc                $   K   t          d          )Read the resource content.z>Subclasses must implement read() or override create_resource()NotImplementedError)r   r   s     r,   readzResourceTemplate.read   s      !L
 
 	
r.   	raw_valuer   r   c                N    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   )r   r   s     r,   convert_resultzResourceTemplate.convert_result   s,     i00 	 i(((r.   r]   	task_metaNonec                
   K   d S Nr'   r   rN   r]   r   s       r,   _readzResourceTemplate._read          r.   r   mcp.types.CreateTaskResultc                
   K   d S r   r'   r   s       r,   r   zResourceTemplate._read          &)Sr.   TaskMeta | None+ResourceResult | mcp.types.CreateTaskResultc                   K   ddl m}  || d||           d{V }|r|S |                     ||           d{V }|                                 d{V }|                     |          S )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_taskr8   	component	task_typer   r   N)fastmcp.server.tasks.routingr   create_resourcer   r   )r   rN   r]   r   r   task_resultresourcero   s           r,   r   zResourceTemplate._read   s      0 	GFFFFF11jFi
 
 
 
 
 
 
 
 
  	 --c6::::::::}}&&&&&&""6***r.   r   c                $   K   t          d          )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   )r   rN   r]   s      r,   r   z ResourceTemplate.create_resource  s       "=
 
 	
r.   	overridesSDKResourceTemplatec                   t          |                    d| j                  |                    d| j                  |                    d| j                  |                    d| j                  |                    d| j                  |                    d| j                  |                    d| j                  |                    d| 	                                          	          S )
z8Convert the resource template to an SDKResourceTemplate.rL   uriTemplaterw   mimeTyper   r   r   _meta)rL   r   rw   r   r   r   r   r   )
r   getrL   r    rw   rz   r   r   r   get_meta)r   r   s     r,   to_mcp_templatez ResourceTemplate.to_mcp_template'  s     #vty11!mT5FGG!mT5EFF]]:t~>>--44--44!mT5EFF-- 
 
 
 	
r.   mcp_templatec                N     | |j         |j        |j        |j        pdi           S )zJCreates a FastMCP ResourceTemplate from a raw MCP ResourceTemplate object.rx   )r    rL   rw   rz   r{   )r   rL   rw   r   )r   r   s     r,   from_mcp_templatez"ResourceTemplate.from_mcp_template:  s=    
 s%1"$0"+;|
 
 
 	
r.   c                R    |                      | j                  }| d| j        pd S )z1The globally unique lookup key for this template.@r;   )make_keyr    r   )r   base_keys     r,   rp   zResourceTemplate.keyG  s3     ==!23311T\/R111r.   docketr   c                    | j                                         sdS |                    | j        | j        g           dS z<Register this template with docket for background execution.N)rl   )task_configsupports_tasksregisterr   rp   r   r   s     r,   register_with_docketz%ResourceTemplate.register_with_docketM  s@    ..00 	F	$(44444r.   fn_keytask_keyr   r   kwargsr   c               `   K   |p| j         }|r||d<     |j        |fi ||           d{V S )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()
        rp   Nrp   addr   r   r]   r   r   r   
lookup_keys          r,   add_to_docketzResourceTemplate.add_to_docketS  s[      $ 'tx
 	%$F5M5ZVZ
55f55f=========r.   c                P    t                                                      dddz  S )Nresource_templateLocalProvider)zfastmcp.component.typezfastmcp.provider.type)superget_span_attributes)r   r   s    r,   r   z$ResourceTemplate.get_span_attributesj  s0    ww**,,&9%40
 0
 
 	
r.   )r"   r!   NNNNNNNNNNNr   r   r    r!   rL   r   r   r   r   r   rw   r   r   r   rz   r   r   r   r   r|   r   r   r   r   r~   r   r"   r   )rz   r   r"   r!   )rN   r!   r"   r   r   ra   r"   r   )r   r   r"   r   r   rN   r!   r]   ra   r   r   r"   r   rN   r!   r]   ra   r   r   r"   r   rN   r!   r]   ra   r   r   r"   r   rN   r!   r]   ra   r"   r   )r   r   r"   r   )r   r   r"   r   r   r   r"   r   r   r   r]   ra   r   r   r   r   r   r   r"   r   )r"   ra   ) r   
__module____qualname____doc__rv   __annotations__r   r    rz   r{   r   r~   r   staticmethodr   r   classmethodr   r   r   r   r   r   r   r   r   propertyrp   r   r   r   __classcell__)r   s   @r,   r   r      s1        88 *J****R  L     U*M  I     "'9" " "J     ',e"V' ' 'K     @EuE@ @ @D    X X X X   $( "&#' $ $*.&*)-37
 
 
 
 \
> _[x000   [ 10: : : :
 
 
 
) ) ) )  BF    X ) ) ) X)
 NR$+ $+ $+ $+ $+L	
 	
 	
 	

 
 
 
& 

 

 

 [

 2 2 2 X2
5 5 5 5 "#> > > > > >.
 
 
 
 
 
 
 
 
 
r.   r   c                      e Zd ZU dZded<   e	 d9d:d            Zed;d            Z	 d9d<dZd=dZd>dZd?dZ	dddd@d#Z
e	 	 	 	 	 	 	 	 	 	 	 dAdBd8            ZdS )Cr   ru   z"SkipJsonSchema[Callable[..., Any]]r   NrN   r!   r]   ra   r   r   r"   r   c                
   K   d S r   r'   r   s       r,   r   zFunctionResourceTemplate._readv  r   r.   r   r   c                
   K   d S r   r'   r   s       r,   r   zFunctionResourceTemplate._read{  r   r.   r   r   c                   K   ddl m}  || d||           d{V }|r|S |                     |           d{V }|                     |          S )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   r8   r   Nr   )r   r   r   r   )r   rN   r]   r   r   r   ro   s          r,   r   zFunctionResourceTemplate._read  s      & 	GFFFFF11jFi
 
 
 
 
 
 
 
 
  	 yy6y22222222""6***r.   r   c           
         K   d fd}t          j        || j         j         j         j         j         j                  S )z>Create a resource from the template with the given parameters.r"   r   c                 D   K                                   d {V } | S )Nr   )r   )ro   r]   r   s    r,   resource_read_fnzBFunctionResourceTemplate.create_resource.<locals>.resource_read_fn  s1      99v966666666FMr.   )r   rN   rL   rw   rz   r   r   r~   )r"   r   )r   r   rL   rw   rz   r   r   r~   )r   rN   r]   r  s   ` ` r,   r   z(FunctionResourceTemplate.create_resource  sm      	 	 	 	 	 	 	
 %(n!	
 	
 	
 		
r.   r   r   c                  K   |                                 }t          j        | j                  }t	          |                                          D ]\  }}||j        v rt          |t                    r|j        |         }|j	        }|t          j
        j        u s	|t          u rT	 |t          u rt          |          ||<   nb|t          u rt          |          ||<   nF|t          u r=|                                }|dv rd||<   n|dv rd||<   nt!          d| d|          # t           t"          f$ r  w xY w | j        di |}	t          j        |	          r|	 d{V }	|	S )	r   )true1yesT)false0noFzInvalid boolean value for z: Nr'   )copyinspect	signaturer   listrX   r{   r   r!   
annotation	Parameteremptyintfloatboollower
ValueErrorAttributeErrorisawaitable)
r   r   r   sig
param_nameparam_valueparamr  r  ro   s
             r,   r   zFunctionResourceTemplate.read  s      !!(('+FLLNN';'; 	 	#JS^++
;0L0L+z2"-
!2!888J#<M<M!S((-0-=-=z**#u,,-2;-?-?z**#t++ + 1 1 3 3 $88815F:.."&:::16F:..", ZZ Z Z; Z Z# #  #N3   
 ""6""v&& 	"!\\\\\\Fs   &A>D%%D8r   r   c                    | j                                         sdS |                    | j        | j        g           dS r   )r   r   r   r   rp   r   s     r,   r   z-FunctionResourceTemplate.register_with_docket  s@    ..00 	Fz22222r.   r   r   r   r   r   r   r   c               Z   K   |p| j         }|r||d<     |j        |fi |di | d{V S )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()
        rp   Nr'   r   r   s          r,   r   z&FunctionResourceTemplate.add_to_docket  sa      ( 'tx
 	%$F5M5ZVZ
55f55???????????r.   r   r    rL   r   r   r   rw   r   r   rz   r   r   r   r|   r   r   r   r   r~   r   c                   |pt          |dd          p|j        j        }|dk    rt          d          t	          j        |          }|j                                        D ]+}|j        t          j	        j
        k    rt          d          ,t          t          j        d|                    }t          |          }||z  }|st          d          t          |          }t	          j        |          t          j                                                  }fd|D             }fd	|D             }|r||z
  }|rt          d
| d          |                    |          st          d| d|           t%          d |j                                        D                       s*|                    |          st          d| d|           ||nt	          j        |          }|t)          d          }n,t+          |t,                    rt)          j        |          }n|}|                    ||           t	          j        |          s!t+          |t4          j                  s|j        }t+          |t:                    r|j        }t?          |          }t          |          }tA          |          }|!                                }tE          |d          }tG          |          }tI          ||          } | |||tK          |          nd||||pd|||	pt                      |
|||          S )z"Create a template from a function.r   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 parameterc                    h | ]L}j         |         j        t          j        j        u r'j         |         j        t          j        j        k    J|MS r'   r{   ry   r
  r  r  kindVAR_KEYWORDr*   r+   user_sigs     r,   r-   z9FunctionResourceTemplate.from_function.<locals>.<setcomp>&  s^     
 
 
"1%-1B1HHH#A&+w/@/LLL  MLLr.   c                    h | ]L}j         |         j        t          j        j        ur'j         |         j        t          j        j        k    J|MS r'   r  r"  s     r,   r-   z9FunctionResourceTemplate.from_function.<locals>.<setcomp>,  s^     
 
 
"1%-W5F5LLL#A&+w/@/LLL  MLLr.   z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    V  d S r   )r   r
  r  r!  )r*   r  s     r,   	<genexpr>z9FunctionResourceTemplate.from_function.<locals>.<genexpr>C  sC       
 
 J'+77
 
 
 
 
 
r.   zURI parameters z- must be a subset of the function arguments: 	forbiddenr   T)prune_titlesrx   )r    rL   r   r   rw   r   rz   r   r{   r   r   r   r   r~   )&getattrr   r   r  r
  r  r{   valuesr   r  VAR_POSITIONALr5   r1   findallr7   r   keysissubsetanygetdocr   r   r  	from_boolvalidate_function	isroutine	functoolspartial__call__r   __func__r   r   json_schemar   r   r   r!   )r   r   r    rL   r   r   rw   r   rz   r   r   r   r   r~   	func_namer  r  path_paramsquery_paramsall_uri_params
wrapper_fnfunc_paramsrequired_paramsoptional_paramsinvalid_query_paramsr   type_adapterr{   resolved_mimer#  s                                @r,   r   z&FunctionResourceTemplate.from_function  s   & RGB
D99RR\=R	
""KLLL ##^**,, 	 	EzW.=== R   > "*%6EEFF+L99$|3 	QOPPP 144
$Z00(-224455
 
 
 
 
 
 

 
 
 
 
 
 
  	#//#A #  w(<www  
 ''44 	zzzmxzz  
  
 
..00
 
 
 
 
 	 "**;77  pnppcnpp   &1%<kk'.QSBTBT <$+666KKd## 	$.t44KKK%%b)444  $$ 	ZI<M-N-N 	Bb,'' 	B +2..044
-j99!--//
$ZdCCC
 :&& -\9EEs%$+$7CLLLT##3|!##
 
 
 	
r.   r   r   r   r   r   r   r   r   r   r   )r   r   r   r   r   r   r   r   r   r   r   r   r   r'   r.   r,   r   r   q  sF        88****BF    X ) ) ) X)
 NR+ + + + +>
 
 
 
&% % % %N3 3 3 3 "#@ @ @ @ @ @2 
  $( "&#' $ $*.&*)-37B
 B
 B
 B
 [B
 B
 B
r.   r   )r    r!   r"   r#   )r8   r!   r"   r9   )rN   r!   r    r!   r"   rO   )r    r!   r]   ra   r"   r!   )9r   
__future__r   r4  r
  r1   collections.abcr   typingr   r   r   r   urllib.parser	   r
   r   	mcp.typesmcpr   r   pydantic.json_schemar   r   r   docket.executionr   r   r   pydanticr   r   r   fastmcp.resources.baser   r   !fastmcp.server.auth.authorizationr   fastmcp.server.dependenciesr   r   fastmcp.server.tasks.configr   r   fastmcp.utilities.componentsr   fastmcp.utilities.json_schemar   fastmcp.utilities.mimer   fastmcp.utilities.typesr   r7   rM   r`   rs   r   r'   r.   r,   <module>rU     s   & & " " " " " "      				 $ $ $ $ $ $ 9 9 9 9 9 9 9 9 9 9 9 9 1 1 1 1 1 1 1 1 1 1     ' ' ' ' ' ' ' ' / / / / / / +****** = = = = = =          < ; ; ; ; ; ; ; 7 7 7 7 7 7        = < < < < < < < 9 9 9 9 9 9 9 9 9 9 9 9 7 7 7 7 7 7 : : : : : :      @   B   @^
 ^
 ^
 ^
 ^
' ^
 ^
 ^
BJ
 J
 J
 J
 J
/ J
 J
 J
 J
 J
r.   