
    OKi*                        S r SSKJr  SSKrSSKrSSKJr  SSKJr  SSK	J
r
JrJrJrJr  SSKJrJrJrJrJrJr  \(       a  SSKJrJr   " S	 S
\\\   \\4   5      rg)z"Model retry middleware for agents.    )annotationsN)TYPE_CHECKING)	AIMessage)	OnFailureRetryOncalculate_delayshould_retry_exceptionvalidate_retry_params)AgentMiddleware
AgentStateContextTModelRequestModelResponse	ResponseT)	AwaitableCallablec                     ^  \ rS rSrSrS\4SSSSSS	.               SU 4S
 jjjr\SS j5       rSS jr	      SS jr
      SS jrSrU =r$ )ModelRetryMiddleware   a4  Middleware that automatically retries failed model calls with configurable backoff.

Supports retrying on specific exceptions and exponential backoff.

Examples:
    !!! example "Basic usage with default settings (2 retries, exponential backoff)"

        ```python
        from langchain.agents import create_agent
        from langchain.agents.middleware import ModelRetryMiddleware

        agent = create_agent(model, tools=[search_tool], middleware=[ModelRetryMiddleware()])
        ```

    !!! example "Retry specific exceptions only"

        ```python
        from anthropic import RateLimitError
        from openai import APITimeoutError

        retry = ModelRetryMiddleware(
            max_retries=4,
            retry_on=(APITimeoutError, RateLimitError),
            backoff_factor=1.5,
        )
        ```

    !!! example "Custom exception filtering"

        ```python
        from anthropic import APIStatusError


        def should_retry(exc: Exception) -> bool:
            # Only retry on 5xx errors
            if isinstance(exc, APIStatusError):
                return 500 <= exc.status_code < 600
            return False


        retry = ModelRetryMiddleware(
            max_retries=3,
            retry_on=should_retry,
        )
        ```

    !!! example "Custom error handling"

        ```python
        def format_error(exc: Exception) -> str:
            return "Model temporarily unavailable. Please try again later."


        retry = ModelRetryMiddleware(
            max_retries=4,
            on_failure=format_error,
        )
        ```

    !!! example "Constant backoff (no exponential growth)"

        ```python
        retry = ModelRetryMiddleware(
            max_retries=5,
            backoff_factor=0.0,  # No exponential growth
            initial_delay=2.0,  # Always wait 2 seconds
        )
        ```

    !!! example "Raise exception on failure"

        ```python
        retry = ModelRetryMiddleware(
            max_retries=2,
            on_failure="error",  # Re-raise exception instead of returning message
        )
        ```
   continueg       @g      ?g      N@T)max_retriesretry_on
on_failurebackoff_factorinitial_delay	max_delayjitterc                  > [         TU ]  5         [        XXd5        Xl        / U l        X l        X0l        X@l        XPl        X`l	        Xpl
        g)u  Initialize `ModelRetryMiddleware`.

Args:
    max_retries: Maximum number of retry attempts after the initial call.

        Must be `>= 0`.
    retry_on: Either a tuple of exception types to retry on, or a callable
        that takes an exception and returns `True` if it should be retried.

        Default is to retry on all exceptions.
    on_failure: Behavior when all retries are exhausted.

        Options:

        - `'continue'`: Return an `AIMessage` with error details,
            allowing the agent to continue with an error response.
        - `'error'`: Re-raise the exception, stopping agent execution.
        - **Custom callable:** Function that takes the exception and returns a
            string for the `AIMessage` content, allowing custom error
            formatting.
    backoff_factor: Multiplier for exponential backoff.

        Each retry waits `initial_delay * (backoff_factor ** retry_number)`
        seconds.

        Set to `0.0` for constant delay.
    initial_delay: Initial delay in seconds before first retry.
    max_delay: Maximum delay in seconds between retries.

        Caps exponential backoff growth.
    jitter: Whether to add random jitter (`±25%`) to delay to avoid thundering herd.

Raises:
    ValueError: If `max_retries < 0` or delays are negative.
N)super__init__r
   r   toolsr   r   r   r   r   r   )	selfr   r   r   r   r   r   r   	__class__s	           i/var/www/html/dynamic-report/venv/lib/python3.13/site-packages/langchain/agents/middleware/model_retry.pyr!   ModelRetryMiddleware.__init__o   sJ    \ 	 	k)T&
 $,*"    c                    [        U 5      R                  n[        U 5      nUS:X  a  SOSnSU SU SU SU 3n[        US9$ )	zFormat the failure message when retries are exhausted.

Args:
    exc: The exception that caused the failure.
    attempts_made: Number of attempts actually made.

Returns:
    `AIMessage` with formatted error message.
   attemptattemptszModel call failed after  z with z: content)type__name__strr   )excattempts_madeexc_typeexc_msgattempt_wordr.   s         r%   _format_failure_message,ModelRetryMiddleware._format_failure_message   s[     9%%c($1Q$6yJ&}oQ|nF8*TVW^V_` 	 ))r'   c                    U R                   S:X  a  Ue[        U R                   5      (       a  U R                  U5      n[        US9nOU R                  X5      n[	        U/S9$ )a  Handle failure when all retries are exhausted.

Args:
    exc: The exception that caused the failure.
    attempts_made: Number of attempts actually made.

Returns:
    `ModelResponse` with error details.

Raises:
    Exception: If `on_failure` is `'error'`, re-raises the exception.
errorr-   )result)r   callabler   r7   r   )r#   r2   r3   r.   ai_msgs        r%   _handle_failure$ModelRetryMiddleware._handle_failure   sY     ??g%IDOO$$ooc*Gw/F11#EFVH--r'   c           
        [        U R                  S-   5       H  n U" U5      s  $    Sn[        U5      e! [         a  nUS-   n[        X@R                  5      (       d  U R                  XE5      s SnAs  $ X0R                  :  a]  [        UU R                  U R                  U R                  U R                  S9nUS:  a  [        R                  " U5         SnAM   SnAM  U R                  XE5      s SnAs  $ SnAff = f)al  Intercept model execution and retry on failure.

Args:
    request: Model request with model, messages, state, and runtime.
    handler: Callable to execute the model (can be called multiple times).

Returns:
    `ModelResponse` or `AIMessage` (the final result).

Raises:
    RuntimeError: If the retry loop completes without returning. (This should not happen.)
r)   Nr   r   r   r   r   2Unexpected: retry loop completed without returning)ranger   	Exceptionr	   r   r>   r   r   r   r   r   timesleepRuntimeErrorr#   requesthandlerr*   r2   r3   delaymsgs           r%   wrap_model_call$ModelRetryMiddleware.wrap_model_call   s    $ T--12GDw'' 3: C37  D '! .c==AA//CC ---+'+':':&*&8&8"&..#{{E qy

5)) !
  //CC/Ds.   6
D  /C;/D 7A C;#C;3D ;D c           
     4  #    [        U R                  S-   5       H  n U" U5      I Sh  vN s  $    Sn[        U5      e N! [         a  nUS-   n[        X@R                  5      (       d  U R                  XE5      s SnAs  $ X0R                  :  af  [        UU R                  U R                  U R                  U R                  S9nUS:  a%  [        R                  " U5      I Sh  vN     SnAM   SnAM  U R                  XE5      s SnAs  $ SnAff = f7f)a}  Intercept and control async model execution with retry logic.

Args:
    request: Model request with model, messages, state, and runtime.
    handler: Async callable to execute the model and returns `ModelResponse`.

Returns:
    `ModelResponse` or `AIMessage` (the final result).

Raises:
    RuntimeError: If the retry loop completes without returning. (This should not happen.)
r)   NrA   r   rB   )rC   r   rD   r	   r   r>   r   r   r   r   r   asynciorF   rG   rH   s           r%   awrap_model_call%ModelRetryMiddleware.awrap_model_call  s     $ T--12GD$W--- 3: C39 . D '! .c==AA//CC ---+'+':':&*&8&8"&..#{{E qy%mmE222 !
  //CC/Dsn   DAA AD A
D/D;D<DA#D&C)'D,D8DD	DDD)r   r   r   r   r   r   r   r"   )r   intr   r   r   r   r   floatr   rT   r   rT   r   boolreturnNone)r2   rD   r3   rS   rV   r   )r2   rD   r3   rS   rV   zModelResponse[ResponseT])rI   ModelRequest[ContextT]rJ   z<Callable[[ModelRequest[ContextT]], ModelResponse[ResponseT]]rV   $ModelResponse[ResponseT] | AIMessage)rI   rX   rJ   zGCallable[[ModelRequest[ContextT]], Awaitable[ModelResponse[ResponseT]]]rV   rY   )r0   
__module____qualname____firstlineno____doc__rD   r!   staticmethodr7   r>   rM   rQ   __static_attributes____classcell__)r$   s   @r%   r   r      s    Md &L * #": : 	:
 : : : : : 
: :x * *$.00 '0  N0  
.	0 d0 '0  Y0  
.	0  0 r'   r   )r]   
__future__r   rP   rE   typingr   langchain_core.messagesr   "langchain.agents.middleware._retryr   r   r   r	   r
   !langchain.agents.middleware.typesr   r   r   r   r   r   collections.abcr   r   r    r'   r%   <module>rh      sR    ( "     -   3Y ?:i+@(I+UV Y r'   