
    `gj                        d Z ddlZddlZddlZddlmZ da ej                         ZdZ	dZ
dddd	d
ededededef
dZdedefdZdedz  dedz  dedefdZe
dd
ededz  dedz  dedededeeedz  f   fdZe
fdedefdZy)u   Retry utilities — jittered backoff for decorrelated retries.

Replaces fixed exponential backoff with jittered delays to prevent
thundering-herd retry spikes when multiple sessions hit the same
rate-limited provider concurrently.
    N)Any)g      >@g      N@g     V@      ^@   g      @r   g      ?
base_delay	max_delayjitter_ratioattemptr   r   r	   returnc                J   t         5  t        dz  at        }ddd       t        d| dz
        }|dk\  s|dk  r|}nt        |d|z  z  |      }t	        j
                         dz  z  dz  }t        j                  |      }|j                  d||z        }	||	z   S # 1 sw Y   xY w)aC  Compute a jittered exponential backoff delay.

    Args:
        attempt: 1-based retry attempt number.
        base_delay: Base delay in seconds for attempt 1.
        max_delay: Maximum delay cap in seconds.
        jitter_ratio: Fraction of computed delay to use as random jitter
            range.  0.5 means jitter is uniform in [0, 0.5 * delay].

    Returns:
        Delay in seconds: min(base * 2^(attempt-1), max_delay) + jitter.

    The jitter decorrelates concurrent retries so multiple sessions
    hitting the same provider don't all retry at the same instant.
       Nr   ?      l   yn< l    )	_jitter_lock_jitter_countermaxmintimetime_nsrandomRandomuniform)
r
   r   r   r	   tickexponentdelayseedrngjitters
             D/root/.hermes/venv/lib/python3.12/site-packages/agent/retry_utils.pyjittered_backoffr    $   s    . 
 1 1gk"H2~qJ!x-0)< LLNdZ/0J>D
--
C[[L501F6> s   BB"errorc                     | t        | dd      t        | dd      t        | dd      g}dj                  d |D              j                         S )zCBest-effort flattened provider error text for retry classification.messageNbodyresponse c              3   8   K   | ]  }|t        |        y w)N)str).0parts     r   	<genexpr>z_error_text.<locals>.<genexpr>U   s     D$43CCIDs   )getattrjoinlower)r!   partss     r   _error_textr0   M   sR     	y$'vt$z4(	E 88D%DDJJLL    base_urlmodelc                     | xs dj                         }|xs dj                         }t        |dd      }t        |      }|dk(  xr d|v xr d|v xr
 d|v xs d|v S )	aL  Return True for Z.AI Coding Plan transient overload 429s.

    The coding-plan endpoint reports overload as HTTP 429 with body code 1305
    and message "The service may be temporarily overloaded...". Treat only
    that narrow shape specially so ordinary quota/billing 429s still fail fast
    through the existing classifier.
     status_codeNi  zapi.z.ai/api/coding/paas/v4zglm-5.21305ztemporarily overloaded)r.   r,   r0   )r2   r3   r!   base
model_namestatustexts          r   is_zai_coding_overload_errorr<   X   s     N!!#D+2$$&JUM40FuD# 	A)T1	A#	A t^?74?	r1   short_attemptsdefault_waitr>   c                    t        |||      s|dfS | |k  r|dfS t        | |z
  dz
  t        t              dz
        }t        |   }t	        d||d      dfS )u7  Provider-aware rate-limit backoff.

    For most providers this returns ``default_wait`` unchanged. For Z.AI
    Coding Plan GLM-5.2 overloads, keep the first ``short_attempts`` retries on
    the normal short exponential schedule, then switch to progressively longer
    waits (30s → 60s → 90s → 120s, capped) plus light jitter.

    ``attempt`` is 1-based, matching the retry loop's logged attempt number.
    Returns ``(wait_seconds, reason_label)`` where ``reason_label`` is suitable
    for status/log decoration when a provider-specific policy fired.
    )r2   r3   r!   Nzai_coding_overload_shortr   g?r   zai_coding_overload_long)r<   r   len!_ZAI_CODING_OVERLOAD_LONG_BACKOFFr    )r
   r2   r3   r!   r?   r>   idxr   s           r   adaptive_rate_limit_backoffrF   l   su    ( (eTT!!. 888
g&*C0Q,RUV,V
WC237J A*
Y\]_yyyr1   c                 ,    | t        t              z   dz   S )u  Retry-loop ceiling needed for the full Z.AI overload backoff schedule.

    The adaptive policy runs ``short_attempts`` short retries, then walks the
    long-backoff table one entry per subsequent attempt. The retry loop gives
    up as soon as ``retry_count >= ceiling`` — and that check runs *before* the
    attempt's backoff is computed — so the ceiling must sit one past the final
    long-backoff entry for every long tier to actually execute.

    With the default ``api_max_retries`` (3) equal to ``short_attempts`` (3),
    the loop always gave up before reaching the long tier, leaving the whole
    long-backoff schedule as dead code. Callers extend the ceiling to this
    value for Z.AI Coding overload 429s so the 30/60/90/120s waits run.
    r   )rC   rD   r=   s    r   !zai_coding_overload_retry_ceilingrH      s     C ABBQFFr1   )__doc__r   	threadingr   typingr   r   Lockr   rD   #_ZAI_CODING_OVERLOAD_SHORT_ATTEMPTSintfloatr    r(   r0   boolr<   tuplerF   rH    r1   r   <module>rS      sI      
 y~~ %> ! '( # && & 	&
 & &RMs Ms McDj t TW \` 6 >zz Djz :	z
 z z z 5#*z@ =` Gc Gdg Gr1   