
    iW                       S SK Jr  S SKrS SKrS SKrS SKrS SKrS SKJr  S SK	J
r
JrJr  S SKJrJrJr  S SKJr  S SKJr  S SKJr  S S	KJrJrJrJrJrJrJrJrJ r   \RB                  " \"5      r# " S
 S\\$   \\5      r%\%r& " S S\5      r'g)    )annotationsN)defaultdict)AsyncIteratorIteratorSequence)AbstractAsyncContextManagerAbstractContextManager	ExitStack)TracebackType)Any)RunnableConfig)	WRITES_IDX_MAPBaseCheckpointSaverChannelVersions
CheckpointCheckpointMetadataCheckpointTupleSerializerProtocolget_checkpoint_idget_checkpoint_metadatac                    ^  \ rS rSr% SrS\S'   S\S'   S\S'   S	\S
.     SU 4S jjjrSS jr        S S jr	SS jr
        S!S jr        S"S jrS#S jrS	S	S	S.         S$S jjr          S%S jr S&         S'S jjrS(S jrS#S jrS	S	S	S.         S)S jjr          S%S jr S&         S'S jjrS(S jrS*S jrSrU =r$ )+InMemorySaver   aa  An in-memory checkpoint saver.

This checkpoint saver stores checkpoints in memory using a defaultdict.

Note:
    Only use `InMemorySaver` for debugging or testing purposes.
    For production use cases we recommend installing [langgraph-checkpoint-postgres](https://pypi.org/project/langgraph-checkpoint-postgres/) and using `PostgresSaver` / `AsyncPostgresSaver`.

    If you are using LangSmith Deployment, no checkpointer needs to be specified. The correct managed checkpointer will be used automatically.

Args:
    serde: The serializer to use for serializing and deserializing checkpoints.

Examples:

        import asyncio

        from langgraph.checkpoint.memory import InMemorySaver
        from langgraph.graph import StateGraph

        builder = StateGraph(int)
        builder.add_node("add_one", lambda x: x + 1)
        builder.set_entry_point("add_one")
        builder.set_finish_point("add_one")

        memory = InMemorySaver()
        graph = builder.compile(checkpointer=memory)
        coro = graph.ainvoke(1, {"configurable": {"thread_id": "thread-1"}})
        asyncio.run(coro)  # Output: 2
z_defaultdict[str, dict[str, dict[str, tuple[tuple[str, bytes], tuple[str, bytes], str | None]]]]storagezadefaultdict[tuple[str, str, str], dict[tuple[str, int], tuple[str, str, tuple[str, bytes], str]]]writesz@dict[tuple[str, str, str, str | int | float], tuple[str, bytes]]blobsN)serdefactoryc                 > [         TU ]  US9  U" S 5      U l        U" [        5      U l        U" 5       U l        [        5       U l        U[        Lap  U R                  R                  U R                  5        U R                  R                  U R                  5        U R                  R                  U R
                  5        g g )N)r   c                      [        [        5      $ N)r   dict     ^/home/james-whalen/.local/lib/python3.13/site-packages/langgraph/checkpoint/memory/__init__.py<lambda>(InMemorySaver.__init__.<locals>.<lambda>Y   s	    {4'8r$   )
super__init__r   r"   r   r   r
   stackr   enter_context)selfr   r   	__class__s      r%   r)   InMemorySaver.__init__R   s     	u%89dmY
[
+%JJ$$T\\2JJ$$T[[1JJ$$TZZ0 &r$   c                6    U R                   R                  5       $ r!   r*   	__enter__r,   s    r%   r1   InMemorySaver.__enter__b   s    zz##%%r$   c                :    U R                   R                  XU5      $ r!   r*   __exit__)r,   exc_type	exc_value	tracebacks       r%   r6   InMemorySaver.__exit__e   s     zz""8	BBr$   c                >   #    U R                   R                  5       $ 7fr!   r0   r2   s    r%   
__aenter__InMemorySaver.__aenter__m   s     zz##%%s   c                B   #    U R                   R                  XU5      $ 7fr!   r5   )r,   _InMemorySaver__exc_type_InMemorySaver__exc_value_InMemorySaver__tracebacks       r%   	__aexit__InMemorySaver.__aexit__p   s      zz"":KHHs   c                    0 nUR                  5        HQ  u  pVXXV4nXpR                  ;   d  M  U R                  U   nUS   S:w  d  M4  U R                  R                  U5      XE'   MS     U$ )Nr   empty)itemsr   r   loads_typed)	r,   	thread_idcheckpoint_nsversionschannel_valueskvkkvvs	            r%   _load_blobsInMemorySaver._load_blobsx   sh     *,NN$DAA1BZZZZ^a5G#(,

(>(>r(BN% % r$   c                X   US   S   nUS   R                  SS5      n[        U5      =n(       a  U R                  U   U   R                  U5      =n(       a  Uu  pgnU R                  X#U4   R	                  5       n	U R
                  R                  U5      n
[        U0 U
ESU R                  X#U
S   5      0EU R
                  R                  U5      U	 VVVVs/ s H#  u  ppXU R
                  R                  U5      4PM%     snnnnU(       a
  SUUUS.0S	9$ SS	9$ gU R                  U   U   =n(       a  [        UR                  5       5      nX   u  pgnU R                  X#U4   R	                  5       n	U R
                  R                  U5      n
[        SUUUS.00 U
ESU R                  X#U
S   5      0EU R
                  R                  U5      U	 VVVVs/ s H#  u  ppXU R
                  R                  U5      4PM%     snnnnU(       a
  SUUUS.0S	9$ SS	9$ gs  snnnnf s  snnnnf )
a  Get a checkpoint tuple from the in-memory storage.

This method retrieves a checkpoint tuple from the in-memory storage based on the
provided config. If the config contains a `checkpoint_id` key, the checkpoint with
the matching thread ID and timestamp is retrieved. Otherwise, the latest checkpoint
for the given thread ID is retrieved.

Args:
    config: The config to use for retrieving the checkpoint.

Returns:
    The retrieved checkpoint tuple, or None if no matching checkpoint was found.
configurablerH   rI    rK   channel_versionsrH   rI   checkpoint_idN)config
checkpointmetadatapending_writesparent_config)getr   r   r   valuesr   rG   r   rP   maxkeys)r,   rX   rH   rI   rW   savedrY   rZ   parent_checkpoint_idr   checkpoint_idcrM   _checkpointss                   r%   	get_tupleInMemorySaver.get_tuple   s     /<	#N377L-f55=5Y/>BB=QQuQ=B:
&:i%NOVVX*.***@*@*L&! % ($*:*:%kBT6U+  "ZZ33H=NT$NT{ra

 6 6q 9:f$ 0 +-61>1E- * "+ 	 R: #ll95mDD{D #K$4$4$6 7=H=W:
&:i%NOVVX"jj44Z@&&)2-:-:) % ($*:*:%kBT6U+  "ZZ33H=NT$NT{ra

 6 6q 9:f$ 0 +-61>1E-' 6 "7  E!$H$s   *H*H$filterbeforelimitc             #    ^#    U(       a	  US   S   4OU R                   nU(       a  US   R                  S5      OSnU(       a  [        U5      OSnU GH  nU R                   U   R                  5        GH  n	Ub  X:w  a  M  [	        U R                   U   U	   R                  5       S SS9 GHI  u  n
u  nnnU(       a  X:w  a  M  U(       a  [        U5      =n(       a  X:  a  M9  U R                  R                  U5      mU(       a*  [        U4S jUR                  5        5       5      (       d  M  Ub	  US	::  a    M  Ub  US
-  nU R                  XU
4   R                  5       nU R                  R                  U5      n[        SUU	U
S.00 UESU R                  UU	US   5      0ETU(       a  SUU	US.0OSU VVVVs/ s H&  u  nnnnUUU R                  R                  U5      4PM(     snnnnS9v   GML     GM     GM     gs  snnnnf 7f)a  List checkpoints from the in-memory storage.

This method retrieves a list of checkpoint tuples from the in-memory storage based
on the provided criteria.

Args:
    config: Base configuration for filtering checkpoints.
    filter: Additional filtering criteria for metadata.
    before: List checkpoints created before this configuration.
    limit: Maximum number of checkpoints to return.

Yields:
    An iterator of matching checkpoint tuples.
rS   rH   rI   Nc                    U S   $ )Nr   r#   )xs    r%   r&   $InMemorySaver.list.<locals>.<lambda>   s    !A$r$   T)keyreversec              3  P   >#    U  H  u  pUTR                  U5      :H  v   M     g 7fr!   )r]   ).0	query_keyquery_valuerZ   s      r%   	<genexpr>%InMemorySaver.list.<locals>.<genexpr>  s)      *6D2I $x||I'>>6Ds   #&r      rV   rK   rU   )rX   rY   rZ   r\   r[   )r   r]   r   r`   sortedrF   r   rG   allr   r^   r   rP   )r,   rX   rk   rl   rm   
thread_idsconfig_checkpoint_nsconfig_checkpoint_idrH   rI   rW   rY   
metadata_brb   before_checkpoint_idr   rc   rd   re   rM   rf   rZ   s                        @r%   listInMemorySaver.list   sH    , @Ff^,[9;4<<
;AF>"&&7t 	 =C08#I!%i!8!=!=!?(4%= LL+M:@@B& 	M $( ,0U  5Fv5NN1N)A   $zz55jAHc *6<lln* ' ' ! (UaZ*
![["=Afh  /3jj.D.DZ.PK)*-61>1>- $)$,d.>.> ) - +,> ?/$ "*  4 !/1:5B5I1" "& SY(RX;2q!QRDJJ$:$:1$=>RX(9 K "@ $Z(s   F;H>-H+"Hc           
        UR                  5       nUS   S   nUS   S   nUR                  S5      nUR                  5        H8  u  pX;   a  U R                  R	                  X   5      OSU R
                  XgX4'   M:     U R                  U   U   R                  US   U R                  R	                  U5      U R                  R	                  [        X5      5      US   R                  S5      405        SUUUS   S.0$ )	a  Save a checkpoint to the in-memory storage.

This method saves a checkpoint to the in-memory storage. The checkpoint is associated
with the provided config.

Args:
    config: The config to associate with the checkpoint.
    checkpoint: The checkpoint to save.
    metadata: Additional metadata to save with the checkpoint.
    new_versions: New versions as of this write

Returns:
    RunnableConfig: The updated config containing the saved checkpoint's timestamp.
rS   rH   rI   rK   )rE   r$   rd   rW   rV   )
copypoprF   r   dumps_typedr   r   updater   r]   )r,   rX   rY   rZ   new_versionsre   rH   rI   r^   rL   rM   s              r%   putInMemorySaver.putC  s   * OO>*;7	~.?!"'7!8 &&(DA56[

&&vy1n JJ	!78 ) 	Y.554 JJ**1-JJ**+B6+TU>*..?#	
 &!.!+D!1
 	
r$   c                v   US   S   nUS   R                  SS5      nUS   S   nXVU4nU R                  R                  U5      n	[        U5       Hf  u  n
u  pU[        R                   " X5      4nUS   S:  a  U	(       a  X;   a  M7  UUU R                  R                  U5      U4U R                  U   U'   Mh     g)	a  Save a list of writes to the in-memory storage.

This method saves a list of writes to the in-memory storage. The writes are associated
with the provided config.

Args:
    config: The config to associate with the writes.
    writes: The writes to save.
    task_id: Identifier for the task creating the writes.
    task_path: Path of the task creating the writes.

Returns:
    RunnableConfig: The updated config containing the saved writes' timestamp.
rS   rH   rI   rT   rW   rz   r   N)r]   r   	enumerater   r   r   )r,   rX   r   task_id	task_pathrH   rI   rW   	outer_keyouter_writes_idxre   rM   	inner_keys                 r%   
put_writesInMemorySaver.put_writesq  s    * >*;7	~.22?BG~.?}=		2$V,KC! ."4"4Q"<=I|q ]y7Q 

&&q)	1DKK	"9- -r$   c                D   XR                   ;   a  U R                   U	 [        U R                  R                  5       5       H  nUS   U:X  d  M  U R                  U	 M     [        U R                  R                  5       5       H  nUS   U:X  d  M  U R                  U	 M     g)Delete all checkpoints and writes associated with a thread ID.

Args:
    thread_id: The thread ID to delete.

Returns:
    None
r   N)r   r   r   r`   r   )r,   rH   rL   s      r%   delete_threadInMemorySaver.delete_thread  s     $Y'dkk&&()Aty KKN * djjoo'(Aty JJqM )r$   c                ,   #    U R                  U5      $ 7f)aD  Asynchronous version of `get_tuple`.

This method is an asynchronous wrapper around `get_tuple` that runs the synchronous
method in a separate thread using asyncio.

Args:
    config: The config to use for retrieving the checkpoint.

Returns:
    The retrieved checkpoint tuple, or None if no matching checkpoint was found.
)rh   )r,   rX   s     r%   
aget_tupleInMemorySaver.aget_tuple  s      ~~f%%   c              D   #    U R                  XX4S9 H  nU7v   M
     g7f)a  Asynchronous version of `list`.

This method is an asynchronous wrapper around `list` that runs the synchronous
method in a separate thread using asyncio.

Args:
    config: The config to use for listing the checkpoints.

Yields:
    An asynchronous iterator of checkpoint tuples.
rj   N)r   )r,   rX   rk   rl   rm   items         r%   alistInMemorySaver.alist  s$     & IIfFIPDJ Qs    c                .   #    U R                  XX45      $ 7f)aT  Asynchronous version of `put`.

Args:
    config: The config to associate with the checkpoint.
    checkpoint: The checkpoint to save.
    metadata: Additional metadata to save with the checkpoint.
    new_versions: New versions as of this write

Returns:
    RunnableConfig: The updated config containing the saved checkpoint's timestamp.
)r   )r,   rX   rY   rZ   r   s        r%   aputInMemorySaver.aput  s     $ xxHCC   c                .   #    U R                  XX45      $ 7f)a  Asynchronous version of `put_writes`.

This method is an asynchronous wrapper around `put_writes` that runs the synchronous
method in a separate thread using asyncio.

Args:
    config: The config to associate with the writes.
    writes: The writes to save, each as a (channel, value) pair.
    task_id: Identifier for the task creating the writes.
    task_path: Path of the task creating the writes.

Returns:
    None
)r   )r,   rX   r   r   r   s        r%   aput_writesInMemorySaver.aput_writes  s     * vwBBr   c                ,   #    U R                  U5      $ 7f)r   )r   )r,   rH   s     r%   adelete_threadInMemorySaver.adelete_thread  s      !!),,r   c                    Uc  SnO5[        U[        5      (       a  UnO[        UR                  S5      S   5      nUS-   n[        R                  " 5       nUS SUS 3$ )Nr   .rz   032016)
isinstanceintsplitrandom)r,   currentchannel	current_vnext_vnext_hs         r%   get_next_versionInMemorySaver.get_next_version  s_    ?I%%IGMM#.q12IQQvcl++r$   )r   r*   r   r   )r   zSerializerProtocol | Noner   ztype[defaultdict]returnNone)r   r   )r7   type[BaseException] | Noner8   BaseException | Noner9   TracebackType | Noner   bool | None)r?   r   r@   r   rA   r   r   r   )rH   strrI   r   rJ   r   r   zdict[str, Any])rX   r   r   zCheckpointTuple | None)
rX   RunnableConfig | Nonerk   dict[str, Any] | Nonerl   r   rm   
int | Noner   zIterator[CheckpointTuple])
rX   r   rY   r   rZ   r   r   r   r   r   )rT   )
rX   r   r   zSequence[tuple[str, Any]]r   r   r   r   r   r   )rH   r   r   r   )
rX   r   rk   r   rl   r   rm   r   r   zAsyncIterator[CheckpointTuple])r   z
str | Noner   r   r   r   )__name__
__module____qualname____firstlineno____doc____annotations__r   r)   r1   r6   r<   rB   rP   rh   r   r   r   r   r   r   r   r   r   r   __static_attributes____classcell__r-   s   @r%   r   r      sy   @ 
   ,0%0	1 )1 #	1
 
1 1 &C,C (C (	C
 
C&I.I *I *	I
 
I

-0
<K
	
Pl )-(, k%k &	k
 &k k 
#kZ,
,
 ,
 %	,

 &,
 
,
f $$ *$ 	$
 $ 
$L"$&$ )-(, % &	
 &  
(,DD D %	D
 &D 
D2 CC *C 	C
 C 
C.	-	, 	,r$   r   c                  l   ^  \ rS rSrSrSU 4S jjrSS jrSS jrSS jrSS jr	SS jr
SS	 jrS
rU =r$ )PersistentDicti  a  Persistent dictionary with an API compatible with shelve and anydbm.

The dict is kept in memory, so the dictionary operations run as fast as
a regular dictionary.

Write to disk is delayed until close or sync (similar to gdbm's fast mode).

Input file format is automatically discovered.
Output file format is selectable between pickle, json, and csv.
All three serialization formats are backed by fast C implementations.

Adapted from https://code.activestate.com/recipes/576642-persistent-dict-with-multiple-standard-file-format/

c               \   > SU l         S U l        SU l        Xl        [        TU ]  " U0 UD6  g )Nre   pickle)flagmodeformatfilenamer(   r)   )r,   r   argskwdsr-   s       r%   r)   PersistentDict.__init__"  s/    		 $'$'r$   c                   U R                   S:X  a  gU R                  S-   n[        XR                  S:X  a  SOS5      n U R	                  U5         UR                  5         [        R                  " XR                  5        U R                  b,  [        R                  " U R                  U R                  5        gg! [
         a    [        R                  " U5        e f = f! UR                  5         f = f)zWrite dict to diskrNz.tmpr   wbw)r   r   openr   dump	Exceptionosremovecloseshutilmover   chmod)r,   tempnamefileobjs      r%   syncPersistentDict.sync)  s    99==6)x)@cJ	IIg
 MMOHmm,99 HHT]]DII. !  	IIh	 MMOs   B; ;"CC   C2c                D    U R                  5         U R                  5         g r!   )r   clearr2   s    r%   r   PersistentDict.close:  s    		

r$   c                    U $ r!   r#   r2   s    r%   r1   PersistentDict.__enter__>  s    r$   c                $    U R                  5         g r!   )r   )r,   exc_infos     r%   r6   PersistentDict.__exit__A  s    

r$   c                    U R                   S:X  a"  [        R                  " [        U 5      US5        g [	        S[        U R                   5      -   5      e)Nr      zUnknown format: )r   r   r   r"   NotImplementedErrorrepr)r,   r   s     r%   r   PersistentDict.dumpD  s<    ;;("KKT
GQ/%&84;L&LMMr$   c                   U R                   S:X  a  g [        U R                  U R                  S:X  a  SOS5       n[        R
                  4 H5  nUR                  S5         U R                  U" U5      5      s  sS S S 5        $    [        S5      e! [         a       S S S 5        g [         a$    [        R                  SUR                   35        e f = f! , (       d  f       g = f)Nnr   rbr   r   zFailed to load file: zFile not in a supported format)r   r   r   r   r   loadseekr   EOFErrorr   loggererrorname
ValueError)r,   r   loaders      r%   r   PersistentDict.loadJ  s    99$--)@cJg!;;.Q;;vg77	 KJ( =>>    KJ ! LL#8!GH KJs5   &C!B7CC
CC%-CC
C#)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   r)   r   r   r1   r6   r   r   r   r   r   s   @r%   r   r     s1    (/"N? ?r$   r   )(
__future__r   loggingr   r   r   r   collectionsr   collections.abcr   r   r   
contextlibr   r	   r
   typesr   typingr   langchain_core.runnablesr   langgraph.checkpoint.baser   r   r   r   r   r   r   r   r   	getLoggerr   r   r   r   MemorySaverr   r#   r$   r%   <module>r     s    "  	    # = = U U   3
 
 
 
		8	$m,46Qm,` F?[ F?r$   