
    k
ii                       d Z ddlmZ ddl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 ddlmZmZmZmZmZmZmZmZmZmZ ddlmZmZmZmZmZmZ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+ ddl,m-Z-m.Z. ddl/m0Z0 ddl1m2Z2 ddl3m4Z4 ddl5m6Z6m7Z7  e0            Z8 e4            Z9 ej:        e;          Z<dZ=dZ>dZ?de>e=z   ddddddddddddddddddddgd de?e=z   ddddddddd!ddd"d#dddddddddddddgd gZ@dFd(ZA ed)ee%e'f         *          ZB G d+ d,ed-.          ZC G d/ d0ee7e6f                   ZD	 dGdHd5ZEdId7ZF	 dJdKd=ZG	 	 dLdMdAZHdNdEZIdS )OzTBase implementation for Redis-backed store with optional vector search capabilities.    )annotationsN)defaultdict)datetime	timedeltatimezone)
AnyCallableDictGenericIterableOptionalSequence	TypedDictTypeVarUnion)GetOpIndexConfigItemListNamespacesOpOpPutOp
SearchItemSearchOp	TTLConfigensure_embeddingsget_text_at_pathtokenize_path)Redis)ResponseError)SearchIndex)TagText)TokenEscaper)JsonPlusRedisSerializer   )TokenUnescaper)	IndexTypeRedisClientType:storestore_vectorsjsonnameprefixstorage_typer/   textr.   typekeytag
created_atnumeric
updated_atttl_minutes
expires_atindexfields
field_name	embeddingvectorvaluer   returnstrc                h    t          | d          r|                                 S t          |           S )zConvert value to string safely.lower)hasattrrE   rC   )rA   s    C:\Users\Dell Inspiron 16\Desktop\tws\AgrotaPowerBi\back-agrota-powerbi\mcp-client-agrota\venv\Lib\site-packages\langgraph/store/redis/base.py_ensure_string_or_literalrH   `   s.    ug {{}}u::    C)boundc                  V    e Zd ZU ded<   ded<   ded<   ded<   ded<   d	ed
<   ded<   dS )RedisDocumentrC   r/   r4   zOptional[str]rA   intr6   r8   Optional[float]r9   Optional[int]r:   N)__name__
__module____qualname____annotations__ rI   rG   rM   rM   j   sZ         KKKHHHOOOOOO    rI   rM   F)totalc                     e Zd ZU dZded<   ded<   ded<   dZded	<   dZd
ed<   dZded<   eZdZ	ded<   dZ
ded<   ded<   	 	 dKdLdZdMdZdNdOd#ZdNdPd%Zdddeed&dQd-ZdRd.ZdRd/ZdSd1ZdSd2ZdTd6ZdUd:ZdVd>ZdWdBZdXdEZdYdJZdS )ZBaseRedisStorezUBase Redis implementation for persistent key-value store with optional vector search.r(   _redisr'   store_indexvector_indexNzOptional[threading.Thread]_ttl_sweeper_threadzthreading.Event | None_ttl_stop_eventOptional[bool]cluster_modeTboolsupports_ttlOptional[TTLConfig]
ttl_configr$   _serdemain_keyrC   related_keysOptional[list[str]]r9   rO   rB   r   c                   |*| j         r#d| j         v r| j                             d          }|t          |dz            }| j        rA| j                            ||           |r |D ]}| j                            ||           dS dS | j                            d          }|                    ||           |r|D ]}|                    ||           |                                 dS dS )zApply Redis native TTL to keys.

        Args:
            main_key: The primary Redis key
            related_keys: Additional Redis keys that should expire at the same time
            ttl_minutes: Time-to-live in minutes
        Ndefault_ttl<   T)transaction)rc   getrN   r_   rY   expirepipelineexecute)selfre   rf   r9   ttl_secondsr4   rn   s          rG   _apply_ttl_to_keysz!BaseRedisStore._apply_ttl_to_keys   s5     A=DO#C#C"o11-@@"kB.//K   #""8[999 =+ = =**3<<<<= == =  ;//D/AA+666 :+ : : [9999  """""# #"rI   rN   c                    dS )a  Clean up any remaining expired items.

        This is not needed with Redis native TTL, but kept for API compatibility.
        Redis automatically removes expired keys.

        Returns:
            int: Always returns 0 as Redis handles expiration automatically
        r   rU   )rp   s    rG   	sweep_ttlzBaseRedisStore.sweep_ttl   s	     qrI   _sweep_interval_minutesrP   Nonec                    dS )zStart TTL sweeper.

        This is a no-op with Redis native TTL, but kept for API compatibility.
        Redis automatically removes expired keys.

        Args:
            _sweep_interval_minutes: Ignored parameter, kept for API compatibility
        NrU   )rp   ru   s     rG   start_ttl_sweeperz BaseRedisStore.start_ttl_sweeper   s	     	rI   _timeoutc                    dS )a  Stop TTL sweeper.

        This is a no-op with Redis native TTL, but kept for API compatibility.

        Args:
            _timeout: Ignored parameter, kept for API compatibility

        Returns:
            bool: Always True as there's no sweeper to stop
        TrU   )rp   ry   s     rG   stop_ttl_sweeperzBaseRedisStore.stop_ttl_sweeper   s	     trI   )r<   ttlr_   store_prefixvector_prefixconnr<   Optional[IndexConfig]r|   r}   r~   c                  || _         || _        || _        || _        t	                      | _        || _        || _        | j         r| j                                         | _         t          | j         
                    d                    | _        | j         
                    ddg          pg }t          |t                    r|g}d |D             | j         d<   | j        | j        t          z   dddd	d
ddd
ddd
ddd
ddd
ddd
gd}t          j        || j                  | _        | j         r=t%          | j                   }	|	
                    dd          }
| j        | j        t          z   |
ddd	d
ddd
ddd
ddd
ddd
ddd
ddd
ddd
gd}|
                    dg           }d}|D ]4}t          |t$                    r|
                    d          dk    r|} n5|redd| j         d         dddd t'          |	
                    d!d"                             d#|d$<   d%|	v r!|d$                             |	d%                    t          j        || j                  | _        dS dS )&a  Initialize store with Redis connection and optional index config.

        Args:
            conn: Redis client connection
            index: Optional index configuration for vector search
            ttl: Optional TTL configuration
            cluster_mode: Optional cluster mode setting (None = auto-detect)
            store_prefix: Prefix for store keys (default: "store")
            vector_prefix: Prefix for vector keys (default: "store_vectors")
        embedr=   $c                D    g | ]}|d k    r|t          |          fn||fS )r   r   ).0ps     rG   
<listcomp>z+BaseRedisStore.__init__.<locals>.<listcomp>   sC     7 7 7BCcM!$$%%1v7 7 7rI   __tokenized_fieldsr,   r-   r/   r1   r2   r4   r5   r6   r7   r8   r9   r:   r;   )redis_clientvector_storage_typer>   r?   r@   Nr.   flatfloat32dimsCOSINEIPL2)cosineinner_productl2distance_typer   )	algorithmdatatyper   distance_metricattrsann_index_config)index_configrc   rY   r_   r$   rd   r}   r~   copyr   rl   
embeddings
isinstancerC   REDIS_KEY_SEPARATORr    	from_dictrZ   dictrH   updater[   )rp   r   r<   r|   r_   r}   r~   r=   store_schema
index_dictr   vector_schemavector_fieldsvector_fieldfs                  rG   __init__zBaseRedisStore.__init__   s\   ( "(-// )* 
	 $ 1 6 6 8 8D/!%%g.. DO &**8cU;;ArF&#&& " 7 7GM7 7 7D23 )+.AA &  "622..%y99%y99&	::%y99
 
" '0DKXXX  8	 d/00J",..1F"O"O
 !."03FF$7  &v66"E22)599((;;)9==)9==*I>>)9==	- -M$ *--h;;ML"  a&& 155==K+G+G#$LE Q "( ) -f5 #+)-"( (
 2&NN?HEE () )W%" &33 )00<N1OPPP + 5DK! ! !Dm8	 8	rI   c                    ddl m} 	 | j                            d|           dS # t          t
          f$ r1 	 | j                            |           Y dS # t          $ r Y Y dS w xY ww xY w)z%Set client info for Redis monitoring.r   __full_lib_name__LIB-NAMEN)"langgraph.checkpoint.redis.versionr   rY   client_setinfor   AttributeErrorecho	Exception)rp   r   s     rG   set_client_infozBaseRedisStore.set_client_infoN  s     	IHHHHH		K&&z3DEEEEE~. 	 	 	  !2333333   		s&   % A'A
A#A'"A##A'c                  K   ddl m} 	 | j                            d|           d{V  dS # t          t
          f$ rL 	 | j                            |          }t          |d          r| d{V  Y dS Y dS # t          $ r Y Y dS w xY ww xY w)z4Set client info for Redis monitoring asynchronously.r   r   r   N	__await__)	r   r   rY   r   r   r   r   rF   r   )rp   r   echo_results      rG   aset_client_infozBaseRedisStore.aset_client_info^  s       	IHHHHH	+,,Z9JKKKKKKKKKKK~. 		 		 		"k../@AA;44 &%%%%%%%%%%%& & &   		s&   !- B
2A77
BB
BB
rA   c                    |dS 	 t          j        |           |S # t          $ r Y nw xY w| j                            |          \  }}|dk    r|                    d          }n|                                }||dS )a"  Serialize a value for storage in Redis.

        This method handles complex objects like LangChain messages by
        serializing them to a JSON-compatible format.

        The method is smart about serialization:
        - If the value is a simple JSON-serializable dict/list, it's stored as-is
        - If the value contains complex objects (HumanMessage, etc.), it uses
          the serde wrapper format with __serde_type__ and __serde_data__ keys

        Note: Values containing LangChain messages will be wrapped in a serde format,
        which means filters on nested fields won't work for such values.

        Args:
            value: The value to serialize (can contain HumanMessage, AIMessage, etc.)

        Returns:
            A JSON-serializable representation of the value
        Nr,   utf-8)__serde_type____serde_data__)r,   dumps	TypeErrorrd   dumps_typeddecodehex)rp   rA   type_str
data_bytesdata_encodeds        rG   _serialize_valuezBaseRedisStore._serialize_valueq  s    ( =4	Ju L 	 	 	D	
  ${66u==* v%,,W55LL &>>++L '*
 
 	
s    
))c                    |dS t          |t                    rt          |                                          ddhk    r|d         }|d         }	 |dk    r|                    d          }nt
                              |          }| j                            ||f          S # t          t          f$ r'}t                              d||           Y d}~dS d}~wt          $ r'}t                              d||           Y d}~dS d}~ww xY w|S )a]  Deserialize a value from Redis storage.

        This method handles both new serialized format and legacy plain values
        for backward compatibility.

        Args:
            value: The value from Redis (may be serialized or plain)

        Returns:
            The deserialized value with proper Python objects (HumanMessage, etc.)
        Nr   r   r,   r   z9Failed to deserialize value from Redis: type=%r, error=%szBUnexpected error deserializing value from Redis: type=%r, error=%s)r   r   setkeysencodebytesfromhexrd   loads_typed
ValueErrorr   loggererrorr   )rp   rA   r   data_strr   es         rG   _deserialize_valuez!BaseRedisStore._deserialize_value  sO    =4 eT""  	s5::<<'8'8=
 (
 (
 -.H-.Hv%%!)!9!9JJ "'x!8!8J{..*/EFFF	*   O   ttttt   X  
 ttttt s%   AB$ $D5CD$DDget_opsSequence[tuple[int, GetOp]]1list[tuple[str, Sequence, tuple[str, ...], list]]c                   t          t                    }|D ],\  }}||j                                     ||j        f           -g }|                                D ]\  }}t          | \  }}	t          d          t          |          k    }
d|
 d}|	r)t          d          t          |	          k    }|| dz  }n|dz  }|                    |g ||f           |S )z*Convert GET operations into Redis queries.r/   ( r4   ))
r   list	namespaceappendr4   itemszipr"   _namespace_to_textr!   )rp   r   namespace_groupsidxopresultsr   r   _r   prefix_filter
filter_str
key_filters                rG   _get_batch_GET_ops_queriesz)BaseRedisStore._get_batch_GET_ops_queries  s   
 't,, 	A 	AGCR\*113-@@@@EG 0 6 6 8 8 
	? 
	?Iu5kGAt NN.@.K.KKM-]---J " ZZ4::5
....

c!
NNJIu=>>>>rI   put_opsSequence[tuple[int, PutOp]]Qtuple[list[RedisDocument], Optional[tuple[str, list[tuple[str, str, str, str]]]]]c           
     
   i }|D ]\  }}|||j         |j        f<   g }g }|                                D ]4}|j        |                    |           |                    |           5g }d }g }	|rj|D ]g}t          |j                   }
d|
 d|j         d}| j                            |          }|j        D ]!}| j	        
                    |j                   "h|r|D ]}t          t          j        t          j                                                  dz            }d }d }t%          |d          ra|j        Z|j        }t          t          j        t          j                  t)          |j                  z                                             }t+          t          |j                   |j        |                     |j                  ||||          }|                    |           | j        r|j        durw|j        | j        d	         nd
 |j        D             }|D ]O\  }}t3          |j        |          }|D ]2}|	                    t          |j                   |j        ||f           3P|	rd|	f}||fS )Nz	(@prefix:z @key:{z})@B r|   )minutes)r/   r4   rA   r6   r8   r9   r:   Fr   c                0    g | ]}|t          |          fS rU   r   )r   ixs     rG   r   z=BaseRedisStore._prepare_batch_PUT_queries.<locals>.<listcomp>0  s%    III"r=#4#45IIIrI    )r   r4   valuesrA   r   r   rZ   searchdocsrY   deleteidrN   r   nowr   utc	timestamprF   r|   r   rM   r   r   r<   r   )rp   r   dedupped_opsr   r   insertsdeletes
operationsembedding_requestto_embedr/   queryr   docr   r9   r:   pathspathtokenized_pathtextsr1   s                         rG   _prepare_batch_PUT_queriesz)BaseRedisStore._prepare_batch_PUT_queries  s    BD 	6 	6EAr35L",/00!!%%'' 	# 	#Bxr""""r""""*,
 46 	/ / /+BL99?F??BF???*11%88"< / /CK&&sv..../  +	3 ' '(,x|44>>@@9LMM #!
2u%% "&*<"$&K "%$L66269R9R9RR#)++" "J $-bl;;//99"" +)   !!#&&&$ )>)> 8+ )*>??IIIII  16  ,n 0> J J$)  D$OO!3BL!A!A264QU V   
  3%'N!,,,rI   
search_opsSequence[tuple[int, SearchOp]]>tuple[list[tuple[str, list, int, int]], list[tuple[int, str]]]c                   g }g }|D ]\  }}g }|j         r-t          |j                   }|                    d| d           |j        r#| j        r|                    ||j        f           |rd                    |          nd}|j        |j        nd}	|j        |j        nd}
|	|
g}|                    |||	|
f           ||fS )z-Convert search operations into Redis queries.@prefix:*r   N
   r   )namespace_prefixr   r   r   r   joinlimitoffset)rp   r  queriesembedding_requestsr   r   filter_conditionsr/   r   r  r  paramss               rG   _get_batch_search_queriesz(BaseRedisStore._get_batch_search_queries?  s   
 ! 	; 	;GC "" ?+B,?@@!(()=F)=)=)=>>>x ;D- ;"))3/:::3DMCHH.///#E " 4BHH"E"$)"7RYYQFV_FNNE65&9::::***rI   list_ops&Sequence[tuple[int, ListNamespacesOp]]list[tuple[str, list]]c                   g }|D ]\  }}g }|j         r~|j         D ]v}|j        dk    r0t          |j        d          }|                    d| d           =|j        dk    r.t          |j        d          }|                    d|            w|rd                    |          nd}|j        s|j        r|j        |j        gng }	|                    ||	f           |S )	z6Convert list namespaces operations into Redis queries.r/   T)handle_wildcardsr
  r  suffixz	@prefix:*r   )match_conditions
match_typer   r  r   r  r  r  )
rp   r  r  r   r   
conditions	conditionr  r   r  s
             rG   "_get_batch_list_namespaces_queriesz1BaseRedisStore._get_batch_list_namespaces_queriesX  s   
  	, 	,EArJ" >!#!4 > >I +x771).SWXXX"))*<T*<*<*<===="-991).SWXXX"))*<d*<*<===,6?CHHZ(((CE.0hK")Kbh	**FNNE6?++++rI   r4   r   c                    |dk    r	d| d| dS |dk    r	d| d| dS |dk    r	d| d	| dS |d
k    r	d| d| dS |dk    r	d| d| dS |dk    r	d| d| dS t          d|           )z2Get Redis search filter condition for an operator.z$eq@z:""z$gtz:[(z inf]z$gtez:[z$ltz:[-inf (]z$ltez:[-inf z$nez-@zUnsupported operator: )r   )rp   r4   r   rA   s       rG   _get_filter_conditionz$BaseRedisStore._get_filter_conditiono  s    ;;&s&&e&&&&5[[+s++u++++6\\*s**e****5[[,s,,E,,,,6\\+s++5++++5[['''u'''':b::;;;rI   vec1list[float]vecslist[list[float]]c                L   g }|D ]}t          d t          ||          D                       }t          d |D                       dz  }t          d |D                       dz  }|dk    s|dk    r|                    d           |                    |||z  z             |S )z*Compute cosine similarity between vectors.c              3  &   K   | ]\  }}||z  V  d S NrU   )r   abs      rG   	<genexpr>z4BaseRedisStore._cosine_similarity.<locals>.<genexpr>  s*      @@1a!e@@@@@@rI   c              3      K   | ]	}||z  V  
d S r,  rU   r   xs     rG   r/  z4BaseRedisStore._cosine_similarity.<locals>.<genexpr>  &      --1Q------rI   g      ?c              3      K   | ]	}||z  V  
d S r,  rU   r1  s     rG   r/  z4BaseRedisStore._cosine_similarity.<locals>.<genexpr>  r3  rI   r   )sumr   r   )rp   r&  r(  similaritiesvec2dot_productnorm1norm2s           rG   _cosine_similarityz!BaseRedisStore._cosine_similarity  s    
  	C 	CD@@D$@@@@@K-------#5E-------#5EzzUaZZ##A&&&&##K55=$ABBBBrI   NN)re   rC   rf   rg   r9   rO   rB   r   )rB   rN   r,  )ru   rP   rB   rv   )ry   rO   rB   r`   )r   r(   r<   r   r|   rb   r_   r^   r}   rC   r~   rC   rB   rv   )rB   rv   )rA   r   rB   r   )r   r   rB   r   )r   r   rB   r   )r  r  rB   r  )r  r  rB   r  )r4   rC   r   rC   rA   r   rB   rC   )r&  r'  r(  r)  rB   r'  )rQ   rR   rS   __doc__rT   r\   r]   r_   SCHEMASra   rc   rr   rt   rx   r{   STORE_PREFIXSTORE_VECTOR_PREFIXr   r   r   r   r   r   r  r  r   r%  r;  rU   rI   rG   rX   rX   t   s        __6:::::.2O2222#'L''''GL&*J**** $###
 -1'+	## ## ## ## ##J	 	 	 	
 
 
 
 
    $ (,#''+(0y y y y y y|       &.
 .
 .
 .
`5 5 5 5n   .N- N- N- N-`+ + + +2   .< < < <"     rI   rX   r   tuple[str, ...]r  r`   c                    |rt          d | D                       } t                              d                    |                     }|S )a&  Convert namespace tuple to text string with proper escaping.

    Args:
        namespace: Tuple of strings representing namespace components
        handle_wildcards: Whether to handle wildcard characters specially

    Returns:
        Properly escaped string representation of namespace
    c              3  *   K   | ]}|d k    rdn|V  dS )r  %NrU   )r   vals     rG   r/  z%_namespace_to_text.<locals>.<genexpr>  s.      JJ##JJJJJJrI   .)tuple_token_escaperescaper  )r   r  ns_texts      rG   r   r     sO      KJJ	JJJJJ	 ##CHHY$7$788GNrI   nsc                v    t          t                              |                               d                    S )z4Convert a dotted namespace string back into a tuple.rF  )rG  _token_unescaperunescapesplit)rK  s    rG   
_decode_nsrP    s-    !**2..44S99:::rI   rowdict[str, Any]deserialize_fnOptional[Callable[[Any], Any]]r   c           
         |d         }| ||          }t          ||d         | t          j        |d         dz  t          j                  t          j        |d         dz  t          j                            S )aC  Convert a row from Redis to an Item.

    Args:
        namespace: The namespace tuple for this item
        row: The raw row data from Redis
        deserialize_fn: Optional function to deserialize the value (handles
            LangChain messages, etc.)

    Returns:
        An Item with properly deserialized value
    rA   Nr4   r6   r   r8   )rA   r4   r   r6   r8   )r   r   fromtimestampr   r   )r   rQ  rS  rA   s       rG   _row_to_itemrW    s~      LE!u%%J)#l*;i*GVV)#l*;i*GVV   rI   scorerO   r   c           
         |d         }| ||          }t          ||d         | t          j        |d         dz  t          j                  t          j        |d         dz  t          j                  |          S )a  Convert a row from Redis to a SearchItem.

    Args:
        namespace: The namespace tuple for this item
        row: The raw row data from Redis
        score: Optional similarity score from vector search
        deserialize_fn: Optional function to deserialize the value (handles
            LangChain messages, etc.)

    Returns:
        A SearchItem with properly deserialized value
    rA   Nr4   r6   r   r8   )rA   r4   r   r6   r8   rX  )r   r   rV  r   r   )r   rQ  rX  rS  rA   s        rG   _row_to_search_itemrZ    s    $ LE!u%%J)#l*;i*GVV)#l*;i*GVV   rI   opsIterable[Op],tuple[dict[type, list[tuple[int, Op]]], int]c                    t          t                    }d}t          |           D ]4\  }}|t          |                                       ||f           |dz  }5||fS )z.Group operations by type for batch processing.r   r%   )r   r   	enumerater3   r   )r[  grouped_opstotr   r   s        rG   
_group_opsrb    sf    4?4E4EK
CS>>  RDHH$$c2Y///qrI   )rA   r   rB   rC   )F)r   rA  r  r`   rB   rC   )rK  rC   rB   rA  r,  )r   rA  rQ  rR  rS  rT  rB   r   r<  )
r   rA  rQ  rR  rX  rO   rS  rT  rB   r   )r[  r\  rB   r]  )Jr=  
__future__r   r   r,   logging	threadingcollectionsr   r   r   r   typingr   r	   r
   r   r   r   r   r   r   r   langgraph.store.baser   r   r   r   r   r   r   r   r   r   r   r   redisr   redis.asyncio
AsyncRedisredis.exceptionsr   redisvl.indexr    redisvl.query.filterr!   r"   redisvl.utils.token_escaperr#   )langgraph.checkpoint.redis.jsonplus_redisr$   token_unescaperr&   typesr'   r(   rH  rM  	getLoggerrQ   r   r   r?  r@  r>  rH   rJ   rM   rX   r   rP  rW  rZ  rb  rU   rI   rG   <module>rt     s   Z Z " " " " " "        # # # # # # 2 2 2 2 2 2 2 2 2 2                                                         - - - - - - * * * * * * % % % % % % * * * * * * * * 4 4 4 4 4 4 M M M M M M + + + + + + - - - - - - - -!>## 		8	$	$ %  "%88"
 
 v..E**!955!955"I66!955
 " $),??"
 
 v..E**!511 (33!955!955"I66!955	
 !!H    GCuUJ./000    IU    Z Z Z Z ZW_i78 Z Z Z| :?    *; ; ; ; 6:    > "59	    >     rI   