§
    ÷žyjß8 ã                  ó(  — d Z 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	m
Z
mZ  ej        e¦  «        Z G d„ dej        ¦  «        Ze G d„ d	¦  «        ¦   «         Zg d
¢ZdZ eddddddddeh	¦  «        Zg d¢Zg d¢Zg d¢Zg d¢Zg d¢Zg d¢Zg d¢Zg d¢Zg d¢ZdOd"„Zg d#¢Z g d$¢Z!g d%¢Z"g d&¢Z#g d'¢Z$d(gZ%g d)¢Z&g d*¢Z' eh d+£¦  «        Z(g d,¢Z)g d-¢Z*g d.¢Z+d/d/dd0dd1œdPd8„Z,dd9œdQd@„Z-dRdA„Z.dd9œdSdB„Z/dTdC„Z0dUdE„Z1dVdG„Z2dWdH„Z3dXdI„Z4dYdJ„Z5dZdL„Z6d[dN„Z7dS )\a«  API error classification for smart failover and recovery.

Provides a structured taxonomy of API errors and a priority-ordered
classification pipeline that determines the correct recovery action
(retry, rotate credential, fallback to another provider, compress
context, or abort).

Replaces scattered inline string-matching with a centralized classifier
that the main retry loop in run_agent.py consults for every API failure.
é    )ÚannotationsN)Ú	dataclassÚfield)ÚAnyÚDictÚOptionalc                  ón   — e Zd ZdZdZdZdZdZdZdZ	dZ
d	Zd
ZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdS )ÚFailoverReasonu8   Why an API call failed â€” determines recovery strategy.ÚauthÚauth_permanentÚbillingÚ
rate_limitÚupstream_rate_limitÚ
overloadedÚserver_errorÚtimeoutÚssl_cert_verificationÚcontext_overflowÚpayload_too_largeÚimage_too_largeÚmodel_not_foundÚprovider_policy_blockedÚcontent_policy_blockedÚformat_errorÚinvalid_encrypted_contentÚ#multimodal_tool_content_unsupportedÚthinking_signatureÚlong_context_tierÚ!oauth_long_context_beta_forbiddenÚllama_cpp_grammar_patternÚunknownN)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r    r!   © ó    ú</home/ragecks/.hermes/hermes-agent/agent/error_classifier.pyr
   r
      s©   € € € € € ØBÐBð €DØ%€Nð €GØ€Jð 0Ðð €JØ!€Lð €Gð
 4Ðð *ÐØ+ÐØ'€Oð (€OØ7ÐØ5Ðð "€LØ ;ÐØ*OÐ'ð .ÐØ+ÐØ(KÐ%Ø ;Ðð €G€G€Gr'   r
   c                  óÈ   — e Zd ZU dZded<   dZded<   dZded<   dZded	<   d
Zded<    e	e
¬¦  «        Zded<   dZded<   dZded<   dZded<   dZded<   edd„¦   «         ZdS )ÚClassifiedErrorz>Structured classification of an API error with recovery hints.r
   ÚreasonNúOptional[int]Ústatus_codeúOptional[str]ÚproviderÚmodelÚ ÚstrÚmessage)Údefault_factoryzDict[str, Any]Úerror_contextTÚboolÚ	retryableFÚshould_compressÚshould_rotate_credentialÚshould_fallbackÚreturnc                ó@   — | j         t          j        t          j        hv S ©N)r+   r
   r   r   )Úselfs    r(   Úis_authzClassifiedError.is_auth_   s   € àŒ{�~Ô2µNÔ4QÐRÐRÐRr'   )r;   r6   )r"   r#   r$   r%   Ú__annotations__r-   r/   r0   r3   r   Údictr5   r7   r8   r9   r:   Úpropertyr?   r&   r'   r(   r*   r*   M   sõ   € € € € € € àHÐHàÐÐÑØ!%€KÐ%Ð%Ð%Ñ%Ø"€HÐ"Ð"Ð"Ñ"Ø€EÐÐÐÑØ€GÐÐÐÑØ$) E¸$Ð$?Ñ$?Ô$?€MÐ?Ð?Ð?Ñ?ð €IÐÐÐÑØ!€OÐ!Ð!Ð!Ñ!Ø%*ÐÐ*Ð*Ð*Ñ*Ø!€OÐ!Ð!Ð!Ñ!àðSð Sð Sñ „XðSð Sð Sr'   r*   )zinsufficient creditsÚinsufficient_quotazinsufficient balancezcredit balancezcredits exhaustedzcredits have been exhaustedzno usable creditsztop up your creditszpayment requiredzbilling hard limitzexceeded your current quotazaccount is deactivatedzplan does not includezout of extra usagezout of fundszrun out of fundsÚbalance_depletedÚ model_not_supported_on_free_tierznot available on the free tierz$personal-team-blocked:spending-limitrC   Úbilling_not_activeÚpayment_requiredÚinsufficient_creditsÚno_usable_creditsrD   rE   Úmember_spend_cap_exceeded)z
rate limitr   ztoo many requestsÚ	throttledzrequests per minuteztokens per minutezrequests per dayztry again inzplease retry afterÚresource_exhaustedzrate increased too quicklyÚthrottlingexceptionztoo many concurrent requestsÚservicequotaexceededexceptionÚ
throttling)r   ztemporarily overloadedz!service is temporarily overloadedz%service may be temporarily overloadedzserver is overloadedzserver overloadedzservice overloadedzservice is overloadedzupstream overloadedzcurrently overloadedzat capacityzover capacity)zusage limitÚquotazlimit exceededúkey limit exceeded)z	try againÚretryz	resets atzreset inÚwaitzrequests remainingÚperiodicÚwindow)zrequest entity too largezpayload too largezerror code: 413Úrequest_too_largez request exceeds the maximum size)zimage exceedszimage too larger   zimage size exceedszimage dimensions exceedz"dimensions exceed max allowed sizezmax allowed size: 8000)ztext is not setz%tool message content must be a stringztool content must be a stringztool message must be a stringzexpected string, got listzexpected string, got arrayz tool_call.content must be string)zcontext lengthzcontext sizezmaximum contextztoken limitztoo many tokenszreduce the lengthzexceeds the limitzcontext windowzprompt is too longzprompt exceeds max lengthÚ
max_tokenszmaximum number of tokenszexceeds the max_model_lenÚmax_model_lenzprompt lengthúinput is too longzmaximum model lengthzcontext length exceededztruncating inputzslot contextÚ
n_ctx_slotu   è¶…è¿‡æœ€å¤§é•¿åº¦u   ä¸Šä¸‹æ–‡é•¿åº¦z.tokens in request more than max tokens allowedrY   zmax input tokenzinput tokenz*exceeds the maximum number of input tokenszmaximum allowed input length)	zis not a valid modelzinvalid modelzmodel not foundr   zdoes not existzno such modelzunknown modelzunsupported modelz(no endpoints found that support tool user0   r2   r/   r;   r6   c                óÈ   — | pd                      ¦   «         }|rd|v rdS 	 ddlm} t           ||pd                      ¦   «         |¦  «        ¦  «        S # t          $ r Y dS w xY w)uÆ  True when a bare model id is only known to the provider as ``vendor/id``.

    Some providers answer a malformed model id with a naked 404 that names
    nothing â€” NVIDIA NIM returns ``404 page not found`` for a bare
    ``nemotron-3-ultra-550b-a55b``, indistinguishable from a bad endpoint
    path. Consulting the curated catalogue tells the two apart: if the id
    carries no ``/`` but the catalogue has exactly one entry ending in
    ``/<id>``, the prefix was dropped and the failure is deterministic.

    Never guesses â€” an id absent from the catalogue (a local NIM container,
    a proxied model) returns False so genuine endpoint problems keep their
    retryable ``unknown`` classification.
    r1   ú/Fr   )Úsuggest_prefixed_model_id)ÚstripÚhermes_cli.model_normalizer]   r6   Ú	Exception)r0   r/   Únamer]   s       r(   Ú_model_id_missing_known_prefixrb   X  s“   € ð ˆK�R×ÒÑ Ô €DØð �3˜$�;�;ØˆuðØHÐHÐHÐHÐHÐHåÐ-Ð-¨x¨~¸2×.DÒ.DÑ.FÔ.FÈÑMÔMÑNÔNÐNøÝð ð ð Øˆuˆuðøøøs    2A Á
A!Á A!)zmust have non-empty contentzmessages must have non-emptyÚinvalid_request_bodyz%text content blocks must be non-emptyzcontent field is requiredz*messages: at least one message is required)zunknown parameterzunsupported parameterzunrecognized request argumentÚinvalid_request_errorÚunknown_parameterÚunsupported_parameter)z.no endpoints available matching your guardrailz0no endpoints available matching your data policyz,no endpoints found matching your data policy)
z'flagged for possible cybersecurity riskztrusted access for cyberzviolates our usage policiesz violates openai's usage policieszyour request was flagged byz prompt was flagged by our safetyz+responses cannot be generated due to safetyÚcontent_filterÚresponsibleaipolicyviolationÚnew_sensitive)
zinvalid api keyÚinvalid_api_keyÚgateway_auth_failedÚauthenticationÚunauthorizedÚ	forbiddenzinvalid tokenztoken expiredztoken revokedzaccess deniedÚ	signature)zreturned an empty responsezempty response despite retriesz#provider returned an empty responsezmodel returning empty responseszempty response stream)z	timed outzturn timed outzrequest timed outzdeadline exceededzoperation timed outzupstream timed out>   ÚSSLErrorÚ	ReadErrorÚPoolTimeoutÚReadTimeoutÚSSLEOFErrorÚConnectErrorÚTimeoutErrorÚConnectTimeoutÚAPITimeoutErrorÚBrokenPipeErrorÚConnectionErrorÚSSLSyscallErrorÚSSLWantReadErrorÚSSLWantWriteErrorÚAPIConnectionErrorÚSSLZeroReturnErrorÚRemoteProtocolErrorÚConnectionResetErrorÚConnectionAbortedErrorÚServerDisconnectedError)zserver disconnectedzpeer closed connectionzconnection reset by peerzconnection was closedznetwork connection lostzunexpected eofzincomplete chunked read)zcertificate verify failedÚcertificate_verify_failedz&unable to get local issuer certificatezself-signed certificatezself signed certificatezcertificate has expiredz+hostname mismatch, certificate is not validz&unable to verify the first certificate)zbad record macz	ssl alertz	tls alertzssl handshake failureztlsv1 alertzsslv3 alertÚbad_record_macÚ	ssl_alertÚ	tls_alertÚtls_alert_internal_errorz[ssl:r1   i@ )r/   r0   Úapprox_tokensÚcontext_lengthÚnum_messagesÚerrorr`   r‰   ÚintrŠ   r‹   c               óV  ‡ ‡‡‡‡‡— t          ‰ ¦  «        Št          ‰ ¦  «        j        }‰€|dk    rdŠt          ‰ ¦  «        Št	          ‰¦  «        }t          ‰ ¦  «                             ¦   «         }d}	d}
t          ‰t          ¦  «        �r­‰ 	                    di ¦  «        }t          |t          ¦  «        �rIt          | 	                    d¦  «        pd¦  «                             ¦   «         }	| 	                    di ¦  «        }t          |t          ¦  «        rè| 	                    d¦  «        pd}t          |t
          ¦  «        r¼| 
                    ¦   «         r¨	 d	dl}|                     |¦  «        }t          |t          ¦  «        ra| 	                    di ¦  «        }t          |t          ¦  «        r6t          | 	                    d¦  «        pd¦  «                             ¦   «         }
n# |j        t          f$ r Y nw xY w|	s6t          ‰ 	                    d¦  «        pd¦  «                             ¦   «         }	|g}|	r|	|vr|                     |	¦  «         |
r|
|vr|
|	vr|                     |
¦  «         d
                     |¦  «        Š‰pd 
                    ¦   «                              ¦   «         }‰pd 
                    ¦   «                              ¦   «         }d7ˆˆ ˆˆˆfd„}t#          ˆfd„t$          D ¦   «         ¦  «        r |t&          j        dd¬¦  «        S ‰dk    r(d‰v r$d‰v sd‰v sd‰v r |t&          j        dd¬¦  «        S ‰dk    r d‰v rd‰v r |t&          j        dd¬¦  «        S ‰dk    r d‰v rd‰v r |t&          j        dd¬¦  «        S ‰dk    r(d‰v sd‰v sd ‰v rd!‰v r |t&          j        dd¬¦  «        S d"‰v sd#‰v rd$‰v r |t&          j        dd¬¦  «        S ‰�t5          ‰‰|‰||||||¬%¦
  «
        }|�|S |d&k    r:d't          ‰ ¦  «        v sd(t          ‰ ¦  «        v r |t&          j        dd¬¦  «        S d	d)lm} t          ‰ |¦  «        r |t&          j        d¬*¦  «        S |rt?          |‰|¦  «        }|�|S tA          ‰||||¬+¦  «        }|�|S t#          ˆfd,„tB          D ¦   «         ¦  «        r |t&          j"        dd¬¦  «        S t#          ˆfd-„tF          D ¦   «         ¦  «        r |t&          j$        d¬*¦  «        S t#          ˆfd.„tJ          D ¦   «         ¦  «        }|rv‰std	d/l&m'}  |‰¦  «        � |t&          j$        d¬*¦  «        S ||d0z  k    p|d1k    o|d2k    p|d3k    }|r |t&          j(        dd¬¦  «        S  |t&          j$        d¬*¦  «        S |d4k    r d5‰v rd6‰v r |t&          j$        dd¬¦  «        S |tR          v s"t          ‰ tT          tV          tX          f¦  «        r |t&          j$        d¬*¦  «        S  |t&          j-        d¬*¦  «        S )8u¼  Classify an API error into a structured recovery recommendation.

    Priority-ordered pipeline:
      1. Special-case provider-specific patterns (thinking sigs, tier gates)
      2. HTTP status code + message-aware refinement
      3. Error code classification (from body)
      4. Message pattern matching (billing vs rate_limit vs context vs auth)
      5. SSL/TLS transient alert patterns â†’ retry as timeout
      6. Server disconnect + large session â†’ context overflow
      7. Transport error heuristics
      8. Fallback: unknown (retryable with backoff)

    Args:
        error: The exception from the API call.
        provider: Current provider name (e.g. "openrouter", "anthropic").
        model: Current model slug.
        approx_tokens: Approximate token count of the current context.
        context_length: Maximum context length for the current model.

    Returns:
        ClassifiedError with reason and recovery action hints.
    NÚRateLimitErroré­  r1   rŒ   r3   ÚmetadataÚrawr   Ú r+   r
   r;   r*   c                ór   •— | ‰‰‰t          ‰‰¦  «        dœ}|                     |¦  «         t          di |¤ŽS )N)r+   r-   r/   r0   r3   r&   )Ú_extract_messageÚupdater*   )r+   Ú	overridesÚdefaultsÚbodyrŒ   r0   r/   r-   s      €€€€€r(   Ú_resultz#classify_api_error.<locals>._resultÄ  sP   ø€ àØ&Ø ØÝ'¨¨tÑ4Ô4ð
ð 
ˆð 	�Š˜	Ñ"Ô"Ð"ÝÐ*Ð* Ð*Ð*Ð*r'   c              3  ó    •K  — | ]}|‰v V — Œ	d S r=   r&   ©Ú.0ÚpÚ	error_msgs     €r(   ú	<genexpr>z%classify_api_error.<locals>.<genexpr>Ø  s'   øè è € Ð
DÐ
D˜aˆ1�	ˆ>Ð
DÐ
DÐ
DÐ
DÐ
DÐ
Dr'   FT©r7   r:   é�  Úthinkingro   zcannot be modifiedzmust remain as they were©r7   r8   zextra usagezlong contextzlong context betaznot yet availablezerror parsing grammarzjson-schema-to-grammarzunable to generate parserÚtemplatez'do not have an active grok subscriptionzout of available resourcesÚgrok©r/   r0   r‰   rŠ   r‹   Ú	result_fnÚmoaz.'types.SimpleNamespace' object is not iterablez7'types.SimpleNamespace' object has no attribute 'index')ÚMoAPresetNotFoundError©r7   )r‰   rŠ   r¨   c              3  ó    •K  — | ]}|‰v V — Œ	d S r=   r&   rœ   s     €r(   r    z%classify_api_error.<locals>.<genexpr>‘  ó'   øè è € Ð
=Ð
=˜aˆ1�	ˆ>Ð
=Ð
=Ð
=Ð
=Ð
=Ð
=r'   c              3  ó    •K  — | ]}|‰v V — Œ	d S r=   r&   rœ   s     €r(   r    z%classify_api_error.<locals>.<genexpr>   s'   øè è € Ð
;Ð
;˜aˆ1�	ˆ>Ð
;Ð
;Ð
;Ð
;Ð
;Ð
;r'   c              3  ó    •K  — | ]}|‰v V — Œ	d S r=   r&   rœ   s     €r(   r    z%classify_api_error.<locals>.<genexpr>©  s'   øè è € ÐLÐL¨1˜˜Y˜ÐLÐLÐLÐLÐLÐLr'   )Ú!get_reasoning_stale_timeout_floorg333333ã?é è iÀÔ éÈ   ÚRuntimeErrorzconsecutive stale attemptszaborting this call)r+   r
   r;   r*   ).Ú_extract_status_codeÚtyper"   Ú_extract_error_bodyÚ_extract_error_coder2   ÚlowerÚ
isinstancerA   Úgetr^   ÚjsonÚloadsÚJSONDecodeErrorÚ	TypeErrorÚappendÚjoinÚanyÚ _CONTENT_POLICY_BLOCKED_PATTERNSr
   r   r   r   r   r    r   Ú_classify_by_statusr   Úagent.errorsrª   r   Ú_classify_by_error_codeÚ_classify_by_messageÚ_SSL_CERT_VERIFY_PATTERNSr   Ú_SSL_TRANSIENT_PATTERNSr   Ú_SERVER_DISCONNECT_PATTERNSÚagent.reasoning_timeoutsr°   r   Ú_TRANSPORT_ERROR_TYPESrv   rz   ÚOSErrorr!   )rŒ   r/   r0   r‰   rŠ   r‹   Ú
error_typeÚ
error_codeÚ_raw_msgÚ	_body_msgÚ_metadata_msgÚ_err_objÚ	_metadataÚ	_raw_jsonr»   Ú_innerÚ
_inner_errÚpartsÚprovider_lowerÚmodel_lowerrš   Ú
classifiedrª   Úis_disconnectr°   Úis_larger™   rŸ   r-   s   ```                       @@@r(   Úclassify_api_errorrÝ   p  s&  øøøøøø€ õ> ' uÑ-Ô-€KÝ�e‘”Ô%€Jð Ð˜zÐ-=Ò=Ð=ØˆÝ˜uÑ%Ô%€DÝ$ TÑ*Ô*€Jõ �5‰zŒz×ÒÑ!Ô!€HØ€IØ€MÝ�$�ÑÔñ ?Ø—8’8˜G RÑ(Ô(ˆÝ�h¥Ñ%Ô%ñ 	Ý˜HŸLšL¨Ñ3Ô3Ð9°rÑ:Ô:×@Ò@ÑBÔBˆIà Ÿš Z°Ñ4Ô4ˆIÝ˜)¥TÑ*Ô*ð Ø%ŸMšM¨%Ñ0Ô0Ð6°B�	Ý˜i­Ñ-Ô-ð 	°)·/²/Ñ2CÔ2Cð 	ðØ#˜˜˜Ø!%§¢¨IÑ!6Ô!6˜Ý% f­dÑ3Ô3ð ]Ø)/¯ª°G¸RÑ)@Ô)@˜JÝ)¨*µdÑ;Ô;ð ]Ý03°J·N²NÀ9Ñ4MÔ4MÐ4SÐQSÑ0TÔ0T×0ZÒ0ZÑ0\Ô0\ øøØ Ô0µ)Ð<ð ð ð Ø˜ðøøøàð 	?Ý˜DŸHšH YÑ/Ô/Ð5°2Ñ6Ô6×<Ò<Ñ>Ô>ˆIàˆJ€EØð  �Y hÐ.Ð.Ø�Š�YÑÔÐØð $˜¨hÐ6Ð6¸=ÐPYÐ;YÐ;YØ�Š�]Ñ#Ô#Ð#Ø—’˜‘”€IØ�n "×+Ò+Ñ-Ô-×3Ò3Ñ5Ô5€NØ�;˜B×%Ò%Ñ'Ô'×-Ò-Ñ/Ô/€Kð	+ð 	+ð 	+ð 	+ð 	+ð 	+ð 	+ð 	+ð 	+ð 	+õ( Ð
DÐ
DÐ
DÐ
DÕ#CÐ
DÑ
DÔ
DÑDÔDð 
ØˆwÝÔ1ØØ ð
ñ 
ô 
ð 	
ð2 	�sÒÐØ˜)Ð#Ð#à˜9Ð$Ð$Ø# yÐ0Ð0Ø)¨YÐ6Ð6ð ˆwÝÔ-ØØ!ð
ñ 
ô 
ð 	
ð 	�sÒÐØ˜YÐ&Ð&Ø˜iÐ'Ð'àˆwÝÔ,ØØ ð
ñ 
ô 
ð 	
ð 	�sÒÐØ 9Ð,Ð,Ø 9Ð,Ð,àˆwÝÔ<ØØ!ð
ñ 
ô 
ð 	
ð 	�sÒÐà# yÐ0Ð0Ø'¨9Ð4Ð4à+¨yÐ8Ð8Ø )Ð+Ð+ð ˆwÝÔ4ØØ!ð
ñ 
ô 
ð 	
ð4 	2°YÐ>Ð>Ø(¨IÐ5Ð5¸&ÀIÐ:MÐ:MàˆwÝÔØØ ð
ñ 
ô 
ð 	
ð ÐÝ(Ø˜ J°Ø#¨;Ø'¸Ø%Øð
ñ 
ô 
ˆ
ð Ð!ØÐð
 ˜ÒÐØ8½CÀ¹J¼JÐFÐFØDÍÈEÉ
Ì
ÐRÐRàˆwÝÔ'ØØ!ð
ñ 
ô 
ð 	
ð 4Ð3Ð3Ð3Ð3Ð3å�%Ð/Ñ0Ô0ð HØˆw•~Ô5ÀÐGÑGÔGÐGð ð Ý,¨Z¸ÀGÑLÔLˆ
ØÐ!ØÐõ &Ø�:Ø#Ø%Øð	ñ ô €Jð ÐØÐõ Ð
=Ð
=Ð
=Ð
=Õ#<Ð
=Ñ
=Ô
=Ñ=Ô=ð 
ØˆwÝÔ0ØØ!ð
ñ 
ô 
ð 	
õ Ð
;Ð
;Ð
;Ð
;Õ#:Ð
;Ñ
;Ô
;Ñ;Ô;ð ?Øˆw•~Ô-¸Ð>Ñ>Ô>Ð>õ ÐLÐLÐLÐLÕ0KÐLÑLÔLÑLÔL€MØð !?˜[ð !?ð$ 	OÐNÐNÐNÐNÐNØ,Ð,¨UÑ3Ô3Ð?Ø�7�>Ô1¸TÐBÑBÔBÐBð ! >°CÑ#7Ò7ð 
Ø˜fÒ$ÐW¨-¸&Ò*@Ð*VÀLÐSVÒDVð 	ð ð 	Ø�7ÝÔ/ØØ $ðñ ô ð ð
 ˆw•~Ô-¸Ð>Ñ>Ô>Ð>ð 	�nÒ$Ð$Ø(¨IÐ5Ð5Ø  IÐ-Ð-àˆwÝÔ"ØØ ð
ñ 
ô 
ð 	
ð Õ+Ð+Ð+­z¸%Å,ÕP_ÕahÐAiÑ/jÔ/jÐ+Øˆw•~Ô-¸Ð>Ñ>Ô>Ð>ð ˆ7•>Ô)°TÐ:Ñ:Ô:Ð:s   ÅBG+ Ç+G?Ç>G?)r‹   r-   rŸ   rÎ   r™   rA   úOptional[ClassifiedError]c               ó˜  ‡— | dk    r |	t           j        ddd¬¦  «        S | dk    r||dk    r|                     ¦   «         t          k    s(d‰v s$d‰v s t	          ˆfd	„t
          D ¦   «         ¦  «        r |	t           j        ddd¬¦  «        S  |	t           j        dd¬
¦  «        S | dk    rt          ‰|	¦  «        S | dk    rèt	          ˆfd„t
          D ¦   «         ¦  «        r |	t           j        ddd¬¦  «        S t	          ˆfd„t          D ¦   «         ¦  «        r |	t           j	        dd¬
¦  «        S t	          ˆfd„t          D ¦   «         ¦  «        r |	t           j        dd¬
¦  «        S t          ||¦  «        r |	t           j        dd¬
¦  «        S  |	t           j        d¬¦  «        S | dk    r |	t           j        dd¬¦  «        S | dk    r‘t	          ˆfd„t          D ¦   «         ¦  «        r |	t           j        d¬¦  «        S t#          ||¦  «        r1t%          |¦  «        }
|
rd|
ini } |	t           j        ddd|¬¦  «        S  |	t           j        ddd¬¦  «        S | dk    rt+          ‰||||||||	¬¦	  «	        S | dv rÕt	          ˆfd„t,          D ¦   «         ¦  «        s|                     ¦   «         dv r |	t           j        dd¬
¦  «        S t	          ˆfd„t0          D ¦   «         ¦  «        r |	t           j        dd¬¦  «        S t	          ˆfd„t4          D ¦   «         ¦  «        r |	t           j        dd¬¦  «        S  |	t           j        d¬¦  «        S | dv r‡t	          ˆfd„t0          D ¦   «         ¦  «        r |	t           j        dd¬¦  «        S t	          ˆfd „t4          D ¦   «         ¦  «        r |	t           j        dd¬¦  «        S  |	t           j        d¬¦  «        S | d!k    r |	t           j        d¬¦  «        S d| cxk    rd"k     rn n |	t           j        dd¬
¦  «        S d"| cxk    rd#k     rn n |	t           j        d¬¦  «        S d$S )%zAClassify based on HTTP status code with message-aware refinement.i‘  FT©r7   r9   r:   i“  z	xai-oauthrQ   zspending limitc              3  ó    •K  — | ]}|‰v V — Œ	d S r=   r&   rœ   s     €r(   r    z&_classify_by_status.<locals>.<genexpr>  s'   øè è € Ð=Ð= a�1˜	�>Ð=Ð=Ð=Ð=Ð=Ð=r'   r¡   i’  i”  c              3  ó    •K  — | ]}|‰v V — Œ	d S r=   r&   rœ   s     €r(   r    z&_classify_by_status.<locals>.<genexpr>+  s'   øè è € Ð9Ð9 !ˆq�Iˆ~Ð9Ð9Ð9Ð9Ð9Ð9r'   c              3  ó    •K  — | ]}|‰v V — Œ	d S r=   r&   rœ   s     €r(   r    z&_classify_by_status.<locals>.<genexpr>7  ó'   øè è € ÐIÐI !ˆq�Iˆ~ÐIÐIÐIÐIÐIÐIr'   c              3  ó    •K  — | ]}|‰v V — Œ	d S r=   r&   rœ   s     €r(   r    z&_classify_by_status.<locals>.<genexpr>=  s'   øè è € ÐAÐA !ˆq�Iˆ~ÐAÐAÐAÐAÐAÐAr'   r«   i�  r¤   r�   c              3  ó    •K  — | ]}|‰v V — Œ	d S r=   r&   rœ   s     €r(   r    z&_classify_by_status.<locals>.<genexpr>k  s'   øè è € Ð<Ð< !ˆq�Iˆ~Ð<Ð<Ð<Ð<Ð<Ð<r'   Úupstream_provider)r7   r9   r:   r5   r¢   r§   >   éö  éô  c              3  ó    •K  — | ]}|‰v V — Œ	d S r=   r&   rœ   s     €r(   r    z&_classify_by_status.<locals>.<genexpr>š  s'   øè è € ÐEÐE 1��Y�ÐEÐEÐEÐEÐEÐEr'   >   re   rd   rf   c              3  ó    •K  — | ]}|‰v V — Œ	d S r=   r&   rœ   s     €r(   r    z&_classify_by_status.<locals>.<genexpr>«  rä   r'   c              3  ó    •K  — | ]}|‰v V — Œ	d S r=   r&   rœ   s     €r(   r    z&_classify_by_status.<locals>.<genexpr>±  ó'   øè è € ÐBÐB !ˆq�Iˆ~ÐBÐBÐBÐBÐBÐBr'   >   é  é÷  c              3  ó    •K  — | ]}|‰v V — Œ	d S r=   r&   rœ   s     €r(   r    z&_classify_by_status.<locals>.<genexpr>¾  rä   r'   c              3  ó    •K  — | ]}|‰v V — Œ	d S r=   r&   rœ   s     €r(   r    z&_classify_by_status.<locals>.<genexpr>Ä  rí   r'   i˜  ré   éX  N)r
   r   r¸   Ú_XAI_SPENDING_LIMIT_ERROR_CODErÁ   Ú_BILLING_PATTERNSr   Ú_classify_402Ú!_PROVIDER_POLICY_BLOCKED_PATTERNSr   Ú_MODEL_NOT_FOUND_PATTERNSr   rb   r!   r   Ú_OVERLOADED_PATTERNSr   Ú_is_openrouter_upstream_errorÚ_extract_upstream_provider_namer   r   Ú_classify_400Ú_REQUEST_VALIDATION_PATTERNSr   Ú!_EMPTY_PROVIDER_RESPONSE_PATTERNSr   Ú_CONTEXT_OVERFLOW_PATTERNSr   r   )r-   rŸ   rÎ   r™   r/   r0   r‰   rŠ   r‹   r¨   rç   Úctxs    `          r(   rÃ   rÃ   ï  sW  ø€ ð �cÒÐð ˆyÝÔØØ%)Ø ð	
ñ 
ô 
ð 	
ð �cÒÐð
 ˜KÒ'Ð'Ø×$Ò$Ñ&Ô&Õ*HÒHÐHà# yÐ0Ð0Ø 9Ð,Ð,ÝÐ=Ð=Ð=Ð=Õ+<Ð=Ñ=Ô=Ñ=Ô=ð -ð �9ÝÔ&ØØ)-Ø $ð	ñ ô ð ð ˆyÝÔØØ ð
ñ 
ô 
ð 	
ð �cÒÐÝ˜Y¨	Ñ2Ô2Ð2à�cÒÐõ
 Ð9Ð9Ð9Ð9Õ'8Ð9Ñ9Ô9Ñ9Ô9ð 	Ø�9ÝÔ&ØØ)-Ø $ð	ñ ô ð õ ÐIÐIÐIÐIÕ'HÐIÑIÔIÑIÔIð 	Ø�9ÝÔ6ØØ %ðñ ô ð õ
 ÐAÐAÐAÐAÕ'@ÐAÑAÔAÑAÔAð 	Ø�9ÝÔ.ØØ $ðñ ô ð õ *¨%°Ñ:Ô:ð 	Ø�9ÝÔ.ØØ $ðñ ô ð ð ˆyÝÔ"Øð
ñ 
ô 
ð 	
ð
 �cÒÐØˆyÝÔ,ØØ ð
ñ 
ô 
ð 	
ð �cÒÐõ Ð<Ð<Ð<Ð<Õ';Ð<Ñ<Ô<Ñ<Ô<ð 	Ø�9ÝÔ)Øðñ ô ð õ )¨¨xÑ8Ô8ð 		Ý ?ÀÑ EÔ EÐØ>OÐWÐ&Ð(9Ð:Ð:ÐUWˆCØ�9ÝÔ2ØØ).Ø $Ø!ðñ ô ð ð ˆyÝÔ%ØØ%)Ø ð	
ñ 
ô 
ð 	
ð �cÒÐÝØ�z 4Ø UØ'Ø)Ø%Øð
ñ 
ô 
ð 	
ð �jÐ Ð õ ÐEÐEÐEÐEÕ(DÐEÑEÔEÑEÔEð		à×ÒÑ!Ô!ð &?ð ?ð ?ð �9ÝÔ+ØØ $ðñ ô ð õ ÐIÐIÐIÐIÕ'HÐIÑIÔIÑIÔIð 	Ø�9ÝÔ+ØØ %ðñ ô ð õ
 ÐBÐBÐBÐBÕ'AÐBÑBÔBÑBÔBð 	Ø�9ÝÔ/ØØ $ðñ ô ð ð
 ˆy�Ô4ÀÐEÑEÔEÐEà�jÐ Ð õ
 ÐIÐIÐIÐIÕ'HÐIÑIÔIÑIÔIð 	Ø�9ÝÔ+ØØ %ðñ ô ð õ
 ÐBÐBÐBÐBÕ'AÐBÑBÔBÑBÔBð 	Ø�9ÝÔ/ØØ $ðñ ô ð ð
 ˆy�Ô2¸dÐCÑCÔCÐCð �cÒÐØˆy�Ô/¸4Ð@Ñ@Ô@Ð@ð ˆkÐÐÒÐ˜CÒÐÐÐÐØˆyÝÔ'ØØ ð
ñ 
ô 
ð 	
ð ˆkÐÐÒÐ˜CÒÐÐÐÐØˆy�Ô4ÀÐEÑEÔEÐEàˆ4r'   c                óð   ‡ — t          ˆ fd„t          D ¦   «         ¦  «        }t          ˆ fd„t          D ¦   «         ¦  «        }|r|r |t          j        ddd¬¦  «        S  |t          j        ddd¬¦  «        S )u  Disambiguate 402: billing exhaustion vs transient usage limit.

    The key insight from OpenClaw: some 402s are transient rate limits
    disguised as payment errors.  "Usage limit, try again in 5 minutes"
    is NOT a billing problem â€” it's a periodic quota that resets.
    c              3  ó    •K  — | ]}|‰v V — Œ	d S r=   r&   rœ   s     €r(   r    z _classify_402.<locals>.<genexpr>î  ó'   øè è € ÐHÐH¨Q˜!˜y˜.ÐHÐHÐHÐHÐHÐHr'   c              3  ó    •K  — | ]}|‰v V — Œ	d S r=   r&   rœ   s     €r(   r    z _classify_402.<locals>.<genexpr>ï  s'   øè è € ÐVÐV°!˜q I˜~ÐVÐVÐVÐVÐVÐVr'   Trà   F)rÁ   Ú_USAGE_LIMIT_PATTERNSÚ_USAGE_LIMIT_TRANSIENT_SIGNALSr
   r   r   )rŸ   r¨   Úhas_usage_limitÚhas_transient_signals   `   r(   rõ   rõ   æ  s®   ø€ õ ÐHÐHÐHÐHÕ2GÐHÑHÔHÑHÔH€OÝÐVÐVÐVÐVÕ7UÐVÑVÔVÑVÔVÐàð 
Ð/ð 
àˆyÝÔ%ØØ%)Ø ð	
ñ 
ô 
ð 	
ð ˆ9ÝÔØØ!%Øð	ñ ô ð r'   c               ó,	  ‡ — t          ˆ fd„t          D ¦   «         ¦  «        r |t          j        d¬¦  «        S t          ˆ fd„t          D ¦   «         ¦  «        r |t          j        d¬¦  «        S |pd                     ¦   «         }	|	dk    sd‰ v sd‰ v rd‰ v sd	‰ v r |t          j        dd
¬¦  «        S t          ˆ fd„t          D ¦   «         ¦  «        s|	dv r |t          j	        d
d¬¦  «        S t          ˆ fd„t          D ¦   «         ¦  «        s|	dk    r5t                               d||‰ ¦  «          |t          j	        d
d¬¦  «        S t          ˆ fd„t          D ¦   «         ¦  «        r |t          j        dd
¬¦  «        S t          ˆ fd„t          D ¦   «         ¦  «        r |t          j        dd¬¦  «        S t          ˆ fd„t"          D ¦   «         ¦  «        r |t          j        d
d
¬¦  «        S t          ˆ fd„t&          D ¦   «         ¦  «        r |t          j        d
d¬¦  «        S t          ˆ fd„t*          D ¦   «         ¦  «        r |t          j        ddd¬¦  «        S t          ˆ fd„t.          D ¦   «         ¦  «        r |t          j        d
dd¬¦  «        S d}
t3          |t4          ¦  «        �r{|                     di ¦  «        }t3          |t4          ¦  «        rHt9          |                     d¦  «        pd¦  «                             ¦   «                              ¦   «         }
|
sHt9          |                     d¦  «        pd¦  «                             ¦   «                              ¦   «         }
|
sHt9          |                     d¦  «        pd¦  «                             ¦   «                              ¦   «         }
|
sr|                     d¦  «        }t3          |t4          ¦  «        rHt9          |                     d¦  «        pd¦  «                             ¦   «                              ¦   «         }
t=          |
¦  «        dk     p|
dv }||d z  k    p|d!k    o|d"k    p|d#k    }|r|r |t          j        dd¬¦  «        S  |t          j	        d
d¬¦  «        S )$uH   Classify 400 Bad Request â€” context overflow, format error, or generic.c              3  ó    •K  — | ]}|‰v V — Œ	d S r=   r&   rœ   s     €r(   r    z _classify_400.<locals>.<genexpr>  ó'   øè è € Ð
EÐ
E˜aˆ1�	ˆ>Ð
EÐ
EÐ
EÐ
EÐ
EÐ
Er'   Tr«   c              3  ó    •K  — | ]}|‰v V — Œ	d S r=   r&   rœ   s     €r(   r    z _classify_400.<locals>.<genexpr>!  r­   r'   r1   r   zencrypted content for itemzcould not be verifiedz0could not decrypt the provided encrypted_contentFr¡   c              3  ó,   •K  — | ]}|d k    ¯|‰v V — ŒdS )rd   Nr&   rœ   s     €r(   r    z _classify_400.<locals>.<genexpr>N  s>   øè è € ð -ð -˜qØÐ+Ò+Ð+ð �ˆNØ+Ð+Ð+Ð+ð-ð -r'   >   re   rf   c              3  ó    •K  — | ]}|‰v V — Œ	d S r=   r&   rœ   s     €r(   r    z _classify_400.<locals>.<genexpr>b  s'   øè è € ÐCÐC˜qˆA�ˆNÐCÐCÐCÐCÐCÐCr'   rc   u%  Malformed message array 400 (invalid request body) classified as format_error, NOT context overflow â€” failing fast + falling back instead of entering the compression loop. This usually means an empty-content assistant stub is in the transcript; num_messages=%s approx_tokens=%s. error=%.200sc              3  ó    •K  — | ]}|‰v V — Œ	d S r=   r&   rœ   s     €r(   r    z _classify_400.<locals>.<genexpr>w  r
  r'   r¤   c              3  ó    •K  — | ]}|‰v V — Œ	d S r=   r&   rœ   s     €r(   r    z _classify_400.<locals>.<genexpr>  ó'   øè è € Ð
>Ð
>˜aˆ1�	ˆ>Ð
>Ð
>Ð
>Ð
>Ð
>Ð
>r'   c              3  ó    •K  — | ]}|‰v V — Œ	d S r=   r&   rœ   s     €r(   r    z _classify_400.<locals>.<genexpr>‡  r
  r'   c              3  ó    •K  — | ]}|‰v V — Œ	d S r=   r&   rœ   s     €r(   r    z _classify_400.<locals>.<genexpr>�  r­   r'   c              3  ó    •K  — | ]}|‰v V — Œ	d S r=   r&   rœ   s     €r(   r    z _classify_400.<locals>.<genexpr>–  ó'   øè è € Ð
8Ð
8˜aˆ1�	ˆ>Ð
8Ð
8Ð
8Ð
8Ð
8Ð
8r'   rà   c              3  ó    •K  — | ]}|‰v V — Œ	d S r=   r&   rœ   s     €r(   r    z _classify_400.<locals>.<genexpr>�  ó'   øè è € Ð
5Ð
5˜aˆ1�	ˆ>Ð
5Ð
5Ð
5Ð
5Ð
5Ð
5r'   rŒ   r3   ÚerrorMessageÚ	errorArgsr+   é   >   r1   rŒ   gš™™™™™Ù?r±   i€8 éP   )rÁ   Ú!_MULTIMODAL_TOOL_CONTENT_PATTERNSr
   r   Ú_IMAGE_TOO_LARGE_PATTERNSr   r¸   r   rü   r   Ú_INVALID_MESSAGE_BODY_PATTERNSÚloggerÚwarningrý   r   rþ   r   rö   r   r÷   r   Ú_RATE_LIMIT_PATTERNSr   rô   r   r¹   rA   rº   r2   r^   Úlen)rŸ   rÎ   r™   r/   r0   r‰   rŠ   r‹   r¨   Úerror_code_lowerÚerr_body_msgÚerr_objÚ_argsÚ
is_genericrÜ   s   `              r(   rû   rû     sÔ  ø€ õ* Ð
EÐ
EÐ
EÐ
EÕ#DÐ
EÑ
EÔ
EÑEÔEð 
ØˆyÝÔ>Øð
ñ 
ô 
ð 	
õ Ð
=Ð
=Ð
=Ð
=Õ#<Ð
=Ñ
=Ô
=Ñ=Ô=ð 
ØˆyÝÔ*Øð
ñ 
ô 
ð 	
ð #Ð( b×/Ò/Ñ1Ô1ÐàÐ7Ò7Ð7Ø&¨)Ð3Ð3à(¨IÐ5Ð5Ø'¨9Ð4Ð4à=ÀÐJÐJàˆyÝÔ4ØØ!ð
ñ 
ô 
ð 	
õ0 	ð -ð -ð -ð -Õ$@ð -ñ -ô -ñ 	-ô 	-ð	
ð ÐMÐMÐMàˆyÝÔ'ØØ ð
ñ 
ô 
ð 	
õ  	ÐCÐCÐCÐCÕ$BÐCÑCÔCÑCÔCð
àÐ5Ò5Ð5å�Šð-ð
 ˜-¨ñ	
ô 	
ð 	
ð ˆyÝÔ'ØØ ð
ñ 
ô 
ð 	
õ Ð
EÐ
EÐ
EÐ
EÕ#DÐ
EÑ
EÔ
EÑEÔEð 
ØˆyÝÔ'ØØ!ð
ñ 
ô 
ð 	
õ Ð
>Ð
>Ð
>Ð
>Õ#=Ð
>Ñ
>Ô
>Ñ>Ô>ð 
ØˆyÝÔ+ØØ ð
ñ 
ô 
ð 	
õ Ð
EÐ
EÐ
EÐ
EÕ#DÐ
EÑ
EÔ
EÑEÔEð 
ØˆyÝÔ2ØØ!ð
ñ 
ô 
ð 	
õ
 Ð
=Ð
=Ð
=Ð
=Õ#<Ð
=Ñ
=Ô
=Ñ=Ô=ð 
ØˆyÝÔ*ØØ ð
ñ 
ô 
ð 	
õ Ð
8Ð
8Ð
8Ð
8Õ#7Ð
8Ñ
8Ô
8Ñ8Ô8ð 
ØˆyÝÔ%ØØ%)Ø ð	
ñ 
ô 
ð 	
õ Ð
5Ð
5Ð
5Ð
5Õ#4Ð
5Ñ
5Ô
5Ñ5Ô5ð 
ØˆyÝÔ"ØØ%)Ø ð	
ñ 
ô 
ð 	
ð €LÝ�$�ÑÔñ NØ—(’(˜7 BÑ'Ô'ˆÝ�g�tÑ$Ô$ð 	MÝ˜wŸ{š{¨9Ñ5Ô5Ð;¸Ñ<Ô<×BÒBÑDÔD×JÒJÑLÔLˆLàð 	JÝ˜tŸxšx¨	Ñ2Ô2Ð8°bÑ9Ô9×?Ò?ÑAÔA×GÒGÑIÔIˆLð ð 	OÝ˜tŸxšx¨Ñ7Ô7Ð=¸2Ñ>Ô>×DÒDÑFÔF×LÒLÑNÔNˆLØð 	NØ—H’H˜[Ñ)Ô)ˆEÝ˜%¥Ñ&Ô&ð NÝ" 5§9¢9¨XÑ#6Ô#6Ð#<¸"Ñ=Ô=×CÒCÑEÔE×KÒKÑMÔM�Ý�\Ñ"Ô" RÒ'ÐH¨<¸=Ð+H€Jð ˜~°Ñ3Ò3ð Ø˜&Ò ÐQ m°eÒ&;Ð&P¸|ÈbÒ?Pð ð ð 
�hð 
ØˆyÝÔ+ØØ ð
ñ 
ô 
ð 	
ð ˆ9ÝÔ#ØØðñ ô ð r'   c                óV  — |                       ¦   «         }|dv r |t          j        dd¬¦  «        S |t          v r |t          j        ddd¬¦  «        S |dv r |t          j        dd¬¦  «        S |dv r |t          j        dd¬	¦  «        S |d
k    r |t          j        dd¬¦  «        S dS )z:Classify by structured error codes from the response body.>   rK   rL   Úrate_limit_exceededT)r7   r9   Frà   >   Úinvalid_modelr   Úmodel_not_availabler¡   >   Úmax_tokens_exceededÚcontext_length_exceededr¤   r   N)r¸   r
   r   Ú_BILLING_ERROR_CODESr   r   r   r   )rÎ   rŸ   r¨   Ú
code_lowers       r(   rÅ   rÅ   Ô  s  € ð ×!Ò!Ñ#Ô#€JàÐOÐOÐOØˆyÝÔ%ØØ%)ð
ñ 
ô 
ð 	
ð Õ)Ð)Ð)ØˆyÝÔ"ØØ%)Ø ð	
ñ 
ô 
ð 	
ð ÐPÐPÐPØˆyÝÔ*ØØ ð
ñ 
ô 
ð 	
ð ÐGÐGÐGØˆyÝÔ+ØØ ð
ñ 
ô 
ð 	
ð Ð0Ò0Ð0ØˆyÝÔ4ØØ!ð
ñ 
ô 
ð 	
ð ˆ4r'   rÍ   c               ó2  ‡ — t          ˆ fd„t          D ¦   «         ¦  «        r |t          j        dd¬¦  «        S t          ˆ fd„t          D ¦   «         ¦  «        r |t          j        d¬¦  «        S t          ˆ fd„t          D ¦   «         ¦  «        r |t          j        d¬¦  «        S t          ˆ fd„t          D ¦   «         ¦  «        }|rTt          ˆ fd„t          D ¦   «         ¦  «        }|r |t          j
        ddd¬	¦  «        S  |t          j        d
dd¬	¦  «        S t          ˆ fd„t          D ¦   «         ¦  «        r |t          j        d¬¦  «        S t          ˆ fd„t          D ¦   «         ¦  «        r |t          j        d
dd¬	¦  «        S t          ˆ fd„t          D ¦   «         ¦  «        r |t          j
        ddd¬	¦  «        S t          ˆ fd„t           D ¦   «         ¦  «        r |t          j        dd
¬¦  «        S t          ˆ fd„t$          D ¦   «         ¦  «        r |t          j        dd¬¦  «        S t          ˆ fd„t(          D ¦   «         ¦  «        r |t          j        d
dd¬	¦  «        S t          ˆ fd„t,          D ¦   «         ¦  «        r |t          j        d
d
¬¦  «        S t          ˆ fd„t0          D ¦   «         ¦  «        r |t          j        d
d¬¦  «        S t          ˆ fd„t4          D ¦   «         ¦  «        r |t          j        d¬¦  «        S dS )zJClassify based on error message patterns when no status code is available.c              3  ó    •K  — | ]}|‰v V — Œ	d S r=   r&   rœ   s     €r(   r    z'_classify_by_message.<locals>.<genexpr>  s'   øè è € Ð
?Ð
?˜aˆ1�	ˆ>Ð
?Ð
?Ð
?Ð
?Ð
?Ð
?r'   Tr¤   c              3  ó    •K  — | ]}|‰v V — Œ	d S r=   r&   rœ   s     €r(   r    z'_classify_by_message.<locals>.<genexpr>  r
  r'   r«   c              3  ó    •K  — | ]}|‰v V — Œ	d S r=   r&   rœ   s     €r(   r    z'_classify_by_message.<locals>.<genexpr>  r­   r'   c              3  ó    •K  — | ]}|‰v V — Œ	d S r=   r&   rœ   s     €r(   r    z'_classify_by_message.<locals>.<genexpr>'  r  r'   c              3  ó    •K  — | ]}|‰v V — Œ	d S r=   r&   rœ   s     €r(   r    z'_classify_by_message.<locals>.<genexpr>)  s'   øè è € Ð"ZÐ"Z°a 1¨	 >Ð"ZÐ"ZÐ"ZÐ"ZÐ"ZÐ"Zr'   rà   Fc              3  ó    •K  — | ]}|‰v V — Œ	d S r=   r&   rœ   s     €r(   r    z'_classify_by_message.<locals>.<genexpr>=  r  r'   c              3  ó    •K  — | ]}|‰v V — Œ	d S r=   r&   rœ   s     €r(   r    z'_classify_by_message.<locals>.<genexpr>D  r  r'   c              3  ó    •K  — | ]}|‰v V — Œ	d S r=   r&   rœ   s     €r(   r    z'_classify_by_message.<locals>.<genexpr>M  r  r'   c              3  ó    •K  — | ]}|‰v V — Œ	d S r=   r&   rœ   s     €r(   r    z'_classify_by_message.<locals>.<genexpr>W  r
  r'   c              3  ó    •K  — | ]}|‰v V — Œ	d S r=   r&   rœ   s     €r(   r    z'_classify_by_message.<locals>.<genexpr>_  r  r'   c              3  ó    •K  — | ]}|‰v V — Œ	d S r=   r&   rœ   s     €r(   r    z'_classify_by_message.<locals>.<genexpr>k  s'   øè è € Ð
2Ð
2˜aˆ1�	ˆ>Ð
2Ð
2Ð
2Ð
2Ð
2Ð
2r'   c              3  ó    •K  — | ]}|‰v V — Œ	d S r=   r&   rœ   s     €r(   r    z'_classify_by_message.<locals>.<genexpr>u  r
  r'   r¡   c              3  ó    •K  — | ]}|‰v V — Œ	d S r=   r&   rœ   s     €r(   r    z'_classify_by_message.<locals>.<genexpr>}  r­   r'   c              3  ó    •K  — | ]}|‰v V — Œ	d S r=   r&   rœ   s     €r(   r    z'_classify_by_message.<locals>.<genexpr>‰  r­   r'   N)rÁ   Ú_PAYLOAD_TOO_LARGE_PATTERNSr
   r   r  r   r  r   r  r  r   r   rø   r   rô   r   rý   r   rþ   r   Ú_AUTH_PATTERNSr   rö   r   r÷   r   Ú_TIMEOUT_MESSAGE_PATTERNSr   )rŸ   rÍ   r‰   rŠ   r¨   r  r  s   `      r(   rÆ   rÆ     sB  ø€ õ Ð
?Ð
?Ð
?Ð
?Õ#>Ð
?Ñ
?Ô
?Ñ?Ô?ð 
ØˆyÝÔ,ØØ ð
ñ 
ô 
ð 	
õ Ð
EÐ
EÐ
EÐ
EÕ#DÐ
EÑ
EÔ
EÑEÔEð 
ØˆyÝÔ>Øð
ñ 
ô 
ð 	
õ Ð
=Ð
=Ð
=Ð
=Õ#<Ð
=Ñ
=Ô
=Ñ=Ô=ð 
ØˆyÝÔ*Øð
ñ 
ô 
ð 	
õ ÐHÐHÐHÐHÕ2GÐHÑHÔHÑHÔH€OØð 
Ý"Ð"ZÐ"ZÐ"ZÐ"ZÕ;YÐ"ZÑ"ZÔ"ZÑZÔZÐØð 	Ø�9ÝÔ)ØØ)-Ø $ð	ñ ô ð ð ˆyÝÔ"ØØ%)Ø ð	
ñ 
ô 
ð 	
õ Ð
8Ð
8Ð
8Ð
8Õ#7Ð
8Ñ
8Ô
8Ñ8Ô8ð 
ØˆyÝÔ%Øð
ñ 
ô 
ð 	
õ Ð
5Ð
5Ð
5Ð
5Õ#4Ð
5Ñ
5Ô
5Ñ5Ô5ð 
ØˆyÝÔ"ØØ%)Ø ð	
ñ 
ô 
ð 	
õ Ð
8Ð
8Ð
8Ð
8Õ#7Ð
8Ñ
8Ô
8Ñ8Ô8ð 
ØˆyÝÔ%ØØ%)Ø ð	
ñ 
ô 
ð 	
õ Ð
EÐ
EÐ
EÐ
EÕ#DÐ
EÑ
EÔ
EÑEÔEð 
ØˆyÝÔ'ØØ!ð
ñ 
ô 
ð 	
õ Ð
>Ð
>Ð
>Ð
>Õ#=Ð
>Ñ
>Ô
>Ñ>Ô>ð 
ØˆyÝÔ+ØØ ð
ñ 
ô 
ð 	
õ Ð
2Ð
2Ð
2Ð
2¥>Ð
2Ñ
2Ô
2Ñ2Ô2ð 
ØˆyÝÔØØ%)Ø ð	
ñ 
ô 
ð 	
õ Ð
EÐ
EÐ
EÐ
EÕ#DÐ
EÑ
EÔ
EÑEÔEð 
ØˆyÝÔ2ØØ!ð
ñ 
ô 
ð 	
õ Ð
=Ð
=Ð
=Ð
=Õ#<Ð
=Ñ
=Ô
=Ñ=Ô=ð 
ØˆyÝÔ*ØØ ð
ñ 
ô 
ð 	
õ Ð
=Ð
=Ð
=Ð
=Õ#<Ð
=Ñ
=Ô
=Ñ=Ô=ð AØˆy�Ô/¸4Ð@Ñ@Ô@Ð@àˆ4r'   r,   c                óN  — | }t          d¦  «        D ]’}t          |dd¦  «        }t          |t          ¦  «        r|c S t          |dd¦  «        }t          |t          ¦  «        rd|cxk    rdk     rn n|c S t          |dd¦  «        pt          |dd¦  «        }|�||u r n|}Œ“dS )	z?Walk the error and its cause chain to find an HTTP status code.é   r-   NÚstatuséd   rò   Ú	__cause__Ú__context__)ÚrangeÚgetattrr¹   r�   )rŒ   ÚcurrentÚ_ÚcodeÚcauses        r(   r´   r´   ‘  sØ   € à€GÝ�1‰XŒXð ð ˆÝ�w ¨tÑ4Ô4ˆÝ�d�CÑ Ô ð 	ØˆKˆKˆKå�w ¨$Ñ/Ô/ˆÝ�d�CÑ Ô ð 	 S¨DÐ%6Ð%6Ò%6Ð%6°3Ò%6Ð%6Ð%6Ð%6Ð%6ØˆKˆKˆKå˜ ¨dÑ3Ô3Ð\µw¸wÈÐW[Ñ7\Ô7\ˆØˆ=˜E WÐ,Ð,ØˆEØˆˆØˆ4r'   c                ó~  — | }t          d¦  «        D ]ª}t          |dd¦  «        }t          |t          ¦  «        r|c S t          |dd¦  «        }|�?	 |                     ¦   «         }t          |t          ¦  «        r|c S n# t
          $ r Y nw xY wt          |dd¦  «        pt          |dd¦  «        }|�||u r n|}Œ«i S )zKExtract the structured error body from an SDK exception or its cause chain.rB  r™   NÚresponserE  rF  )rG  rH  r¹   rA   r»   r`   )rŒ   rI  rJ  r™   rN  Ú	json_bodyrL  s          r(   r¶   r¶   ¤  s÷   € à€GÝ�1‰XŒXð ð ˆÝ�w ¨Ñ-Ô-ˆÝ�d�DÑ!Ô!ð 	ØˆKˆKˆKå˜7 J°Ñ5Ô5ˆØÐðØ$ŸMšM™OœO�	Ý˜i­Ñ.Ô.ð %Ø$Ð$Ð$Ð$ð%øåð ð ð Ø�ðøøøå˜ ¨dÑ3Ô3Ð\µw¸wÈÐW[Ñ7\Ô7\ˆØˆ=˜E WÐ,Ð,ØˆEØˆˆØ€Is   Á*B Â 
BÂBc                ó¨  — | sdS dd„}|                       di ¦  «        }t          |t          ¦  «        �r|                      d¦  «        p|                      d¦  «        pd}t          |t          ¦  «        r@|                     ¦   «         r,|                     ¦   «         dk    r|                     ¦   «         S |                      d	¦  «        }t          |t          ¦  «        rj|                     ¦   «                              d
¦  «        rCddl}	 |                     |¦  «        }n# |j        t          f$ r d}Y nw xY w ||¦  «        }|r|S |                       d¦  «        p+|                       d¦  «        p|                       d¦  «        pd}t          |t          t          f¦  «        r+t          |¦  «                             ¦   «         }|r|dk    r|S dS )z4Extract an error code string from the response body.r1   r;   r2   c                ór  — t          | t          ¦  «        sdS |                      di ¦  «        }t          |t          ¦  «        r�|                     d¦  «        p|                     d¦  «        pd}t          |t          ¦  «        r@|                     ¦   «         r,|                     ¦   «         dk    r|                     ¦   «         S |                      d¦  «        p|                      d¦  «        pd}t          |t          t
          f¦  «        r+t          |¦  «                             ¦   «         }|r|dk    r|S dS )zAExtract a code/type from a nested error payload dict (defensive).r1   rŒ   rK  rµ   Ú400rÎ   )r¹   rA   rº   r2   r^   r�   )ÚpayloadÚpayload_errorÚnestedrK  Útexts        r(   Ú_code_from_payloadz/_extract_error_code.<locals>._code_from_payloadÀ  s  € å˜'¥4Ñ(Ô(ð 	Ø�2ØŸš G¨RÑ0Ô0ˆÝ�m¥TÑ*Ô*ð 	&Ø"×&Ò& vÑ.Ô.ÐQ°-×2CÒ2CÀFÑ2KÔ2KÐQÈrˆFÝ˜&¥#Ñ&Ô&ð &¨6¯<ª<©>¬>ð &¸f¿lºl¹n¼nÐPUÒ>UÐ>UØ—|’|‘~”~Ð%Ø�{Š{˜6Ñ"Ô"ÐE g§k¢k°,Ñ&?Ô&?ÐEÀ2ˆÝ�d�S¥#˜JÑ'Ô'ð 	Ý�t‘9”9—?’?Ñ$Ô$ˆDØð ˜ š˜Ø�Øˆrr'   rŒ   rK  rµ   rR  r3   Ú{r   NrÎ   Ú	errorCode)r;   r2   )rº   r¹   rA   r2   r^   Ú
startswithr»   r¼   r½   r¾   r�   )	r™   rW  Ú	error_objrK  r3   r»   ÚinnerÚnested_coderV  s	            r(   r·   r·   »  sß  € àð Øˆrðð ð ð ð  —’˜ "Ñ%Ô%€IÝ�)�TÑ"Ô"ñ #Ø�}Š}˜VÑ$Ô$ÐC¨	¯ª°fÑ(=Ô(=ÐCÀˆÝ�d�CÑ Ô ð 	  T§Z¢Z¡\¤\ð 	 °d·j²j±l´lÀeÒ6KÐ6KØ—:’:‘<”<Ðð
 —-’- 	Ñ*Ô*ˆÝ�g�sÑ#Ô#ð 	#¨¯ª©¬×(BÒ(BÀ3Ñ(GÔ(Gð 	#ØˆKˆKˆKðØŸ
š
 7Ñ+Ô+��øØÔ(­)Ð4ð ð ð Ø���ðøøøà,Ð,¨UÑ3Ô3ˆKØð #Ø"Ð"ð �8Š8�FÑÔÐT˜tŸxšx¨Ñ5Ô5ÐT¸¿ºÀ+Ñ9NÔ9NÐTÐRT€DÝ�$��c˜
Ñ#Ô#ð Ý�4‰yŒy�ŠÑ Ô ˆØð 	�D˜E’M�MØˆKØˆ2s   ÄD" Ä"D8Ä7D8c                ó¸  — |�rÁ|                      di ¦  «        }t          |t          ¦  «        r[|                      dd¦  «        }t          |t          ¦  «        r0|                     ¦   «         r|                     ¦   «         dd…         S |                      dd¦  «        }t          |t          ¦  «        r0|                     ¦   «         r|                     ¦   «         dd…         S |                      dd¦  «        }t          |t          ¦  «        r0|                     ¦   «         r|                     ¦   «         dd…         S |                      d¦  «        }t          |t          ¦  «        r[|                      dd¦  «        }t          |t          ¦  «        r0|                     ¦   «         r|                     ¦   «         dd…         S t          | ¦  «        dd…         S )	z+Extract the most informative error message.rŒ   r3   r1   Nré   r  r  r+   )rº   r¹   rA   r2   r^   )rŒ   r™   r[  ÚmsgÚargsr+   s         r(   r•   r•   í  s—  € ð ñ ,Ø—H’H˜W bÑ)Ô)ˆ	Ý�i¥Ñ&Ô&ð 	)Ø—-’- 	¨2Ñ.Ô.ˆCÝ˜#�sÑ#Ô#ð )¨¯	ª	©¬ð )Ø—y’y‘{”{ 4 C 4Ô(Ð(Ø�hŠh�y "Ñ%Ô%ˆÝ�c�3ÑÔð 	% C§I¢I¡K¤Kð 	%Ø—9’9‘;”;˜t ˜tÔ$Ð$ð �hŠh�~ rÑ*Ô*ˆÝ�c�3ÑÔð 	% C§I¢I¡K¤Kð 	%Ø—9’9‘;”;˜t ˜tÔ$Ð$Ø�xŠx˜Ñ$Ô$ˆÝ�d�DÑ!Ô!ð 	,Ø—X’X˜h¨Ñ+Ô+ˆFÝ˜&¥#Ñ&Ô&ð ,¨6¯<ª<©>¬>ð ,Ø—|’|‘~”~ d s dÔ+Ð+åˆu‰:Œ:�d�s�dÔÐr'   r   c                óô  — t          | t          ¦  «        sdS |pd                     ¦   «                              ¦   «         }|                      d¦  «        }t          |t          ¦  «        sdS t          |                     d¦  «        pd¦  «                             ¦   «                              ¦   «         }|dk    rdS |dk    rdS |                     d¦  «        }t          |t          ¦  «        r
d	|v sd
|v rdS dS )u°  Detect OpenRouter's aggregator-wrapped upstream provider errors.

    OpenRouter returns errors from upstream model providers (DeepSeek,
    Anthropic, etc.) wrapped with the outer message "Provider returned error"
    and the real error nested in ``metadata.raw``. This signal means the
    user's OpenRouter key is healthy â€” the upstream provider is the one that
    failed â€” so credential rotation is the wrong recovery.
    Fr1   rŒ   r3   zprovider returned errorÚ
openrouterTr‘   r’   Úprovider_name)r¹   rA   r^   r¸   rº   r2   )r™   r/   rØ   ÚerrÚ	outer_msgr‘   s         r(   rù   rù     sÿ   € õ �d�DÑ!Ô!ð ØˆuØ�n "×+Ò+Ñ-Ô-×3Ò3Ñ5Ô5€NØ
�(Š(�7Ñ
Ô
€CÝ�c�4Ñ Ô ð ØˆuÝ�C—G’G˜IÑ&Ô&Ð,¨"Ñ-Ô-×3Ò3Ñ5Ô5×;Ò;Ñ=Ô=€IØÐ-Ò-Ð-Øˆuð ˜Ò%Ð%ØˆtØ�wŠw�zÑ"Ô"€HÝ�(�DÑ!Ô!ð Ø�ÐÐ˜_°Ð8Ð8àˆtØˆ5r'   r.   c                óˆ  — t          | t          ¦  «        sdS |                      d¦  «        }t          |t          ¦  «        sdS |                     d¦  «        }t          |t          ¦  «        sdS |                     d¦  «        }t          |t          ¦  «        r(|                     ¦   «         r|                     ¦   «         S dS )zCPull the upstream provider name out of OpenRouter's error metadata.NrŒ   r‘   rc  )r¹   rA   rº   r2   r^   )r™   rd  r‘   ra   s       r(   rú   rú   %  s®   € å�d�DÑ!Ô!ð ØˆtØ
�(Š(�7Ñ
Ô
€CÝ�c�4Ñ Ô ð ØˆtØ�wŠw�zÑ"Ô"€HÝ�h¥Ñ%Ô%ð ØˆtØ�<Š<˜Ñ(Ô(€DÝ�$�ÑÔð  §¢¡¤ð Ø�zŠz‰|Œ|ÐØˆ4r'   )r0   r2   r/   r2   r;   r6   )rŒ   r`   r/   r2   r0   r2   r‰   r�   rŠ   r�   r‹   r�   r;   r*   )r-   r�   rŸ   r2   rÎ   r2   r™   rA   r/   r2   r0   r2   r‰   r�   rŠ   r�   r‹   r�   r;   rÞ   )rŸ   r2   r;   r*   )rŸ   r2   rÎ   r2   r™   rA   r/   r2   r0   r2   r‰   r�   rŠ   r�   r‹   r�   r;   r*   )rÎ   r2   rŸ   r2   r;   rÞ   )
rŸ   r2   rÍ   r2   r‰   r�   rŠ   r�   r;   rÞ   )rŒ   r`   r;   r,   )rŒ   r`   r;   rA   )r™   rA   r;   r2   )rŒ   r`   r™   rA   r;   r2   )r™   r   r/   r2   r;   r6   )r™   r   r;   r.   )8r%   Ú
__future__r   ÚenumÚloggingÚdataclassesr   r   Útypingr   r   r   Ú	getLoggerr"   r  ÚEnumr
   r*   rô   ró   Ú	frozensetr-  r   rø   r  r  r>  r  r  rþ   r÷   rb   r  rü   rö   rÂ   r?  Ú_THINKING_SIG_PATTERNSrý   r@  rË   rÉ   rÇ   rÈ   rÝ   rÃ   rõ   rû   rÅ   rÆ   r´   r¶   r·   r•   rù   rú   r&   r'   r(   ú<module>rp     s!  ðð	ð 	ð #Ð "Ð "Ð "Ð "Ð "à €€€Ø €€€Ø (Ð (Ð (Ð (Ð (Ð (Ð (Ð (Ø &Ð &Ð &Ð &Ð &Ð &Ð &Ð &Ð &Ð &à	ˆÔ	˜8Ñ	$Ô	$€ð
0ð 0ð 0ð 0ð 0�T”Yñ 0ô 0ð 0ðj ðSð Sð Sð Sð Sñ Sô Sñ „ðSð4ð ð Ð ð2 "HÐ ð
 !�yØØØØØØØ&ØØ"ð
"ñ 
ô 
Ð ðð ð Ð ðHð ð Ð ð ð ð Ð ð	"ð 	"ð 	"Ð ð
ð 
ð 
Ð ð"
ð 
ð 
Ð ð.%ð %ð %Ð !ð ,ð ,ð ,Ð ð^ð ð Ð ð*ð ð ð ðP"ð "ð "Ð ð$ ð  ð  Ð ð4%ð %ð %Ð !ð.$ð $ð $Ð  ð>ð ð €ð ðÐ ð%ð %ð %Ð !ðð ð Ð ð #˜ð $ð $ð $ñ ô Ð ð4ð ð Ð ð,	ð 	ð 	Ð ð6ð ð Ð ð0 ØØØ Øðz;ð z;ð z;ð z;ð z;ð z;ðR ðtð tð tð tð tð tðnð ð ð ðL ðLð Lð Lð Lð Lð Lðb*ð *ð *ð *ð^Ið Ið Ið Ið\ð ð ð ð&ð ð ð ð./ð /ð /ð /ðdð ð ð ð4ð ð ð ð<ð ð ð ð ð r'   