
    gIO              	      >   d dl mZ d dlZd dlZd dl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 d d	lmZmZmZmZmZmZ d dlZd dlZd dl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' d
dl(m)Z)m*Z*m+Z+m,Z,m-Z-m.Z. 	 d dl/Z0d dlmZ e0jb                  jd                  xjf                   e4 ee5      jl                  jo                               fz  c_3        dZ9 ejt                  d      Z; ed      Z<	  ed       G d dee,e#e'f                Z=y# e8$ r Y Cw xY w)    )annotationsN)Sequence)	ExitStack)	dataclassfield)cached_property)Path)perf_counter)TYPE_CHECKING	AnnotatedAnyCallableGenericTypeVar   )_utils
exceptionsmermaid)BaseNodeDepsTEndGraphRunContextNodeDefRunEndT)EndStepHistoryStepNodeStepStateTdeep_copy_statenodes_schema_var)Graphzpydantic-graph)
otel_scopeTF)initc            	      D   e Zd ZU dZded<   ded<   ded<    ed	      Zd
ed<    ed	      Zded<    ed	      Zded<   de	j                  e	j                  edd	 	 	 	 	 	 	 	 	 	 	 d&dZdddd	 	 	 	 	 	 	 	 	 	 	 d'dZdddd	 	 	 	 	 	 	 	 	 	 	 d'dZdddd	 	 	 	 	 	 	 	 	 	 	 	 	 d(dZdd	 	 	 	 	 	 	 d)dZd*dZed+d       Zdddddej*                  ddd	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 d,dZ	 d-	 	 	 	 	 d.dZdd	 	 	 	 	 	 	 d/d Zd0d!Zd1d"Z	 	 	 	 	 	 	 	 d2d#Zd$ Zd3d%Zy)4r!   u  Definition of a graph.

    In `pydantic-graph`, a graph is a collection of nodes that can be run in sequence. The nodes define
    their outgoing edges — e.g. which nodes may be run next, and thereby the structure of the graph.

    Here's a very simple example of a graph which increments a number by 1, but makes sure the number is never
    42 at the end.

    ```py {title="never_42.py" noqa="I001" py="3.10"}
    from __future__ import annotations

    from dataclasses import dataclass

    from pydantic_graph import BaseNode, End, Graph, GraphRunContext

    @dataclass
    class MyState:
        number: int

    @dataclass
    class Increment(BaseNode[MyState]):
        async def run(self, ctx: GraphRunContext) -> Check42:
            ctx.state.number += 1
            return Check42()

    @dataclass
    class Check42(BaseNode[MyState, None, int]):
        async def run(self, ctx: GraphRunContext) -> Increment | End[int]:
            if ctx.state.number == 42:
                return Increment()
            else:
                return End(ctx.state.number)

    never_42_graph = Graph(nodes=(Increment, Check42))
    ```
    _(This example is complete, it can be run "as is")_

    See [`run`][pydantic_graph.graph.Graph.run] For an example of running graph, and
    [`mermaid_code`][pydantic_graph.graph.Graph.mermaid_code] for an example of generating a mermaid diagram
    from the graph.
    
str | Nonenamez*dict[str, NodeDef[StateT, DepsT, RunEndT]]	node_defsCallable[[StateT], StateT]snapshot_stateF)reprtype[StateT] | _utils.Unset_state_typetype[RunEndT] | _utils.Unset_run_end_typebool_auto_instrumentNT)r'   
state_typerun_end_typer*   auto_instrumentc                   || _         || _        || _        || _        || _        t        j                  t        j                               }i | _	        |D ]  }| j                  ||        | j                          y)a  Create a graph from a sequence of nodes.

        Args:
            nodes: The nodes which make up the graph, nodes need to be unique and all be generic in the same
                state type.
            name: Optional name for the graph, if not provided the name will be inferred from the calling frame
                on the first call to a graph method.
            state_type: The type of the state for the graph, this can generally be inferred from `nodes`.
            run_end_type: The type of the result of running the graph, this can generally be inferred from `nodes`.
            snapshot_state: A function to snapshot the state of the graph, this is used in
                [`NodeStep`][pydantic_graph.state.NodeStep] and [`EndStep`][pydantic_graph.state.EndStep] to record
                the state before each step.
            auto_instrument: Whether to create a span for the graph run and the execution of each node's run method.
        N)r'   r-   r/   r1   r*   r   get_parent_namespaceinspectcurrentframer(   _register_node_validate_edges)	selfnodesr'   r2   r3   r*   r4   parent_namespacenodes	            I/var/www/openai/venv/lib/python3.12/site-packages/pydantic_graph/graph.py__init__zGraph.__init__\   su    0 	%) /,!66w7K7K7MNEGD&67  	    statedeps
infer_namec                 K   |r/| j                   #| j                  t        j                                g }t	               5 }d}| j
                  r5|j                  t        j                  d| j                   xs d|            }|}	 | j                  ||||d       d{   }t        |t              rF|j                  t        |             ||j                  d|       |j                  |fcddd       S t        |t               sHt"        rt%        j&                  |       n,t)        j*                  d	t-        |      j.                   d
      7 # 1 sw Y   yxY ww)a  Run the graph from a starting node until it ends.

        Args:
            start_node: the first node to run, since the graph definition doesn't define the entry point in the graph,
                you need to provide the starting node.
            state: The initial state of the graph.
            deps: The dependencies of the graph.
            infer_name: Whether to infer the graph name from the calling frame.

        Returns:
            The result type from ending the run and the history of the run.

        Here's an example of running the graph from [above][pydantic_graph.graph.Graph]:

        ```py {title="run_never_42.py" noqa="I001" py="3.10"}
        from never_42 import Increment, MyState, never_42_graph

        async def main():
            state = MyState(1)
            _, history = await never_42_graph.run(Increment(), state=state)
            print(state)
            #> MyState(number=2)
            print(len(history))
            #> 3

            state = MyState(41)
            _, history = await never_42_graph.run(Increment(), state=state)
            print(state)
            #> MyState(number=43)
            print(len(history))
            #> 5
        ```
        Nz{graph_name} run {start=}graph)
graph_namestartFrB   )resulthistoryzInvalid node return type: `z `. Expected `BaseNode` or `End`.)r'   _infer_namer7   r8   r   r1   enter_context_logfirespannext
isinstancer   appendr   set_attributedatar   r   typing_extensionsassert_neverr   GraphRuntimeErrortype__name__)	r;   
start_noderC   rD   rE   rK   stackrun_span	next_nodes	            r?   runz	Graph.run   s<    R $))+W113402[E7;H$$ ..MM3#'99#7( "  #I"&))IweRVch)"ii	i-NN7)#<=+ ..y'B$>>72% [& $Ix8$)66yA(::9$y/:R:R9SSst  i [s2   >E" A E E!AE1
E";AEEE"c                   |r/| j                   #| j                  t        j                                t	        j
                         j                  | j                  |||d            S )a  Run the graph synchronously.

        This is a convenience method that wraps [`self.run`][pydantic_graph.Graph.run] with `loop.run_until_complete(...)`.
        You therefore can't use this method inside async code or if there's an active event loop.

        Args:
            start_node: the first node to run, since the graph definition doesn't define the entry point in the graph,
                you need to provide the starting node.
            state: The initial state of the graph.
            deps: The dependencies of the graph.
            infer_name: Whether to infer the graph name from the calling frame.

        Returns:
            The result type from ending the run and the history of the run.
        FrB   )r'   rL   r7   r8   asyncioget_event_looprun_until_completer^   )r;   rZ   rC   rD   rE   s        r?   run_synczGraph.run_sync   sW    . $))+W1134%%'::HHZu4EHJ
 	
rA   c          	     x  K   |r/| j                   #| j                  t        j                                |j	                         }|| j
                  vrt        j                  d| d      t               5 }| j                  r'|j                  t        j                  d||             t        ||      }t        j                         }	t!               }
|j#                  |       d{   }t!               |
z
  }ddd       |j%                  t'        ||	| j(                               S 7 D# 1 sw Y   6xY ww)a  Run a node in the graph and return the next node to run.

        Args:
            node: The node to run.
            history: The history of the graph run so far. NOTE: this will be mutated to add the new step.
            state: The current state of the graph.
            deps: The dependencies of the graph.
            infer_name: Whether to infer the graph name from the calling frame.

        Returns:
            The next node to run or [`End`][pydantic_graph.nodes.End] if the graph has finished.
        NzNode `z` is not in the graph.zrun node {node_id})node_idr>   )rC   r>   start_tsdurationr*   )r'   rL   r7   r8   get_idr(   r   rW   r   r1   rM   rN   rO   r   r   now_utcr
   r^   rR   r   r*   )r;   r>   rK   rC   rD   rE   re   r[   ctxrf   rI   r]   rg   s                r?   rP   z
Graph.next   s    * $))+W1134++-$..(..v=S/TUU[E$$##HMM2FPW^bM$cd!%.C~~'H NE"hhsm+I#~-H  	5thbfbubuv	
  , [s1   A3D:5A2D.'D,(D.93D:,D..D73D:indentc               <    | j                   j                  ||      S )zDump the history of a graph run as JSON.

        Args:
            history: The history of the graph run.
            indent: The number of spaces to indent the JSON.

        Returns:
            The JSON representation of the history.
        rk   )history_type_adapter	dump_json)r;   rK   rl   s      r?   dump_historyzGraph.dump_history  s      ((22762JJrA   c                8    | j                   j                  |      S )zLoad the history of a graph run from JSON.

        Args:
            json_bytes: The JSON representation of the history.

        Returns:
            The history of the graph run.
        )rn   validate_json)r;   
json_bytess     r?   load_historyzGraph.load_history  s     ((66zBBrA   c                   | j                   j                         D cg c]  }|j                   }}| j                         }| j	                         }t        j                  |      }	 t        j                  t        t        t        ||f   t        j                  d      f            }t        j                  |       |S c c}w # t        j                  |       w xY w)Nkind)r(   valuesr>   _get_state_type_get_run_end_typer    setpydanticTypeAdapterlistr   r   Discriminatorreset)r;   node_defr<   state_tend_ttokentas          r?   rn   zGraph.history_type_adapter(  s    /3~~/D/D/FG/F8/FG&&(&&( $$U+	*%%d9[%5PRZRhRhioRp5p+q&rsB""5)	 H ""5)s   C (AC C)rZ   titleedge_labelsnoteshighlighted_nodeshighlight_cssrE   	directionc          
         |r/| j                   #| j                  t        j                                || j                   r| j                   }t	        j
                  | ||||xs d|||      S )aa  Generate a diagram representing the graph as [mermaid](https://mermaid.js.org/) diagram.

        This method calls [`pydantic_graph.mermaid.generate_code`][pydantic_graph.mermaid.generate_code].

        Args:
            start_node: The node or nodes which can start the graph.
            title: The title of the diagram, use `False` to not include a title.
            edge_labels: Whether to include edge labels.
            notes: Whether to include notes on each node.
            highlighted_nodes: Optional node or nodes to highlight.
            highlight_css: The CSS to use for highlighting nodes.
            infer_name: Whether to infer the graph name from the calling frame.
            direction: The direction of flow.

        Returns:
            The mermaid code for the graph, which can then be rendered as a diagram.

        Here's an example of generating a diagram for the graph from [above][pydantic_graph.graph.Graph]:

        ```py {title="never_42.py" py="3.10"}
        from never_42 import Increment, never_42_graph

        print(never_42_graph.mermaid_code(start_node=Increment))
        '''
        ---
        title: never_42_graph
        ---
        stateDiagram-v2
          [*] --> Increment
          Increment --> Check42
          Check42 --> Increment
          Check42 --> [*]
        '''
        ```

        The rendered diagram will look like this:

        ```mermaid
        ---
        title: never_42_graph
        ---
        stateDiagram-v2
          [*] --> Increment
          Increment --> Check42
          Check42 --> Increment
          Check42 --> [*]
        ```
        N)rZ   r   r   r   r   r   r   )r'   rL   r7   r8   r   generate_code)	r;   rZ   r   r   r   r   r   rE   r   s	            r?   mermaid_codezGraph.mermaid_code4  sk    x $))+W1134=TYYIIE$$!/'-4#	
 		
rA   c                    |r/| j                   #| j                  t        j                                d|vr| j                   r| j                   |d<   t	        j
                  | fi |S )a  Generate a diagram representing the graph as an image.

        The format and diagram can be customized using `kwargs`,
        see [`pydantic_graph.mermaid.MermaidConfig`][pydantic_graph.mermaid.MermaidConfig].

        !!! note "Uses external service"
            This method makes a request to [mermaid.ink](https://mermaid.ink) to render the image, `mermaid.ink`
            is a free service not affiliated with Pydantic.

        Args:
            infer_name: Whether to infer the graph name from the calling frame.
            **kwargs: Additional arguments to pass to `mermaid.request_image`.

        Returns:
            The image bytes.
        r   )r'   rL   r7   r8   r   request_image)r;   rE   kwargss      r?   mermaid_imagezGraph.mermaid_image  sX    & $))+W1134& TYY"iiF7O$$T4V44rA   )rE   c                  |r/| j                   #| j                  t        j                                d|vr| j                   r| j                   |d<   t	        j
                  || fi | y)a  Generate a diagram representing the graph and save it as an image.

        The format and diagram can be customized using `kwargs`,
        see [`pydantic_graph.mermaid.MermaidConfig`][pydantic_graph.mermaid.MermaidConfig].

        !!! note "Uses external service"
            This method makes a request to [mermaid.ink](https://mermaid.ink) to render the image, `mermaid.ink`
            is a free service not affiliated with Pydantic.

        Args:
            path: The path to save the image to.
            infer_name: Whether to infer the graph name from the calling frame.
            **kwargs: Additional arguments to pass to `mermaid.save_image`.
        Nr   )r'   rL   r7   r8   r   
save_image)r;   pathrE   r   s       r?   mermaid_savezGraph.mermaid_save  sW    " $))+W1134& TYY"iiF7O400rA   c                n   t        j                  | j                        r| j                  S | j                  j	                         D ]c  }t        j                  |j                        D ]?  }t        j                  |      t        u st        j                  |      }|r	|d   c c S  c e t        d       S )Nr   )r   is_setr-   r(   rw   rU   get_original_basesr>   
get_originr   get_argsrX   )r;   r   baseargss       r?   rx   zGraph._get_state_type  s    ==))*###--/H)<<X]]K$//5A,55d;D#Aw L 0 DzrA   c                   t        j                  | j                        r| j                  S | j                  j	                         D ]  }t        j                  |j                        D ]b  }t        j                  |      t        u st        j                  |      }t        |      dk(  r |d   }t        j                  |      s|c c S    t        j                  d      )N      zCCould not infer run end type from nodes, please set `run_end_type`.)r   r   r/   r(   rw   rU   r   r>   r   r   r   lenis_neverr   GraphSetupError)r;   r   r   r   ts        r?   ry   zGraph._get_run_end_type  s    ==++,%%%--/H)<<X]]K$//5A,55d;D4yA~ G%q1#$H L 0 (()noorA   c                    |j                         }| j                  j                  |      x}r(t        j                  d| d|j
                   d|       |j                  |      | j                  |<   y )Nz	Node ID `u   ` is not unique — found on z and )rh   r(   getr   r   r>   get_node_def)r;   r>   r=   re   existing_nodes        r?   r9   zGraph._register_node  sy    
 ++- NN..w77=7,,G9$A-BTBTAUUZ[_Z`a  '+&7&78H&IDNN7#rA   c           
     J   | j                   j                         }i }| j                   j                         D ]N  \  }}|j                  j                         D ],  }||vs|j	                  |g       j                  d| d       . P |r|j                         D cg c]   \  }}d| dt        j                  |       " }}}t        |      dk(  rt        j                  |d    d      dj                  d |D              }	t        j                  d|	       y c c}}w )	N`z` is referenced by r   r   z but not included in the graph.
c              3  &   K   | ]	  }d |   yw) N ).0bes     r?   	<genexpr>z(Graph._validate_edges.<locals>.<genexpr>  s     @2"hs   zANodes are referenced in the graph but not included in the graph:
)r(   keysitemsnext_node_edges
setdefaultrR   r   	comma_andr   r   r   join)
r;   known_node_ids	bad_edgesre   r   edgekvbad_edges_listbs
             r?   r:   zGraph._validate_edges  s%   ,,.*,	!%!5!5!7GX 00557~-((r299AgYa.I 8 "8
 ZcZiZiZklZkRVRSUV!$78H8H8K7LMZkNl>"a' 00N14E3FFe1fggII@@@ 00XYZX[\  ls   %Dc                >   | j                   J d       ||j                  x}ry|j                  j                         D ]  \  }}|| u s|| _          y |j                  |j                  k7  r0|j                  j                         D ]  \  }}|| u s|| _          y yyyy)zInfer the agent name from the call frame.

        Usage should be `self._infer_name(inspect.currentframe())`.

        Copied from `Agent`.
        NzName already set)r'   f_backf_localsr   	f_globals)r;   function_frameparent_framer'   items        r?   rL   zGraph._infer_name  s     yy 4"44 %>;P;P+P<+P*3399;
d4< $DI < $$(>(>>"."8"8">">"@JD$t|$(	 #A ? ,Q%rA   )r<   z0Sequence[type[BaseNode[StateT, DepsT, RunEndT]]]r'   r&   r2   r,   r3   r.   r*   r)   r4   r0   )r;   Graph[StateT, DepsT, T]rZ   BaseNode[StateT, DepsT, T]rC   r   rD   r   rE   r0   returnz&tuple[T, list[HistoryStep[StateT, T]]])r;   r   r>   r   rK   list[HistoryStep[StateT, T]]rC   r   rD   r   rE   r0   r   z%BaseNode[StateT, DepsT, Any] | End[T])r;   r   rK   r   rl   z
int | Noner   bytes)rs   zstr | bytes | bytearrayr   z"list[HistoryStep[StateT, RunEndT]])r   z8pydantic.TypeAdapter[list[HistoryStep[StateT, RunEndT]]])rZ   6Sequence[mermaid.NodeIdent] | mermaid.NodeIdent | Noner   z-str | None | typing_extensions.Literal[False]r   r0   r   r0   r   r   r   strrE   r0   r   z$mermaid.StateDiagramDirection | Noner   r   )T)rE   r0   r   /typing_extensions.Unpack[mermaid.MermaidConfig]r   r   )r   z
Path | strrE   r0   r   r   r   None)r   ztype[StateT])r   ztype[RunEndT])r;   r   r>   z type[BaseNode[StateT, DepsT, T]]r=   zdict[str, Any] | Noner   r   )r   ztypes.FrameType | Noner   r   )rY   
__module____qualname____doc____annotations__r   r-   r/   r1   r   UNSETr   r@   r^   rc   rP   rp   rt   r   rn   r   DEFAULT_HIGHLIGHT_CSSr   r   r   rx   ry   r9   r:   rL   r   rA   r?   r!   r!   )   s   (T 99../4%/@K,@27U2CM/C".d.  28,,5;\\5D $# @# 	#
 0# 3# 3# #R F%F.F 	F
 F F 
0FX 
%
.
 	

 
 
 
0
D '%'(' .'
 ' ' ' 
/'T gkK%K0LKYcK	K	C 	 	 NR?C TX$:::>I
 KI
 =	I

 I
 I
 RI
 I
 I
 8I
 
I
X "&551`5	54 :>11261Ix1	1.p J%J.J 0J 
	J&rA   r!   )>
__future__r   _annotationsr`   r7   typescollections.abcr   
contextlibr   dataclassesr   r   	functoolsr   pathlibr	   timer
   typingr   r   r   r   r   r   logfire_apir{   rU    r   r   r   r<   r   r   r   r   r   r   rC   r   r   r   r   r   r    logfire._internal.stack_infologfire	_internal
stack_infoNON_USER_CODE_PREFIXESr   __file__parentabsoluteImportError__all__LogfirerN   r#   r!   r   rA   r?   <module>r      s    2    $   ( %   L L    ) ) J J \ \d'   77CX@U@U@^@^@`<a;cc7 ;*:;CL  VGFE7*+ V V#  		s    D DD