o
    iG                     @   s  U d Z ddlmZ ddlmZ ddlmZmZ ddl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mZ ddlmZmZ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, e,e-dZ.ee/d< dZ0dZ1dZ2dZ3G dd deZ4G dd deZ5G dd deZ6G d d! d!e6Z7G d"d# d#e6Z8G d$d% d%e6Z9G d&d' d'e6Z:G d(d) d)e6Z;G d*d+ d+e6Z<G d,d- d-eZ=G d.d/ d/e&Z>d0e?e@ef dB d1e@fd2d3ZAdS )4z"A middleware for response caching.    )Sequence)Logger)Any	TypedDictN)PydanticAdapter)AsyncKeyValue)MemoryStore)LimitSizeWrapper)StatisticsWrapper)KVStoreCollectionStatistics)ReadResourceContents)	BaseModelField)NotRequiredSelfoverride)Prompt)Resource)CallNext
MiddlewareMiddlewareContext)Tool
ToolResult)
get_logger)nameloggeri  i,  i   
__global__c                   @   s   e Zd ZU dZeeB ed< dZedB ed< defddZ	e
dee defd	d
Ze
dee dee fddZe
dee dee fddZdS )CachableReadResourceContentsz6A wrapper for ReadResourceContents that can be cached.contentN	mime_typereturnc                 C   s   t |  S N)lenmodel_dump_jsonself r&   g/var/www/html/karishye-ai-python/venv/lib/python3.10/site-packages/fastmcp/server/middleware/caching.pyget_size,   s   z%CachableReadResourceContents.get_sizevaluesc                 C   s   t dd |D S )Nc                 s   s    | ]}|  V  qd S r!   )r(   .0itemr&   r&   r'   	<genexpr>1   s    z9CachableReadResourceContents.get_sizes.<locals>.<genexpr>)sumclsr)   r&   r&   r'   	get_sizes/      z&CachableReadResourceContents.get_sizesc                    s    fdd|D S )Nc                    s   g | ]
} |j |jd qS r   r   r4   r*   r0   r&   r'   
<listcomp>5   s    z5CachableReadResourceContents.wrap.<locals>.<listcomp>r&   r/   r&   r5   r'   wrap3   r2   z!CachableReadResourceContents.wrapc                 C   s   dd |D S )Nc                 S   s   g | ]
}t |j|jd qS r3   )r   r   r   r*   r&   r&   r'   r6   9   s    z7CachableReadResourceContents.unwrap.<locals>.<listcomp>r&   r/   r&   r&   r'   unwrap7   s   z#CachableReadResourceContents.unwrap)__name__
__module____qualname____doc__strbytes__annotations__r   intr(   classmethodr   r   r1   r   listr7   r8   r&   r&   r&   r'   r   &   s   
  r   c                   @   sj   e Zd ZU eejj ed< ee	e
f dB ed< ee	e
f dB ed< ededefddZdefd	d
ZdS )CachableToolResultr   Nstructured_contentmetavaluer    c                 C   s   | |j |j|jdS Nr   rD   rE   rH   )r0   rF   r&   r&   r'   r7   D   s
   zCachableToolResult.wrapc                 C   s   t | j| j| jdS rG   )r   r   rD   rE   r$   r&   r&   r'   r8   L   s
   zCachableToolResult.unwrap)r9   r:   r;   rB   mcptypesContentBlockr?   dictr=   r   rA   r   r   r7   r8   r&   r&   r&   r'   rC   ?   s   
 rC   c                   @   s*   e Zd ZU dZee ed< ee ed< dS )SharedMethodSettingsz!Shared config for a cache method.ttlenabledN)r9   r:   r;   r<   r   r@   r?   boolr&   r&   r&   r'   rM   T   s   
 rM   c                   @      e Zd ZdZdS )ListToolsSettings/Configuration options for Tool-related caching.Nr9   r:   r;   r<   r&   r&   r&   r'   rR   [       rR   c                   @   rQ   )ListResourcesSettings3Configuration options for Resource-related caching.NrT   r&   r&   r&   r'   rV   _   rU   rV   c                   @   rQ   )ListPromptsSettings1Configuration options for Prompt-related caching.NrT   r&   r&   r&   r'   rX   c   rU   rX   c                   @   s2   e Zd ZU dZeee  ed< eee  ed< dS )CallToolSettingsrS   included_toolsexcluded_toolsN)r9   r:   r;   r<   r   rB   r=   r?   r&   r&   r&   r'   rZ   g   s   
 rZ   c                   @   rQ   )ReadResourceSettingsrW   NrT   r&   r&   r&   r'   r]   n   rU   r]   c                   @   rQ   )GetPromptSettingsrY   NrT   r&   r&   r&   r'   r^   r   rU   r^   c                   @   s   e Zd ZU eddZedB ed< eddZedB ed< eddZedB ed< eddZ	edB ed< eddZ
edB ed< eddZedB ed< dS )	ResponseCachingStatisticsN)default
list_toolslist_resourceslist_promptsread_resource
get_prompt	call_tool)r9   r:   r;   r   ra   r   r?   rb   rc   rd   re   rf   r&   r&   r&   r'   r_   v   s   
 r_   c                   @   s  e Zd ZdZdddddddefdedB dedB dedB dedB de	dB de
dB d	edB d
efddZedeejj deejjee f dee fddZedeejj deejjee f dee fddZedeejj deejjee f dee fddZedeejj deejjef defddZedeejj  deejj ee! f dee! fddZ"edeejj# deejj#ejj$f dejj$fddZ%de&de'fddZ(de)fdd Z*dS )!ResponseCachingMiddlewarea  The response caching middleware offers a simple way to cache responses to mcp methods. The Middleware
    supports cache invalidation via notifications from the server. The Middleware implements TTL-based caching
    but cache implementations may offer additional features like LRU eviction, size limits, and more.

    When items are retrieved from the cache they will no longer be the original objects, but rather no-op objects
    this means that response caching may not be compatible with other middleware that expects original subclasses.

    Notes:
    - Caches `tools/call`, `resources/read`, `prompts/get`, `tools/list`, `resources/list`, and `prompts/list` requests.
    - Cache keys are derived from method name and arguments.
    Ncache_storagelist_tools_settingslist_resources_settingslist_prompts_settingsread_resource_settingsget_prompt_settingscall_tool_settingsmax_item_sizec	           	      C   s   |pt  | _t| j|dd| _t| jd| _|pt | _|p t | _	|p&t
 | _|p,t | _|p2t | _|p8t | _t| jtt dd| _t| jtt dd| _t| jtt dd| _t| jtt dd| _t| jtjjd	d| _t| jt d
d| _!dS )a  Initialize the response caching middleware.

        Args:
            cache_storage: The cache backend to use. If None, an in-memory cache is used.
            list_tools_settings: The settings for the list tools method. If None, the default settings are used (5 minute TTL).
            list_resources_settings: The settings for the list resources method. If None, the default settings are used (5 minute TTL).
            list_prompts_settings: The settings for the list prompts method. If None, the default settings are used (5 minute TTL).
            read_resource_settings: The settings for the read resource method. If None, the default settings are used (1 hour TTL).
            get_prompt_settings: The settings for the get prompt method. If None, the default settings are used (1 hour TTL).
            call_tool_settings: The settings for the call tool method. If None, the default settings are used (1 hour TTL).
            max_item_size: The maximum size of items eligible for caching. Defaults to 1MB.
        F)	key_valuemax_sizeraise_on_too_large)rp   
tools/list)rp   pydantic_modeldefault_collectionresources/listprompts/listresources/readprompts/get
tools/callN)"r   _backendr	   _size_limiterr
   _statsrR   _list_tools_settingsrV   _list_resources_settingsrX   _list_prompts_settingsr]   _read_resource_settingsr^   _get_prompt_settingsrZ   _call_tool_settingsr   rB   r   _list_tools_cacher   _list_resources_cacher   _list_prompts_cacher   _read_resource_cacherI   rJ   GetPromptResult_get_prompt_cacherC   _call_tool_cache)	r%   rh   ri   rj   rk   rl   rm   rn   ro   r&   r&   r'   __init__   sb   	z"ResponseCachingMiddleware.__init__context	call_nextr    c                       | j ddu r||I dH S | jjtdI dH  }r|S ||dI dH }dd |D }| jjt|| j dtd	I dH  |S )
zList tools from the cache, if caching is enabled, and the result is in the cache. Otherwise,
        otherwise call the next middleware and store the result in the cache if caching is enabled.rO   FNkeyr   c                 S   8   g | ]}t |j|j|j|j|j|j|j|j|j	d 	qS ))	r   titledescription
parametersoutput_schemaannotationsrE   tagsrO   )
r   r   r   r   r   r   r   rE   r   rO   )r+   toolr&   r&   r'   r6          z;ResponseCachingMiddleware.on_list_tools.<locals>.<listcomp>rN   r   rF   rN   )r~   getr   
GLOBAL_KEYputFIVE_MINUTES_IN_SECONDS)r%   r   r   cached_valuetoolscachable_toolsr&   r&   r'   on_list_tools      z'ResponseCachingMiddleware.on_list_toolsc                    r   )
zList resources from the cache, if caching is enabled, and the result is in the cache. Otherwise,
        otherwise call the next middleware and store the result in the cache if caching is enabled.rO   FNr   r   c                 S   r   ))	r   r   r   r   rE   r   r   rO   uri)
r   r   r   r   r   rE   r   r   rO   r   )r+   resourcer&   r&   r'   r6   !  r   z?ResponseCachingMiddleware.on_list_resources.<locals>.<listcomp>rN   r   )r   r   r   r   r   r   )r%   r   r   r   	resourcescachable_resourcesr&   r&   r'   on_list_resources  r   z+ResponseCachingMiddleware.on_list_resourcesc                    r   )
zList prompts from the cache, if caching is enabled, and the result is in the cache. Otherwise,
        otherwise call the next middleware and store the result in the cache if caching is enabled.rO   FNr   r   c                 S   s0   g | ]}t |j|j|j|j|j|j|jd qS ))r   r   r   r   rE   rO   	arguments)r   r   r   r   r   rE   rO   r   )r+   promptr&   r&   r'   r6   I  s    
z=ResponseCachingMiddleware.on_list_prompts.<locals>.<listcomp>rN   r   )r   r   r   r   r   r   )r%   r   r   r   promptscachable_promptsr&   r&   r'   on_list_prompts8  s   
z)ResponseCachingMiddleware.on_list_promptsc                    s   |j j}| jddu s| j|ds||dI dH S | dt|j j }| jj|dI dH  }r6| S ||dI dH }t	j
|d}| jj||| jd	td
I dH  | S )zCall a tool from the cache, if caching is enabled, and the result is in the cache. Otherwise,
        otherwise call the next middleware and store the result in the cache if caching is enabled.rO   F)	tool_namer   N:r   )rF   rN   r   )messager   r   r   _matches_tool_cache_settings_get_arguments_strr   r   r8   rC   r7   r   ONE_HOUR_IN_SECONDS)r%   r   r   r   	cache_keyr   tool_resultcachable_tool_resultr&   r&   r'   on_call_tool^  s.   
z&ResponseCachingMiddleware.on_call_toolc                    s   | j ddu r||dI dH S t|jj}| jj|dI dH  }r)tj|dS ||dI dH }tj|d}| jj	||| j dt
dI dH  tj|dS )	zRead a resource from the cache, if caching is enabled, and the result is in the cache. Otherwise,
        otherwise call the next middleware and store the result in the cache if caching is enabled.rO   Fr   Nr   )r)   rN   r   )r   r   r=   r   r   r   r   r8   r7   r   r   r%   r   r   r   r   rF   r&   r&   r'   on_read_resource  s   
z*ResponseCachingMiddleware.on_read_resourcec                    s   | j ddu r||dI dH S |jj dt|jjd }| jj|dI dH  }r-|S ||dI dH }| jj||| j dtd	I dH  |S )
zGet a prompt from the cache, if caching is enabled, and the result is in the cache. Otherwise,
        otherwise call the next middleware and store the result in the cache if caching is enabled.rO   Fr   Nr   r   r   rN   r   )	r   r   r   r   r   r   r   r   r   r   r&   r&   r'   on_get_prompt  s   
z'ResponseCachingMiddleware.on_get_promptr   c                 C   s<   | j d }r||vrdS | j d }r||v rdS dS )z<Check if the tool matches the cache settings for tool calls.r[   Fr\   T)r   r   )r%   r   r[   r\   r&   r&   r'   r     s   z6ResponseCachingMiddleware._matches_tool_cache_settingsc              	   C   s\   t | jjjd| jjjd| jjjd| jjjd| jjjd| jjjddS )z!Get the statistics for the cache.rs   rv   rw   rx   ry   rz   )ra   rb   rc   rd   re   rf   )r_   r}   
statisticscollectionsr   r$   r&   r&   r'   r     s   z$ResponseCachingMiddleware.statistics)+r9   r:   r;   r<   ONE_MB_IN_BYTESr   rR   rV   rX   r]   r^   rZ   r@   r   r   r   rI   rJ   ListToolsRequestr   r   r   r   ListResourcesRequestr   r   ListPromptsRequestr   r   CallToolRequestParamsr   r   ReadResourceRequestParamsr   r   GetPromptRequestParamsr   r   r=   rP   r   r_   r   r&   r&   r&   r'   rg      s    	
\
'
'
%
 

rg   r   r    c                 C   s<   | du rdS z
t j| td W S  ty   t|  Y S w )z-Get a string representation of the arguments.Nnull)rF   fallback)pydantic_coreto_jsonr=   decode	TypeErrorreprr   r&   r&   r'   r     s   r   )Br<   collections.abcr   loggingr   typingr   r   	mcp.typesrI   r   key_value.aio.adapters.pydanticr   !key_value.aio.protocols.key_valuer   key_value.aio.stores.memoryr   !key_value.aio.wrappers.limit_sizer	   !key_value.aio.wrappers.statisticsr
   )key_value.aio.wrappers.statistics.wrapperr    mcp.server.lowlevel.helper_typesr   pydanticr   r   typing_extensionsr   r   r   fastmcp.prompts.promptr   fastmcp.resources.resourcer   $fastmcp.server.middleware.middlewarer   r   r   fastmcp.tools.toolr   r   fastmcp.utilities.loggingr   r9   r   r?   r   r   r   r   r   rC   rM   rR   rV   rX   rZ   r]   r^   r_   rg   rL   r=   r   r&   r&   r&   r'   <module>   sN    	  "U