
    9i2                    `   d dl mZ d dlZd dlZd dlmZmZ d dlmZ d dl	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 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Z!e"e   ez  Z#dZ$ddZ%e%dd	 	 	 	 	 	 	 dd       Z& edd       G d de             Z' G d de      Z(ddZ)dd	 	 	 	 	 ddZ*y)    )annotationsN)CallableSequence)partial)	AnnotatedAnyLiteralcast)
AnyMessageBaseMessageBaseMessageChunkMessageLikeRepresentationRemoveMessageconvert_to_messagesmessage_chunk_to_message)	TypedDict
deprecated)CONFCONFIG_KEY_SENDNS_SEP)
StateGraph)LangGraphDeprecatedSinceV10)add_messagesMessagesStateMessageGraphREMOVE_ALL_MESSAGES__remove_all__c                     	 d	 	 	 	 	 	 	 d fd} j                   |_         t        t        t        t        gt        f   |      S )Nc                j    | |
 | |fi |S | |d| rdnd d}t        |      t        fi |S )NzMMust specify non-null arguments for both 'left' and 'right'. Only received: 'leftrightz'.)
ValueErrorr   )r    r!   kwargsmsgfuncs       a/var/www/html/backtest/airagagent/rag_env/lib/python3.12/site-packages/langgraph/graph/message.py_add_messagesz,_add_messages_wrapper.<locals>._add_messages*   sd      1e.v..!2(,f':">  S/!4*6**    )NN)r    Messages | Noner!   r)   r#   r   returnz3Messages | Callable[[Messages, Messages], Messages])__doc__r
   r   Messages)r%   r'   s   ` r&   _add_messages_wrapperr-   )   sU    ?C++-<+OR+	<+ !LLM(H-x78-HHr(   )formatc          	        d}t        | t              s| g} t        |t              s|g}t        |       D cg c]  }t        t	        t
        |             } }t        |      D cg c]  }t        t	        t
        |             }}| D ]1  }|j                  t        t        j                               |_        3 t        |      D ]Z  \  }}|j                  "t        t        j                               |_        t        |t              sE|j                  t        k(  sY|}\ |||dz   d S | j                         }t        |      D ci c]  \  }}|j                  | }}}t               }	|D ]  }|j                  |j                        x}
Mt        |t              r|	j!                  |j                         L|	j#                  |j                         |||
<   mt        |t              rt%        d|j                   d      t'        |      ||j                  <   |j)                  |        |D cg c]  }|j                  |	vs| }}|dk(  rt+        |      }|S |rd|d}t%        |      	 |S c c}w c c}w c c}}w c c}w )a  Merges two lists of messages, updating existing messages by ID.

    By default, this ensures the state is "append-only", unless the
    new message has the same ID as an existing message.

    Args:
        left: The base list of `Messages`.
        right: The list of `Messages` (or single `Message`) to merge
            into the base list.
        format: The format to return messages in. If `None` then `Messages` will be
            returned as is. If `langchain-openai` then `Messages` will be returned as
            `BaseMessage` objects with their contents formatted to match OpenAI message
            format, meaning contents can be string, `'text'` blocks, or `'image_url'` blocks
            and tool responses are returned as their own `ToolMessage` objects.

            !!! important "Requirement"

                Must have `langchain-core>=0.3.11` installed to use this feature.

    Returns:
        A new list of messages with the messages from `right` merged into `left`.
        If a message in `right` has the same ID as a message in `left`, the
            message from `right` will replace the message from `left`.

    Example: Basic usage
        ```python
        from langchain_core.messages import AIMessage, HumanMessage

        msgs1 = [HumanMessage(content="Hello", id="1")]
        msgs2 = [AIMessage(content="Hi there!", id="2")]
        add_messages(msgs1, msgs2)
        # [HumanMessage(content='Hello', id='1'), AIMessage(content='Hi there!', id='2')]
        ```

    Example: Overwrite existing message
        ```python
        msgs1 = [HumanMessage(content="Hello", id="1")]
        msgs2 = [HumanMessage(content="Hello again", id="1")]
        add_messages(msgs1, msgs2)
        # [HumanMessage(content='Hello again', id='1')]
        ```

    Example: Use in a StateGraph
        ```python
        from typing import Annotated
        from typing_extensions import TypedDict
        from langgraph.graph import StateGraph


        class State(TypedDict):
            messages: Annotated[list, add_messages]


        builder = StateGraph(State)
        builder.add_node("chatbot", lambda state: {"messages": [("assistant", "Hello")]})
        builder.set_entry_point("chatbot")
        builder.set_finish_point("chatbot")
        graph = builder.compile()
        graph.invoke({})
        # {'messages': [AIMessage(content='Hello', id=...)]}
        ```

    Example: Use OpenAI message format
        ```python
        from typing import Annotated
        from typing_extensions import TypedDict
        from langgraph.graph import StateGraph, add_messages


        class State(TypedDict):
            messages: Annotated[list, add_messages(format="langchain-openai")]


        def chatbot_node(state: State) -> list:
            return {
                "messages": [
                    {
                        "role": "user",
                        "content": [
                            {
                                "type": "text",
                                "text": "Here's an image:",
                                "cache_control": {"type": "ephemeral"},
                            },
                            {
                                "type": "image",
                                "source": {
                                    "type": "base64",
                                    "media_type": "image/jpeg",
                                    "data": "1234",
                                },
                            },
                        ],
                    },
                ]
            }


        builder = StateGraph(State)
        builder.add_node("chatbot", chatbot_node)
        builder.set_entry_point("chatbot")
        builder.set_finish_point("chatbot")
        graph = builder.compile()
        graph.invoke({"messages": []})
        # {
        #     'messages': [
        #         HumanMessage(
        #             content=[
        #                 {"type": "text", "text": "Here's an image:"},
        #                 {
        #                     "type": "image_url",
        #                     "image_url": {"url": "data:image/jpeg;base64,1234"},
        #                 },
        #             ],
        #         ),
        #     ]
        # }
        ```

    N   z?Attempting to delete a message with an ID that doesn't exist ('z')zlangchain-openaizUnrecognized format=z+. Expected one of 'langchain-openai', None.)
isinstancelistr   r   r
   r   idstruuiduuid4	enumerater   r   copysetgetadddiscardr"   lenappend_format_messages)r    r!   r.   remove_all_idxmidxmergedimerged_by_idids_to_removeexisting_idxr$   s               r&   r   r   <   s   ~ NdD!veT" %T* 	!&6!:;D  %U+ 	!&6!:;E 
  %44<tzz|$AD% E" !Q44<tzz|$ADa'ADD4G,G N	! !^a')** YY[F(1&(9:1ADD!G:L:EM (,,QTT22L?!]+!!!$$'%%add+'(|$!]+ UVWVZVZU[[]^  "%VLMM!  =A144}#<a=F=##!&) M 
%fY&QRoMe& ;" >s    I:% I?J8J
J
z{MessageGraph is deprecated in langgraph 1.0.0, to be removed in 2.0.0. Please use StateGraph with a `messages` key instead.)categoryc                  $     e Zd ZdZd fdZ xZS )r   a  A StateGraph where every node receives a list of messages as input and returns one or more messages as output.

    MessageGraph is a subclass of StateGraph whose entire state is a single, append-only* list of messages.
    Each node in a MessageGraph takes a list of messages as input and returns zero or more
    messages as output. The `add_messages` function is used to merge the output messages from each node
    into the existing list of messages in the graph's state.

    Examples:
        ```pycon
        >>> from langgraph.graph.message import MessageGraph
        ...
        >>> builder = MessageGraph()
        >>> builder.add_node("chatbot", lambda state: [("assistant", "Hello!")])
        >>> builder.set_entry_point("chatbot")
        >>> builder.set_finish_point("chatbot")
        >>> builder.compile().invoke([("user", "Hi there.")])
        [HumanMessage(content="Hi there.", id='...'), AIMessage(content="Hello!", id='...')]
        ```

        ```pycon
        >>> from langchain_core.messages import AIMessage, HumanMessage, ToolMessage
        >>> from langgraph.graph.message import MessageGraph
        ...
        >>> builder = MessageGraph()
        >>> builder.add_node(
        ...     "chatbot",
        ...     lambda state: [
        ...         AIMessage(
        ...             content="Hello!",
        ...             tool_calls=[{"name": "search", "id": "123", "args": {"query": "X"}}],
        ...         )
        ...     ],
        ... )
        >>> builder.add_node(
        ...     "search", lambda state: [ToolMessage(content="Searching...", tool_call_id="123")]
        ... )
        >>> builder.set_entry_point("chatbot")
        >>> builder.add_edge("chatbot", "search")
        >>> builder.set_finish_point("search")
        >>> builder.compile().invoke([HumanMessage(content="Hi there. Can you search for X?")])
        {'messages': [HumanMessage(content="Hi there. Can you search for X?", id='b8b7d8f4-7f4d-4f4d-9c1d-f8b8d8f4d9c1'),
                     AIMessage(content="Hello!", id='f4d9c1d8-8d8f-4d9c-b8b7-d8f4f4d9c1d8'),
                     ToolMessage(content="Searching...", id='d8f4f4d9-c1d8-4f4d-b8b7-d8f4f4d9c1d8', tool_call_id="123")]}
        ```
    c                    t        j                  dt        d       t        |   t
        t        t           t        f          y )Nz}MessageGraph is deprecated in LangGraph v1.0.0, to be removed in v2.0.0. Please use StateGraph with a `messages` key instead.   )rH   
stacklevel)	warningswarnr   super__init__r   r2   r   r   )self	__class__s    r&   rP   zMessageGraph.__init__*  s9     L0	

 	4
#3\#ABCr(   )r*   None)__name__
__module____qualname__r+   rP   __classcell__)rR   s   @r&   r   r      s    
,\D Dr(   r   c                      e Zd ZU ded<   y)r   z)Annotated[list[AnyMessage], add_messages]messagesN)rT   rU   rV   __annotations__ r(   r&   r   r   3  s    77r(   r   rY   c                    	 ddl m} t         ||             S # t        $ r% d}t	        j
                  |       t        |       cY S w xY w)Nr   )convert_to_openai_messageszMust have langchain-core>=0.3.11 installed to use automatic message formatting (format='langchain-openai'). Please update your langchain-core version or remove the 'format' flag. Returning un-formatted messages.)langchain_core.messagesr]   r   ImportErrorrM   rN   r2   )rY   r]   r$   s      r&   r?   r?   7  sQ    IF ##=h#GHH   	 	cH~s    +AA)	state_keyc               >  
 ddl m
m} ddlm} ddlm  |       }t        d t        | g      D              } | j                  t        d      t        |d   |      r|d   }|j                  }n/t        |d   t              rt        
fd	|d   D              r|d   }t        fd
D        d      x}rJ|d   }t        t!        t"        |d         j%                  t&                    |f}	|j)                  |	| d       |r |t*           t,           || fg       | S )zWrite a message manually to the `messages` / `messages-tuple` stream mode.

    Will automatically write to the channel specified in the `state_key` unless `state_key` is `None`.
    r   )BaseCallbackHandlerBaseCallbackManager)
get_config)StreamMessagesHandlerc              3      K   | ]  }|  y wNr[   ).0xs     r&   	<genexpr>zpush_message.<locals>.<genexpr>Z  s     =1=s   NzMessage ID is required	callbacksc              3  6   K   | ]  }t        |        y wrg   r1   )rh   ri   rb   s     r&   rj   zpush_message.<locals>.<genexpr>b  s      7/0
1)*7s   c              3  <   K   | ]  }t        |      s|  y wrg   rm   )rh   ri   re   s     r&   rj   zpush_message.<locals>.<genexpr>h  s     Eq
1.C DEs   metadatalanggraph_checkpoint_nsF)dedupe)langchain_core.callbacks.baserb   rc   langgraph.configrd   langgraph.pregel._messagesre   nextr   r3   r"   r1   handlersr2   alltupler
   r4   splitr   _emitr   r   )messager`   rc   rd   configmanagerrv   stream_handlerro   message_metarb   re   s             @@r&   push_messager   G  s,   
 ,@\F=17)<==Gzz122&%':;%##	F;'	.3 74:;4G7 4 +&EHEt ~  *%$sH%>?@FFvNO
 	\75A%t_%	7';&<=Nr(   )r%   r   r*   z(Callable[[Messages, Messages], Messages])r    r,   r!   r,   r.   z"Literal['langchain-openai'] | Noner*   r,   )rY   zSequence[BaseMessage]r*   zlist[BaseMessage])r{   z,MessageLikeRepresentation | BaseMessageChunkr`   z
str | Noner*   r   )+
__future__r   r5   rM   collections.abcr   r   	functoolsr   typingr   r   r	   r
   r^   r   r   r   r   r   r   r   typing_extensionsr   r   langgraph._internal._constantsr   r   r   langgraph.graph.stater   langgraph.warningsr   __all__r2   r,   r   r-   r   r   r   r?   r   r[   r(   r&   <module>r      s   "   .     4 H H , : )*-FF& I& 
 26	w
ww /	w
 w wt  B5D: 5D	5Dp8I 8I& '-9- - 	-r(   