
    k
i8              	           d dl Z d dlZd dlmZ d dlZd dlmZ  ej        e          Z	de
e         fdZdddededeeef         fd	Zdd
deeef         dedefdZ G d de          ZdS )    N)Any)JsonPlusSerializerreturnc                  J    ddl m}  d t          j        |           D             S )zReturn the set of field names on the installed Interrupt dataclass.

    langgraph <=1.0.x has Interrupt(value, id).
    langgraph >=1.1.x has Interrupt(value, resumable, ns, when).
    r   	Interruptc                     h | ]	}|j         
S  )name).0fs     C:\Users\Dell Inspiron 16\Desktop\tws\AgrotaPowerBi\back-agrota-powerbi\mcp-client-agrota\venv\Lib\site-packages\langgraph/checkpoint/redis/jsonplus_redis.py	<setcomp>z$_interrupt_fields.<locals>.<setcomp>   s    :::qAF:::    )langgraph.typesr   dataclassesfieldsr   s    r   _interrupt_fieldsr      s5     *)))))::K.y99::::r   
preprocessobjr   c                    t                      }ddi}| || j                  |d<   n
| j        |d<   dD ]}||v rt          | |          ||<   |S )z;Serialize an Interrupt object using whichever fields exist.__interrupt__TNvalueid	resumablenswhen)r   r   getattr)r   r   r   resultfields        r   _serialize_interruptr#      sp      F-t4F$*SY//w)w2 0 0F??#C//F5MMr   reviver%   c                    ddl m} t                      }| || d                   n| d         }d|i}dD ]}||v r|| v r| |         ||<    |di |S )zIReconstruct an Interrupt from a serialized dict, tolerating both formats.r   r   Nr   r   r
   )r   r   r   )r   r%   r   r   r   kwargsr"   s          r   _deserialize_interruptr(   %   s    ))))))  F$*$6FF3w<   CLE%u-F2 ' 'F??u||JF5M9vr   c                        e Zd ZdZg dZdedefdZdedefdZdedee	e
f         f fdZdee	e
f         def fd	Zdee	ef         defd
ZdedefdZ xZS )JsonPlusRedisSerializera>  Redis-optimized serializer using orjson for JSON processing.

    Redis requires JSON-serializable data (not msgpack), so this serializer:
    1. Uses orjson for fast JSON serialization
    2. Handles LangChain objects by encoding them in the LC constructor format
    3. Handles Interrupt objects with custom serialization/deserialization
    4. Applies parent's _reviver for security-checked object reconstruction

    In checkpoint 3.0, the serializer API uses only dumps_typed/loads_typed
    with tuple[str, bytes] signatures (changed from tuple[str, str] in 2.x).
    )	thread_idcheckpoint_idcheckpoint_nsparent_checkpoint_idr   r   c                 f   t          |t          t          f          rt          d          ddlm} t          ||          rt          |          S ddlm} t          ||          rd|j        |j	        dS 	 t          |d          r/|                                }t          |t                    rd|v r|S |                     t          |          t          |d	          r|j        ni 
          S # t           t"          t$          t          f$ r! t          dt          |           d          w xY w)zCustom JSON encoder for objects that orjson can't serialize.

        This handles LangChain objects by delegating to the parent's
        _encode_constructor_args method which creates the LC format.
        z1bytes/bytearray in nested structure - use msgpackr   r   SendT__send__nodeargto_jsonlc__dict__r'   zObject of type z is not JSON serializable)
isinstancebytes	bytearray	TypeErrorr   r   r#   r1   r4   r5   hasattrr6   dict_encode_constructor_argstyper8   AttributeErrorKeyError
ValueError)selfr   r   r1   	json_dicts        r   _default_handlerz(JsonPlusRedisSerializer._default_handlerG   st    cE9-.. 	QOPPP 	.-----c9%% 	-',,, 	)(((((c4   	 w  	T sI&& %KKMM	i.. %493D3D$$ 00S		'#z2J2J"R#,,PR 1    *i@ 	T 	T 	TRd3iiRRRSSS	Ts   8>C2 7:C2 2>D0c                 *    ddl m}m} t          ||          rt	          | j                  S t          ||          r#d|j                             |j                  dS t          |t                    rdddd	gd
 fd|D             idS t          j
        |          rkt          |t                    sV fdt          j        |                                          D             }                     t          |          |          S t          |t                    r  fd|                                D             S t          |t           t"          f          r4 fd|D             }t          |t"                    rt#          |          n|S |S )aE  Recursively add type markers to Interrupt and Send objects before serialization.

        This prevents false positives where user data with {value, id} fields
        could be incorrectly deserialized as Interrupt objects.

        Also handles dataclass instances to preserve type information during serialization.
        r   )r   r1   r   Tr2      constructorbuiltinsset__set_items__c                 :    g | ]}                     |          S r
   _preprocess_interruptsr   itemrE   s     r   
<listcomp>zBJsonPlusRedisSerializer._preprocess_interrupts.<locals>.<listcomp>   s'    %X%X%XDd&A&A$&G&G%X%X%Xr   )r7   rA   r   r'   c                 B    i | ]\  }}|                     |          S r
   rO   r   kvrE   s      r   
<dictcomp>zBJsonPlusRedisSerializer._preprocess_interrupts.<locals>.<dictcomp>   s=       Aq 4..q11  r   r9   c                 B    i | ]\  }}|                     |          S r
   rO   rU   s      r   rX   zBJsonPlusRedisSerializer._preprocess_interrupts.<locals>.<dictcomp>   s-    NNN$!QAt22155NNNr   c                 :    g | ]}                     |          S r
   rO   rQ   s     r   rS   zBJsonPlusRedisSerializer._preprocess_interrupts.<locals>.<listcomp>   s'    KKKt44T::KKKr   )r   r   r1   r:   r#   rP   r4   r5   rL   r   is_dataclassrA   asdictitemsr@   r?   listtuple)rE   r   r   r1   processed_dict	processeds   `     r   rP   z.JsonPlusRedisSerializer._preprocess_interruptsu   s    	43333333c9%% $	'8STTTTT"" "	 !2237;;  
 S!! 	 %!5)#%X%X%X%XTW%X%X%X	   %c** 	:c43H3H 	   '.s3399;;  N 00c>0RRRT"" 	NNNN#))++NNNNdE]++ 	KKKKsKKKI'1#u'='=L5###9LJr   c                 n   t          |t                    rd|fS t          |t                    rdt          |          fS |dS 	 |                     |          }t	          j        || j                  }d|fS # t          t          j        f$ r$ t                      
                    |          cY S w xY w)zSerialize using orjson for JSON.

        Falls back to msgpack for structures containing bytes/bytearray.

        Returns:
            tuple[str, bytes]: Type identifier and serialized bytes
        r;   r<   N)nullr   )defaultjson)r:   r;   r<   rP   orjsondumpsrG   r=   JSONEncodeErrorsuperdumps_typed)rE   r   processed_obj
json_bytes	__class__s       r   rj   z#JsonPlusRedisSerializer.dumps_typed   s     c5!! 	0C<Y'' 	0c

**[;0 $ ; ;C @ @#\-AVWWW
z))v56 0 0 0ww**3/////0s   3A: :7B43B4datac                 F   |\  }}|dk    rdS |dk    r|S |dk    rt          |          S |dk    r)t          j        |          }|                     |          S |dk    r!t	                                          |          S t	                                          |          S )zDeserialize with custom revival for LangChain/LangGraph objects.

        Args:
            data: Tuple of (type_str, data_bytes)

        Returns:
            Deserialized object with proper revival of LangChain/LangGraph types
        rc   Nr;   r<   re   msgpack)r<   rf   loads_revive_if_neededri   loads_typed)rE   rn   type_
data_bytesparsedrm   s        r   rs   z#JsonPlusRedisSerializer.loads_typed   s     !zF??4gk!!Z(((f__\*--F))&111i77&&t,,, 77&&t,,,r   c           	      B    |                     dg           }|rt          |          dk     rt          d|           d                    |dd                   }|d         }	 ddl}|                    |          }t          ||          }n2# t          t          f$ r}t          d| d	| d
|           |d}~ww xY w|                     di           }	 fd|		                                D             }
|t          u rd|
v rt          |
d                   S  |di |
S )a  Reconstruct an object from LangChain constructor format.

        This handles objects that were serialized using _encode_constructor_args
        but are not LangChain objects (e.g., dataclasses, regular classes, sets).

        Args:
            obj: Dict with 'lc', 'type', 'id', and 'kwargs' keys

        Returns:
            Reconstructed object instance

        Raises:
            Exception: If object cannot be reconstructed
        r   rI   zInvalid constructor format: .Nr   zCannot import z from z: r'   c                 B    i | ]\  }}|                     |          S r
   rr   rU   s      r   rX   zIJsonPlusRedisSerializer._reconstruct_from_constructor.<locals>.<dictcomp>   s-    RRR41a!T33A66RRRr   rM   r
   )getlenrD   join	importlibimport_moduler    ImportErrorrB   r]   rL   )rE   r   id_partsmodule_path
class_namer   moduleclser'   revived_kwargss   `          r   _reconstruct_from_constructorz5JsonPlusRedisSerializer._reconstruct_from_constructor   sk     774$$ 	C3x==1,,ACAABBB hhx}--b\
	,,[99F&*--CC^, 	 	 	EEE;EE!EE 	 2&&RRRR6<<>>RRR #::/^;;~o6777 s$$^$$$s   %)B B> B99B>c                     t          |t                    r|                    d          dv r|                    d          dk    ri                     |          }t          |t                    r=|                    d          dv r&	                      |          S # t
          $ r Y nw xY w|S |                    d          du r\d|v rX	 t          | j                  S # t          t          t          f$ r'}t                              d	|d
           Y d}~nd}~ww xY w|                    d          du rd|v rd|v rt          |          dk    rt	 ddlm}  ||d                              |d                             S # t          t          t          f$ r'}t                              d|d
           Y d}~nd}~ww xY w fd|                                D             S t          |t"                    r fd|D             S |S )aE  Recursively apply reviver to handle LangChain and LangGraph serialized objects.

        This method is crucial for preventing MESSAGE_COERCION_FAILURE by ensuring
        that LangChain message objects stored in their serialized format are properly
        reconstructed. Without this, messages would remain as dictionaries with
        'lc', 'type', and 'constructor' fields, causing errors when the application
        expects actual message objects with 'role' and 'content' attributes.

        It also handles LangGraph Interrupt objects (both old and new serialization formats)
        and must be reconstructed to prevent AttributeError when accessing Interrupt attributes.

        Additionally, it handles dataclass objects (like langmem's RunningSummary) that are serialized
        using the LangChain constructor format but need special reconstruction logic.

        Args:
            obj: The object to potentially revive, which may be a dict, list, or primitive.

        Returns:
            The revived object with LangChain/LangGraph objects properly reconstructed.
        r7   )   rI   rA   rJ   r   Tr   r$   z*Failed to deserialize Interrupt object: %s)exc_infoNr3   r4   r5      r   r0   )r4   r5   z%Failed to deserialize Send object: %sc                 B    i | ]\  }}|                     |          S r
   r{   rU   s      r   rX   z=JsonPlusRedisSerializer._revive_if_needed.<locals>.<dictcomp>T  s-    IIITQAt--a00IIIr   c                 :    g | ]}                     |          S r
   r{   rQ   s     r   rS   z=JsonPlusRedisSerializer._revive_if_needed.<locals>.<listcomp>W  s'    AAATD**400AAAr   )r:   r?   r|   _reviverr   	Exceptionr(   rr   r   r=   rD   loggerdebugr}   r   r1   r]   r^   )rE   r   revivedr   r1   s   `    r   rr   z)JsonPlusRedisSerializer._revive_if_needed  s   * c4   >	wwt}}&&3776??m+K+K --,, gt,, 	#T1B1Bf1L1L#AA#FFF$   
 #N ww''4//GsNN1#d>TUUUU#Y
;   LLDaRV !         
##t++cMMSLLHHMM4444444 [ 223u:>>    $Y
;   LL?T !         JIIISYY[[IIIIT"" 	AAAASAAAA JsB   
B 
B,+B,C# #D!:DD!1F	 	G GG)__name__
__module____qualname____doc__SENTINEL_FIELDSr   rG   rP   r_   strr;   rj   rs   r?   r   rr   __classcell__)rm   s   @r   r*   r*   3   sG       
 
  O,TC ,TC ,T ,T ,T ,T\.# .# . . . .`0s 0uS%Z'8 0 0 0 0 0 02-c5j 1 -c - - - - - -8+%c3h +%C +% +% +% +%ZSS SS S S S S S S S Sr   r*   )r   loggingtypingr   rf   #langgraph.checkpoint.serde.jsonplusr   	getLoggerr   r   rL   r   r   r?   r#   r(   r*   r
   r   r   <module>r      s9               B B B B B B		8	$	$;3s8 ; ; ; ; 9=   c # c3h     BF   S#X 3 #    g g g g g0 g g g g gr   