
    k
iNH                     p   d Z ddlZddlmZmZmZmZmZmZm	Z	 ddl
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 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# ddl$m%Z% ddl&m'Z'm(Z(m)Z)m*Z*m+Z+  ej,        e-          Z.dedefdZ/ G d de          Z0	 	 d*de(dee         dee1         defdZ2	 	 d*dee(         dee         dee1         de0fdZ3	 	 	 	 	 	 	 	 	 d+dee         dee1         d e1d!ee4         d"e1d#ee4         d$eee1                  d%eee1                  d&e5de0fd'Z6 G d( d)          Z7dS ),a$  Middleware composition and factory functions.

This module provides utilities for composing multiple middleware together
and creating middleware stacks that share Redis connections with
checkpointers and stores. Compatible with LangChain's AgentMiddleware protocol
for use with create_agent.
    N)Any	AwaitableCallableListOptionalSequenceUnion)AgentMiddleware)ModelCallResultModelRequestModelResponse)	AIMessage)ToolMessage)ToolCallRequest)Command)Redis   )AsyncRedisMiddleware)ConversationMemoryMiddleware)SemanticCacheMiddleware_strip_content_ids)SemanticRouterMiddleware)ToolResultCacheMiddleware)ConversationMemoryConfigMiddlewareConfigTypeSemanticCacheConfigSemanticRouterConfigToolCacheConfigrequestreturnc                    t          | t                    r|                     d          }nt          | dd          }|s| S g }d}|D ]}t          |t                    rt          |j                  }||j        u}|j        o7|j        ddik    o*t          |j        	                                          dhk    }t          |j                  }|s|s|r<|j                            d          rddini }	|                    ||	i d          }d}|                    |           |s| S t          | t                    ri | d|iS |                     |          S )	a  Strip provider-specific IDs from AIMessages before sending to LLM.

    This is a safety net for stale checkpoint data: messages stored before
    the cache-deserialization fix may still carry provider IDs (rs_, msg_
    prefixes) in content blocks, additional_kwargs, or response_metadata.
    Cleaning them here prevents "Duplicate item found" errors from the
    OpenAI Responses API.
    messagesNFcachedT)contentadditional_kwargsresponse_metadata)update)r"   )
isinstancedictgetgetattrr   r   r$   r%   setkeysboolr&   
model_copyappendoverride)
r   r"   cleanedchangedmsgnew_contentcontent_changedhas_extra_kwargshas_metadata
new_kwargss
             C:\Users\Dell Inspiron 16\Desktop\tws\AgrotaPowerBi\back-agrota-powerbi\mcp-client-agrota\venv\Lib\site-packages\langgraph/middleware/redis/composition.py_sanitize_requestr;   (   s    '4   6;;z**7J55 GG  c9%% 	,S[99K)<O% D)h-==D-224455(C 
   566L "2 l  ),(=(A(A((K(KSXt$$QS  nn#.-7-/  %   s '4   2/'/:w/// 111    c            	          e Zd ZU dZee         ed<   dee         ddfdZde	de
e	gee         f         defd	Zdede
egeeeef                  f         deeef         fd
ZddZddZdee         dee         dee         ddfdZdS )MiddlewareStacka  A stack of middleware that chains calls through all middlewares.

    Inherits from LangChain's AgentMiddleware, so can be used directly with
    create_agent(middleware=[stack]) or as a single middleware entry.

    Middleware are applied in order: the first middleware wraps the second,
    which wraps the third, etc. This means the first middleware's
    before-processing runs first, and its after-processing runs last.

    Example:
        ```python
        from langchain.agents import create_agent
        from langgraph.middleware.redis import (
            MiddlewareStack,
            SemanticCacheMiddleware,
            ToolResultCacheMiddleware,
        )

        stack = MiddlewareStack([
            SemanticCacheMiddleware(cache_config),
            ToolResultCacheMiddleware(tool_config),
        ])

        # Use with create_agent
        agent = create_agent(
            model="gpt-4o",
            tools=[...],
            middleware=[stack],  # Pass stack as middleware
        )
        ```
    _middlewaresmiddlewaresr    Nc                 .    t          |          | _        dS )zwInitialize the middleware stack.

        Args:
            middlewares: List of middleware to chain together.
        N)listr?   )selfr@   s     r:   __init__zMiddlewareStack.__init__   s     !--r<   r   handlerc           
      v  K   | j         s |           d{V S dt          dt          ffd}|}t          | j                   D ]c}dt          dt
          t          gt          t                   f         dt
          t          gt          t                   f         fd} |||          }d ||           d{V S )a  Wrap a model call through all middleware.

        This method is part of the LangChain AgentMiddleware protocol.

        Args:
            request: The model request.
            handler: The final handler to call the model.

        Returns:
            The model response.
        Nreqr    c                 D   K    t          |                      d {V S N)r;   )rG   rE   s    r:   sanitized_handlerz;MiddlewareStack.awrap_model_call.<locals>.sanitized_handler   s2       !23!7!7888888888r<   mwhc                 4     dt           dt          f fd}|S )NrG   r    c                 @   K                        |            d {V S rI   )awrap_model_callrG   rL   rK   s    r:   wrapperzGMiddlewareStack.awrap_model_call.<locals>.make_wrapper.<locals>.wrapper   s/      !#!4!4S!!<!<<<<<<<<r<   )r   r   rK   rL   rQ   s   `` r:   make_wrapperz6MiddlewareStack.awrap_model_call.<locals>.make_wrapper   s<    =| = = = = = = = = r<   )r?   r   r   reversedr   r   r   r   )rC   r   rE   rJ   current_handler
middlewarerS   s     `    r:   rO   z MiddlewareStack.awrap_model_call   s         	* )))))))))
	9 	9/ 	9 	9 	9 	9 	9 	9  	
 #4#455 	H 	HJ(\NIm,DDE <.)M*BBC    +l:GGOO$_W---------r<   c                   K   | j         s ||           d{V S |}t          | j                   D ]}dt          dt          t          gt
          t          t          t          f                  f         dt          t          gt
          t          t          t          f                  f         fd} |||          } ||           d{V S )a  Wrap a tool call through all middleware.

        This method is part of the LangChain AgentMiddleware protocol.

        Args:
            request: The tool call request.
            handler: The final handler to execute the tool.

        Returns:
            The tool result.
        NrK   rL   r    c                 X     dt           dt          t          t          f         f fd}|S )NrG   r    c                 @   K                        |            d {V S rI   )awrap_tool_callrP   s    r:   rQ   zFMiddlewareStack.awrap_tool_call.<locals>.make_wrapper.<locals>.wrapper   s1       "$!3!3C!;!;;;;;;;;r<   )r   r	   LangChainToolMessager   rR   s   `` r:   rS   z5MiddlewareStack.awrap_tool_call.<locals>.make_wrapper   sI    <(</89< < < < < < <
 r<   )	r?   rT   r   r   r   r   r	   r[   r   )rC   r   rE   rU   rV   rS   s         r:   rZ   zMiddlewareStack.awrap_tool_call   s      $   	* ))))))))) ""4#455 	H 	HJ($%y7KW7T1U'VV
  !9U3G3P-Q#RR    +l:GGOO$_W---------r<   c                    K   | j         D ]Q}	 |                                 d{V  # t          $ r'}t                              d|            Y d}~Jd}~ww xY wdS )z"Close all middleware in the stack.NzError closing middleware: )r?   aclose	Exceptionloggerwarning)rC   rV   es      r:   r]   zMiddlewareStack.aclose   s      + 	A 	AJA '')))))))))) A A A?A??@@@@@@@@A	A 	As   (
AAAc                 
   K   | S )zEnter async context manager. )rC   s    r:   
__aenter__zMiddlewareStack.__aenter__   s      r<   exc_typeexc_valexc_tbc                 >   K   |                                   d{V  dS )z4Exit async context manager and close all middleware.N)r]   )rC   re   rf   rg   s       r:   	__aexit__zMiddlewareStack.__aexit__   s.       kkmmr<   )r    N)r    r>   )__name__
__module____qualname____doc__r   r   __annotations__r   rD   r   r   r   r   r   rO   r   r	   r[   r   rZ   r]   rd   r   typeBaseExceptionr   ri   rc   r<   r:   r>   r>   _   sn         @ +,,,,.H-A$B .t . . . .,.,. <.)M*BBC,. 
	,. ,. ,. ,.\+. +. y/CW/L)MNN
+. 
#W,	-+. +. +. +.ZA A A A   4. -( 	
 
     r<   r>   configredis_client	redis_urlc                    ||| _         d| _        n||| _        d| _         t          | t                    rt	          |           S t          | t
                    rt          |           S t          | t                    rt          |           S t          | t                    rt          |           S t          dt          |                      )a/  Create a middleware instance from a config object.

    Args:
        config: The middleware configuration.
        redis_client: Optional Redis client to use (overrides config).
        redis_url: Optional Redis URL to use (overrides config).

    Returns:
        The created middleware instance.
    NzUnknown config type: )rr   rs   r(   r   r   r   r   r   r   r   r   
ValueErrorro   )rq   rr   rs   s      r:   _create_middleware_from_configrv      s      *		$"&-.. 	A&v...	FO	,	, A(000	F0	1	1 A'///	F4	5	5 A+F333?f??@@@r<   configsc                 |    g }| D ])}t          |||          }|                    |           *t          |          S )a?  Create a middleware stack from configuration objects.

    All middlewares will share the same Redis connection.

    Args:
        configs: List of middleware configuration objects.
        redis_client: Optional Redis client to use for all middlewares.
        redis_url: Optional Redis URL to use for all middlewares.

    Returns:
        A MiddlewareStack with the configured middlewares.

    Example:
        ```python
        from langgraph.middleware.redis import (
            from_configs,
            SemanticCacheConfig,
            ToolCacheConfig,
        )

        stack = from_configs(
            redis_url="redis://localhost:6379",
            configs=[
                SemanticCacheConfig(ttl_seconds=3600),
                ToolCacheConfig(cacheable_tools=["search"]),
            ],
        )
        ```
    )rr   rs   )rv   r0   r>   )rw   rr   rs   r@   rq   rV   s         r:   from_configsry     s[    D K ' '3
 
 

 	:&&&&;'''r<   llmcache	toolcache皙?semantic_cache_namesemantic_cache_ttltool_cache_nametool_cache_ttlcacheable_toolsexcluded_toolsdistance_thresholdc	                 v    t          |||          t          |||||pg           g}	t          |	| |          S )at  Create a middleware stack with semantic and tool caching.

    A convenience function for the common pattern of caching both
    LLM responses and tool results.

    Args:
        redis_client: Optional Redis client to use (deprecated, use redis_url).
        redis_url: Redis URL to use.
        semantic_cache_name: Name for the semantic cache index.
        semantic_cache_ttl: TTL in seconds for semantic cache entries.
        tool_cache_name: Name for the tool cache index.
        tool_cache_ttl: TTL in seconds for tool cache entries.
        cacheable_tools: List of tool names to cache (None = all).
        excluded_tools: List of tool names to never cache.
        distance_threshold: Distance threshold for cache hits.

    Returns:
        A MiddlewareStack with semantic and tool caching.

    Example:
        ```python
        from langgraph.middleware.redis import create_caching_stack

        stack = create_caching_stack(
            redis_url="redis://localhost:6379",
            semantic_cache_ttl=3600,
            tool_cache_ttl=7200,
            cacheable_tools=["search", "calculate"],
        )
        ```
    )namettl_secondsr   )r   r   r   r   r   )rw   rr   rs   )r   r   ry   )
rr   rs   r}   r~   r   r   r   r   r   rw   s
             r:   create_caching_stackr   J  sq    V 	$*1	
 	
 	

 	 &1+)/R	
 	
 	
+G !   r<   c                   r    e Zd ZdZededee         defd            Z	ededee         defd            Z
dS )	IntegratedRedisMiddlewarea  Factory for creating middleware that shares Redis connections.

    This class provides static methods to create middleware stacks that
    connect to the same Redis server as existing checkpointers or stores.

    Note: The redisvl library components used by middleware require synchronous
    Redis connections. While the saver/store may use async clients, middleware
    will create their own sync connections to the same Redis URL.
    saverrw   r    c                    t          | dd          pt          | dd          }|kt          | dd          }|Xt          |dd          }|Et          |di           }|                    dd          }|                    d	d
          }d| d| }|t          d          g }|D ]4}	||	_        d|	_        t          |	          }
|                    |
           5t          |          S )a  Create middleware stack connecting to same Redis as a checkpoint saver.

        Note: Middleware creates its own sync Redis connection to the same server.
        The redisvl library components require sync connections internally.

        Args:
            saver: A RedisSaver or AsyncRedisSaver instance.
            configs: List of middleware configurations.

        Returns:
            A MiddlewareStack connecting to the same Redis server.

        Example:
            ```python
            from langgraph.checkpoint.redis import AsyncRedisSaver
            from langgraph.middleware.redis import (
                IntegratedRedisMiddleware,
                SemanticCacheConfig,
            )

            saver = AsyncRedisSaver(redis_url="redis://localhost:6379")
            await saver.asetup()

            stack = IntegratedRedisMiddleware.from_saver(
                saver,
                [SemanticCacheConfig(ttl_seconds=3600)],
            )
            ```
        
_redis_urlNrs   _redisconnection_poolconnection_kwargshost	localhostport  redis://:z[Could not determine Redis URL from saver. Please provide a redis_url in middleware configs.r+   r*   ru   rs   rr   rv   r0   r>   )r   rw   rs   rr   poolr   r   r   r@   rq   rV   s              r:   
from_saverz$IntegratedRedisMiddleware.from_saver  -   F E<66 
';;
 ;
	 "5(D99L'|->EE#(/6I2(N(N%,00EED,00>>D 84 8 8$ 8 8ID  
  	+ 	+F(F"&F7??Jz****{+++r<   storec                    t          | dd          pt          | dd          }|kt          | dd          }|Xt          |dd          }|Et          |di           }|                    dd          }|                    d	d
          }d| d| }|t          d          g }|D ]4}	||	_        d|	_        t          |	          }
|                    |
           5t          |          S )a  Create middleware stack connecting to same Redis as a store.

        Note: Middleware creates its own sync Redis connection to the same server.
        The redisvl library components require sync connections internally.

        Args:
            store: A RedisStore or AsyncRedisStore instance.
            configs: List of middleware configurations.

        Returns:
            A MiddlewareStack connecting to the same Redis server.

        Example:
            ```python
            from langgraph.store.redis import AsyncRedisStore
            from langgraph.middleware.redis import (
                IntegratedRedisMiddleware,
                SemanticCacheConfig,
            )

            store = AsyncRedisStore(conn=redis_client)
            await store.asetup()

            stack = IntegratedRedisMiddleware.from_store(
                store,
                [SemanticCacheConfig(ttl_seconds=3600)],
            )
            ```
        r   Nrs   r   r   r   r   r   r   r   r   r   z[Could not determine Redis URL from store. Please provide a redis_url in middleware configs.r   )r   rw   rs   rr   r   r   r   r   r@   rq   rV   s              r:   
from_storez$IntegratedRedisMiddleware.from_store  r   r<   N)rj   rk   rl   rm   staticmethodr   r   r   r>   r   r   rc   r<   r:   r   r     s          A,A,./A, 
A, A, A, \A,F A,A,./A, 
A, A, A, \A, A, A,r<   r   )NN)	NNrz   Nr{   NNNr|   )8rm   loggingtypingr   r   r   r   r   r   r	   langchain.agents.middlewarer
   !langchain.agents.middleware.typesr   r   r   langchain_core.messagesr   r   r[   langgraph.prebuilt.tool_noder   langgraph.typesr   redis.asyncior   
AsyncRedisaior   conversation_memoryr   semantic_cacher   r   semantic_routerr   
tool_cacher   typesr   r   r   r   r   	getLoggerrj   r_   r;   r>   strrv   ry   intfloatr   r   rc   r<   r:   <module>r      s     L L L L L L L L L L L L L L L L L L 7 7 7 7 7 7         
 . - - - - - G G G G G G 8 8 8 8 8 8 # # # # # # - - - - - - % % % % % % = = = = = = G G G G G G G G 5 5 5 5 5 5 1 1 1 1 1 1              
	8	$	$42| 42 42 42 42 42nY Y Y Y Yo Y Y Y| *.# A  A  A:& A } A 	 A  A  A  AJ *.#)( )(*+)(:&)( })( 	)( )( )( )(Z *.#)(,&$(+/*. #= =:&=}= = !	=
 = SM= d3i(= T#Y'= = = = = =@Q, Q, Q, Q, Q, Q, Q, Q, Q, Q,r<   