
    Áj                      U d dl mZ d dlZd dlZd dlZd dlmZmZm	Z	m
Z
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 d dlZddlmZ ddlmZ dd	l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)m*Z*m+Z+ ddl,m-Z- ddl.m/Z/ ddl0m1Z1 ddl2m3Z3 ddl4m5Z5 ddl6m7Z7 ddl8m9Z9 ddgZ: ejv                  d      Z<de=d<   dZ>dZ?de=d<   	 dXdZ@ G d  d      ZA ed!d"      ZBd#e=d$<    ed%d&"      ZCd'e=d(<    G d) de*      ZD G d* d+e      ZE G d, d-e      ZF G d. d/e      ZG G d0 d1e      ZH G d2 d3      ZIdYd4ZJdZd5ZK G d6 d7      ZLd[d8ZMd\d9ZN G d: d;      ZOd]d<ZPd^d=ZQd_d>ZRd`d?ZSdad@ZTdadAZUdbdBZVdcdCZWdddDZXdedEZYdfdFZZdgdGZ[dhdHZ\didIZ]djdJZ^dkdKZ_dldLZ`dldMZadmdNZbdndOZcdodPZd	 	 	 	 	 	 	 	 dpdQZedqdRZf	 	 	 	 	 	 drdSZg G dT dUej                        Zi G dV dWej                        Zky)s    )annotationsN)AnyDictListCallableIterableIteratorOptional	GeneratorAsyncIteratorAsyncGeneratorcast)Token
ContextVar)Literaloverride   )is_dict)	BaseModel)
APIRequest)APIResponseAsyncAPIResponse)StreamAsyncStreamServerSentEvent)AnthropicError)CallNext
MiddlewareAsyncCallNext)merge_headers)Message   )helper_header)BetaMessage)AnthropicBetaParam)BetaFallbackParam)BetaFallbackCreditTokenParamBetaFallbackStateBetaRefusalFallbackMiddlewarezanthropic.lib.middlewarezlogging.Loggerlogz/v1/messages)zfallback-credit-2026-07-01tuple[AnthropicBetaParam, ...]DEFAULT_BETASc                    | ddS )u   The retry's `fallback_credit_token`, in the object form.

    `best_effort` keeps the retry serving even when redemption fails — a bare
    string would 400 the hop on any token-layer failure.
    best_effort)tokenmode )r/   s    J/tmp/pip-target-k_scjv0h/lib/python/anthropic/lib/middleware/_fallbacks.py_credit_token_paramr3   5   s     M22    c                  6    e Zd ZU dZded<   	 ddZd	dZd
dZy)r(   u{  Tracks which fallback a sequence of requests is pinned to.

    Create one and enter it (`with state:` — the same context manager works for
    both clients) around every request that should share the pin — the turns of
    one conversation, or any wider scope the stickiness should apply to;
    `BetaRefusalFallbackMiddleware` mutates it in place when a model refuses.
    z
int | Noneindexc                    d | _         y N)r6   selfs    r2   __init__zBetaFallbackState.__init__N   s	    
r4   c                    t         j                  |       }t        j                  g t        j                         |       | S r8   )_fallback_stateset_fallback_state_tokensget)r:   r/   s     r2   	__enter__zBetaFallbackState.__enter__Q   s:    ##D)""#I%;%?%?%A#I5#IJr4   c                    t         j                         }t         j                  |d d        t        j	                  |d          y )N)r?   r@   r>   r=   reset)r:   exc_infotokenss      r2   __exit__zBetaFallbackState.__exit__V   s6    '++-""6#2;/fRj)r4   NreturnNone)rI   r(   )rE   objectrI   rJ   )__name__
__module____qualname____doc____annotations__r;   rA   rG   r1   r4   r2   r(   r(   >   s#     
*r4   anthropic_beta_fallback_state)defaultz$ContextVar[BetaFallbackState | None]r=   $anthropic_beta_fallback_state_tokensr1   z7ContextVar[tuple[Token[BetaFallbackState | None], ...]]r?   c                     e Zd ZdZdd	 	 	 	 	 ddZedd       Zedd       ZddZddZ	dd	Z
	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 dd
Z	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 ddZ	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 ddZ	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 ddZy)r)   u  Middleware that retries refused beta `/v1/messages` requests down a
    fallback chain, reproducing the server-side `fallbacks` wire shape
    client-side.

    Only `client.beta.messages` requests are handled — refusals minted by the
    first-party `client.messages` surface carry no `fallback_credit_token`, so
    those requests pass through untouched.

    Each `fallbacks` entry is a patch against the ORIGINAL request params: a
    field set to a value overrides it, a field explicitly `None` unsets it, an
    absent field keeps the original value; `output_config` patches its
    subfields the same way one level deep. Hops never compound — every hop
    patches the original params, never the previous hop's patched request.

    Non-streaming: when a response comes back with `stop_reason: "refusal"`, the
    request is retried with each entry of `fallbacks` applied as a patch to the
    original params — passing along the refusal's `fallback_credit_token` (in
    the object form, with `mode: "best_effort"`) when it minted one — until a
    model accepts or the chain is exhausted. A `fallback` seam
    block per model boundary is prepended to the served message's content —
    the same block shape the streaming splice emits. The served hop's `usage`
    is left verbatim (streaming rewrites it to per-hop `usage.iterations`).

    Streaming: when the stream ends in `stop_reason: "refusal"`, a second
    request is issued to the fallback model. It carries the refusal's
    `fallback_credit_token`, plus the refused model's partial output as a
    trailing assistant prefill when the refusal grants one
    (`fallback_has_prefill_claim`). The fallback's events are then spliced onto
    the still-open stream, so the client sees one continuous message in the
    server-side `fallbacks` wire shape: a `fallback` content block at each
    model boundary, monotonic block indices, and per-hop `usage.iterations` on
    the final `message_delta`. A refusal before any output streamed retries
    even without a credit token, and the serving hop's `message_start` opens
    the wire carrying the primary's message id.

    The fallback-credit beta the credit tokens require is sent by default on
    every request the middleware handles; the `betas` option controls this.

    In both modes a fallback that itself refuses with a fresh credit token
    continues down the chain. A streaming fallback whose appended prefill the
    server rejects (HTTP 400 body mismatch) is retried once without it; a
    fallback whose request fails outright is skipped — its token was never
    redeemed, so it carries to the next entry. When every remaining entry fails
    over HTTP, the suppressed refusal is replayed to the client with
    `recommended_model` stamped from the final failure (the failed model for
    capacity errors, `null` otherwise). A refusal surfaced to the client rather
    than retried is reported through the `anthropic.lib.middleware` logger.

    To keep later requests on the model that accepted, run them inside a shared
    `BetaFallbackState` context; requests sharing that state start directly at
    the pinned fallback. Reuse one state across whatever scope the pin should
    apply to — typically a conversation. The state is the only pin: `fallback`
    seam blocks replayed in the request history are stripped from the outgoing
    request (an assistant turn left empty by the strip is dropped whole), never
    read back as a pin.

    ```py
    client = Anthropic(middleware=[BetaRefusalFallbackMiddleware([{"model": "claude-opus-4-8"}])])

    state = BetaFallbackState()
    with state:
        message = client.beta.messages.create(**params)
    ```
    N)betasc               b    t        |      | _        |t        n
t        |      | _        d| _        y)u  
        Args:
            fallbacks: The fallback chain, tried in order. An empty chain disables
                the middleware.

            betas: Betas added to the `anthropic-beta` header of every `/v1/messages`
                request this middleware handles — the original request included, since
                refusals only carry a `fallback_credit_token` when the beta is enabled.
                Defaults to `("fallback-credit-2026-07-01",)`; pass `()` to send none.
        NF)tuple
_fallbacksr,   _betas_warned_missing_state)r:   	fallbacksrU   s      r2   r;   z&BetaRefusalFallbackMiddleware.__init__   s)       	*',}m%,%*"r4   c           	        | j                  |      }| ||      S t        j                         }| j                  |      }| j	                  |      }t        || j                        }t        |      }|dk(  r|nt        || j                  |         }|j                  |      } ||      }	|	j                  j                  s|	S |j                  rS|dz   }
|
t        | j                        k\  r|	S | j                  ||t!        |j                  d      xs d      |	||
|      S |}|	}t!        |j                  d      xs d      }g }|t        | j                        dz
  k  r"|j                  j                  r|j#                         }t%        |t&        t(        f      r|j*                  dk7  rn|dz  } ||       t-        |      }t/        |      } ||j                  t1        || j                  |   |                  }|j                  j                  r9t!        | j                  |   d         }|j3                  t5        |||             |}|t        | j                        dz
  k  r|j                  j                  r|rW|j                  j                  rA|j#                         }t%        |t&        t(        f      r|j*                  dk7  rt7        ||      S |S NrC   body   model requestr_   initial_modelresponse	call_next	first_hoppinrefusal)_applicable_bodyr=   r@   _start_index	_make_pin_with_middleware_headersrY   _strip_seam_blocks
_apply_hoprX   copyhttp_response
is_successstreamlen_splice_fallback_streamstrparse
isinstancer!   r$   stop_reason_credit_token_refusal_category_merged_bodyappend_seam_block_prepend_seam_blocksr:   rd   rg   r_   statestart_indexri   initial_bodyinitial_requestrf   rh   r6   res
from_modelseamsmessager/   categoryto_modelserveds                       r2   handlez$BetaRefusalFallbackMiddleware.handle   s   $$W-<W%%##%''.nnU# +7DKK@
 "$'*b0tjtWbGc6d!,,L,9_-%%00O>>#aI C00//'!,"2"27";"ArB!## 0   ))'28b9
&(c$//*Q..33D3D3O3OiikGg'=>'BUBUYbBbQJEJ!'*E(1HGLLl4QVAWY^._L`aC  ++tu5g>?[XxHI%
 c$//*Q..33D3D3O3O S&&11YY[F&7K"89f>P>PT]>] ,C77
r4   c           	     4  K   | j                  |      }| ||       d {   S t        j                         }| j                  |      }| j	                  |      }t        || j                        }t        |      }|dk(  r|nt        || j                  |         }|j                  |      } ||       d {   }	|	j                  j                  s|	S |j                  rS|dz   }
|
t        | j                        k\  r|	S | j                  ||t!        |j                  d      xs d      |	||
|      S |}|	}t!        |j                  d      xs d      }g }|t        | j                        dz
  k  r2|j                  j                  r|j#                          d {   }t%        |t&        t(        f      r|j*                  dk7  rn|dz  } ||       t-        |      }t/        |      } ||j                  t1        || j                  |   |                   d {   }|j                  j                  r9t!        | j                  |   d         }|j3                  t5        |||             |}|t        | j                        dz
  k  r|j                  j                  r|r_|j                  j                  rI|j#                          d {   }t%        |t&        t(        f      r|j*                  dk7  rt7        ||      S |S 7 7 T7 q7 7 Bwr]   )rk   r=   r@   rl   rm   rn   rY   ro   rp   rX   rq   rr   rs   rt   ru   _splice_fallback_stream_asyncrw   rx   ry   r!   r$   rz   r{   r|   r}   r~   r   _prepend_seam_blocks_asyncr   s                       r2   handle_asyncz*BetaRefusalFallbackMiddleware.handle_async  s    $$W-<"7+++##%''.nnU# +7DKK@
 "$'*b0tjtWbGc6d!,,L,9"?33%%00O>>#aI C0055'!,"2"27";"ArB!## 6   ))'28b9
&(c$//*Q..33D3D3O3OIIK'Gg'=>'BUBUYbBbQJEJ!'*E(1H!',,LtW\G]_d4e,"fggC  ++tu5g>?[XxHI%
 c$//*Q..33D3D3O3O S&&1199;&F&7K"89f>P>PT]>] 2#u==
 ," 42 ( h 'sa   LLBL:L;C%L L!B L!L"BL(+LL8LLLLLc                `   t        |j                        }t        j                  |j                        }| j
                  rP|j                  j                         dk7  s3|j                  t        k7  s |j                  j                  d      dk7  s|y|j                  d      t        d      |S )zMThe request's JSON body when this middleware applies to it, `None` otherwise.postbetatrueNr[   az  Sending the `fallbacks:` request param is not supported when using the `BetaRefusalFallbackMiddleware`. You should either remove the middleware and send `fallbacks:` with the `server-side-fallback-2026-07-01` beta header to let the API handle refusal fallbacks, or omit the `fallbacks:` param if you'd like `BetaRefusalFallbackMiddleware` to handle fallbacks on the client side.)_as_dictjsonhttpxURLurlrX   methodlowerpath_MESSAGES_PATHparamsr@   r   )r:   rd   r_   r   s       r2   rk   z.BetaRefusalFallbackMiddleware._applicable_bodyH  s    %ii$  ~~##%/xx>)zz~~f%/|88K , 0  r4   c                    ||j                   y|j                   }d|cxk  rt        | j                        k  s'n t        d| dt        | j                         d      |S )zThe chain entry this request starts at (-1 = the original params).

        Only an explicit `BetaFallbackState` pin moves the start; without one
        the request starts at the original params.
        rC   zBetaFallbackState.index z! is out of bounds for a chain of z? fallback(s); was the state shared with a different middleware?)r6   ru   rX   r   )r:   r   r   s      r2   rl   z*BetaRefusalFallbackMiddleware._start_indexb  sk     =EKK/kk[73t#77 *;-7Xt'((gi  r4   c                     d fd}|S )zUPin requests sharing the state to the entry being tried (or warn that there is none).c                l    | _         y j                  sd_        t        j                  d       y y )NTzanthropic-sdk: BetaRefusalFallbackMiddleware fell back without an active BetaFallbackState; follow-up requests will retry models that already refused. Run them inside a shared `with BetaFallbackState():` block to pin them to the accepted model.)r6   rZ   r*   warning)r6   r:   r   s    r2   ri   z4BetaRefusalFallbackMiddleware._make_pin.<locals>.pinu  s7     #//-1*& 0r4   )r6   intrI   rJ   r1   )r:   r   ri   s   `` r2   rm   z'BetaRefusalFallbackMiddleware._make_pinr  s    
	 
r4   c          	         | j                  |||||||      }t        t        |j                  t	        |            |j
                  |j                  d|j                  |j                  |j                        S )u9  Wrap the refusable stream in a response whose body passes events through
        until a retryable refusal, then splices the fallback chain's events on.

        `body` is the original request params — every hop patches it, never the
        previous hop's patched body; `initial_model` is the model the initial
        request actually queried (the pinned entry's when a state pin applied).

        Closing the returned response (or the `Stream` parsed from it) tears down
        whichever stream is being read and abandons any in-flight fallback request.
        rc   Trawcast_toclientrt   
stream_clsoptionsretries_taken)
_spliced_framesr   _spliced_http_responserr   _FrameByteStream_cast_to_client_stream_cls_optionsr   	r:   rd   r_   re   rf   rg   rh   ri   framess	            r2   rv   z5BetaRefusalFallbackMiddleware._splice_fallback_stream  s    * %%' & 
 &x'='=?OPV?WX%%##++%%"00
 	
r4   c          	         | j                  |||||||      }t        t        |j                  t	        |            |j
                  |j                  d|j                  |j                  |j                        S )Nrc   Tr   )
_spliced_frames_asyncr   r   rr   _AsyncFrameByteStreamr   r   r   r   r   r   s	            r2   r   z;BetaRefusalFallbackMiddleware._splice_fallback_stream_async  s     ++' , 
  &x'='=?TU[?\]%%##++%%"00
 	
r4   c          
   #  .  K   | j                   }|j                  }		 |j                  }
t        ddd dd g       }t        |
|      E d {   }|j                  	 |	|	j                          y y |
j                          d }	t        j                  |||      }t        |t        |            D ]w  }||   }t        |d         }|dz   t        |      k  } ||       |j                         }d }d }t        d      D ]  }|j                  |j                  ||            }	  ||      }|j                  j$                  r|j                  }	 nt'        |j                        }|j                  j                          |dk(  r?|j(                  dk(  r0|r.t        j+                  dt-        |             |j.                  }d }t        j!                  d||j(                  t-        |             t#        ||j(                  
      } n |3|r`|j1                  |      D ]  }|   |	|	j                          y y |J |j                  }|j3                  |       t        |j4                  |t7        |j8                  |      |j:                  |j<                  |j?                               }t        ||      E d {   }|j@                  r|jC                          |j                   |	|	j                          y y |j                          d }	|jE                  |||       z 	 |	|	j                          y y 7 # t        $ r0}t        j!                  d	||       t#        |d 
      }Y d }~ md }~ww xY w7 # |	|	j                          w w xY wwNr   TF)
index_basehas_nextsplice	wire_open
primary_idseam_framesra   r`   r"   r^   zOanthropic-sdk: BetaRefusalFallbackMiddleware: fallback request to %s failed: %s)ra   statusi  zanthropic-sdk: BetaRefusalFallbackMiddleware: fallback request with the partial output appended was rejected (HTTP 400: %s); retrying without itzXanthropic-sdk: BetaRefusalFallbackMiddleware: fallback request to %s failed: HTTP %s: %s)
iterationsra   )#rX   rr   
_HopReader
_drive_hoprefusedclose_ChainStatebeginrangeru   rw   continuationrq   hop_body	Exceptionr*   error_HopFailurers   
_read_jsonstatus_coder   _json_dumpsbaseterminal_failure_frames
queue_seam
next_index_SpliceInfor   r   r   pending_seam_framesopenedmark_openedabsorb_refusal)r:   rd   r_   re   rf   rg   rh   ri   r[   currentstream_areaderoutcomechainhopentryra   r   r   res_bfailureattempthop_requesterrerr_bodyframehop_responses                              r2   r   z-BetaRefusalFallbackMiddleware._spliced_frames  s     OO	)1)?)?k	 --HF ",Hf!==G&x " #w NNG  %%dM7CEYI7 SC!#E'N+7S^3C  %11315.2$Qx !G"),,ENN5,4W,"XK	 )+ 6 **55"'"5"5)%*=*=>H''--/!|(9(9S(@\g'1
 (-zz $ IIr))#H-	 *e>O>OPGC!F &  "'!>!>w!G $#$6 " #1 ((($22  '#$//%&%2B2B%P#oo$// % 9 9 ; &0f%EE>>%%'??* " # ""$
 $$We\BgSCj " #} >8 % 		m!
 #.E$"Gj F " #s   N,M= L<	M= N.B3M= "L?*C=M= 'N;BM= =M;>-M= +N?(M= (N<M= ?	M8$M3,M= 3M88M= =NNc          
    B  K   | j                   }|j                  }		 |j                  }
t        ddd dd g       }t        |
|      2 3 d {   }| 7 
6 |j	                         }|j
                  	 |	|	j                          d {  7   y y |
j                          d {  7   d }	t        j                  |||      }t        |t        |            D ]  }||   }t        |d         }|dz   t        |      k  } ||       |j                         }d }d }t        d      D ]_  }|j                  |j                  ||            }	  ||       d {  7  }n;# t        $ r/}t         j#                  d	||       t%        |d 
      }Y d }~ nd }~ww xY w|j                  j&                  r|j                  }	 nt)        |j                         d {  7  }|j                  j                          d {  7   |dk(  r@|j*                  dk(  r1|r/t         j-                  dt/        |             |j0                  }d }t         j#                  d||j*                  t/        |             t%        ||j*                  
      } n |=|r|j3                  |      D ]  }| 	  |	|	j                          d {  7   y y |J |j                  }|j5                  |       t        |j6                  |t9        |j:                  |      |j<                  |j>                  |jA                               }t        ||      2 3 d {  7  }| 6 |j	                         }|jB                  r|jE                          |j
                   |	|	j                          d {  7   y y |j                          d {  7   d }	|jG                  |||        	 |	|	j                          d {  7   y y # |	|	j                          d {  7   w w xY wwr   )$rX   rr   r   _drive_hop_asyncfinishr   acloser   r   r   ru   rw   r   rq   r   r   r*   r   r   rs   _read_json_asyncr   r   r   r   r   r   r   r   r   r   r   r   r   r   r   )r:   rd   r_   re   rf   rg   rh   ri   r[   r   r   r   r   r   r   r   r   ra   r   r   r   r   r   r   r   r   r   s                              r2   r   z3BetaRefusalFallbackMiddleware._spliced_frames_asynca  s     OO	)1)?)?b	'--HF  0&A  eAmmoG&b "nn&&& #a //###G%%dM7CEYI7 IC!#E'N+7S^3C$1136:.2$Qx !G"),,ENN5,4W,"XK	&/&< < <$ 		m!
 #.E$"G **55"'"5"5%5e6I6I%JJJH--44666!|(9(9S(@\g'1
 (-zz $ IIr))#H-	 *e>O>OPGC!F & !&!>!>w!G $#$2 "nn&&& #/ ((($22  '#$//%&%2B2B%P#oo$// % 9 9 ; $4L&#I    %K $J --/>>%%'??* "nn&&& # #))+++$$We\BSICV "nn&&& #w"nn&&& #s"  P)O> A	A
AO> AO> 4P	B
PO> $B'%B(O> E EE O>  	F)$FO> F?O> G"O> :G=;B1O> ,PKP	A?O> MMMAO> P'N*(P/O> OO> !P6O97P>PPPP)r[   zIterable[BetaFallbackParam]rU   z#Iterable[AnthropicBetaParam] | NonerI   rJ   )rd   r   rg   r   rI   APIResponse[Any])rd   r   rg   r   rI   AsyncAPIResponse[Any])rd   r   rI   dict[str, Any] | None)r   BetaFallbackState | NonerI   r   )r   r   rI   Callable[[int], None])rd   r   r_   dict[str, Any]re   rw   rf   r   rg   r   rh   r   ri   r   rI   r   )rd   r   r_   r   re   rw   rf   r   rg   r   rh   r   ri   r   rI   r   )rd   r   r_   r   re   rw   rf   r   rg   r   rh   r   ri   r   rI   Generator[bytes, None, None])rd   r   r_   r   re   rw   rf   r   rg   r   rh   r   ri   r   rI   AsyncGenerator[bytes, None])rL   rM   rN   rO   r;   r   r   r   rk   rl   rm   rv   r   r   r   r1   r4   r2   r)   r)   h   s   ?J 6:	+.+ 3	+
 
+( B BH B BH4 "&
 &
 	&

 &
 #&
 &
 &
 #&
 
&
P
 
 	

 
 (
 !
 
 #
 

tz  z  	z 
 z  #z  z  z  #z  
&z xq' q' 	q'
 q' (q' !q' q' #q' 
%q'r4   c                  D    e Zd ZU ded<   	 ded<   	 ded<   ded<   ded<   y	)
_RefusalOptional[str]r/   r   boolhas_prefill_claimDict[str, Any]usageeventN)rL   rM   rN   rP   r1   r4   r2   r   r     s+    SS(r4   r   c                  &    e Zd ZU dZded<   ded<   y)r   z6Splice context for fallback hops; `None` for stream A.List[Dict[str, Any]]r   rw   ra   NrL   rM   rN   rO   rP   r1   r4   r2   r   r     s    @$$Jr4   r   c                  &    e Zd ZU dZded<   ded<   y)r   z[A fallback hop whose request failed; stamps `recommended_model` when it
    ends the chain.rw   ra   zOptional[int]r   Nr  r1   r4   r2   r   r     s     JRr4   r   c                  d    e Zd ZU dZded<   	 ded<   	 ded<   	 ded	<   	 d
ed<   	 ded<   	 ded<   y)_HopOutcomez*The outcome of consuming one hop's stream.zOptional[_Refusal]r   r   ra   zOptional[Dict[str, Any]]start_eventr   blocksr   r   r   r   last_fallback_toNr  r1   r4   r2   r  r    sD    4E:))0  \O^LT##3r4   r  c                  t    e Zd ZU dZded<   	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 ddZedd       ZddZddZ	ddZ
dd	Zy
)r   u  Consumes one hop's SSE events, producing the frames to forward to the
    client while accumulating its content blocks.

    Events are held until the hop produces output (a content block or a
    terminal event), so a refusal that arrives before any output — a pre-stream
    decline — leaves no trace on the wire and chains silently. On open, stream
    A's held `message_start` is flushed in its original wire bytes; a spliced
    hop's is suppressed when the wire is already open, or emitted with its `id`
    rewritten to the primary's when this hop's start opens the wire. Queued
    seam frames for every hop reached so far are flushed right after.

    A spliced hop has its block indices shifted by `index_base` and its
    terminal message_delta's usage rewritten to the `usage.iterations` chain
    shape.

    A refusal that can be chained — an entry remains, and either a
    `fallback_credit_token` was minted or nothing has streamed yet — ends the
    hop early: open blocks are closed, the terminal message_delta +
    message_stop are suppressed, and the refusal is set on the outcome so the
    caller can issue the next hop. Any other refusal is logged and passes
    through to the client.
    z_HopOutcome | Noner   c                   t        |      | _        || _        || _        || _        || _        || _        d | _        d | _        d | _	        d | _
        g | _        d| _        d | _        d | _        y )NF)_BlockTracker_tracker	_has_next_splice
_wire_open_primary_id_seam_frames_model_start_usage_start_event_held_start_held_opened_last_fallback_tor   )r:   r   r   r   r   r   r   s          r2   r;   z_HopReader.__init__+  sq     &j1!#%'"&373737,.
-1r4   c                    | j                   S r8   )r  r9   s    r2   r   z_HopReader.openedD      ||r4   c           	     p
   t        t        |j                              }||j                  d      nd}| j                  }|dk(  rw|ut        |j                  d            }|I|j                  d      }t        |t              r|nd| _        t        |j                  d            | _        || _	        || _
        g S |dk(  r|| j                         }t        |j                  d            }|Z|j                  d      d	k(  rFt        |j                  d
            }	|	|	j                  d      nd}
t        |
t              r|
| _        | j                  j                  |       |g |t        d|      S g |t!        |      S |dk(  rN|L| j                         }| j                  j#                  |       |g |t        d|      S g |t!        |      S |dk(  rN|L| j                         }| j                  j%                  |       |g |t        d|      S g |t!        |      S |dk(  r|t        |j                  d            xs i }|j                  d      dk(  rt        |j                  d            }||j                  d      dk(  r|nd}||j                  d      nd}t        |t              r|r|nd}| j&                   xr | j                  j)                          }| j*                  r||rt-        t        |j                  d            | j                        }t/        | j                  j1                               }d| _
        | j2                  j5                          t7        t9        |||j                  d      nd|duxr |j                  d      du ||      | j                  | j                  | j                  j)                         | j                  j:                  | j&                  | j                        | _        |S |st>        jA                  d       nt>        jA                  d       | j                         }||j                  d      dk(  r.t        |j                  d            }||jC                  dd       t        |j                  d            xs i }g |jD                  tG        ||jH                        |d<   ||d<   g |t        d|      S g |t!        |      S | j&                  s| j2                  jK                  |       g S t!        |      gS )z:Process one event, returning the frames to forward for it.Ntypemessage_startr   ra   r   content_block_startcontent_blockfallbacktocontent_block_deltacontent_block_stopmessage_deltadeltarz   rj   stop_detailsfallback_credit_tokenr   fallback_has_prefill_claimT)r/   r   r   r   r   r   ra   r  r  r   r   r  zvanthropic-sdk: BetaRefusalFallbackMiddleware: refusal stop_details has no fallback_credit_token; surfacing the refusalzkanthropic-sdk: BetaRefusalFallbackMiddleware: refusal but no fallback entries remain; surfacing the refusalrecommended_modelr   )&r   
_safe_jsondatar@   r  ry   rw   r  r  r  r  _openr  r  start_emit_passthrough_sser$  stopr  content_blocksr  	_backfilllistclose_open_blocksr  clearr  r   r   r   r*   r   
setdefaultr   _serving_iteration_entryra   r~   )r:   sser   
event_typer   r   ra   r   r  r   r   r$  r%  detailsr/   
pre_streamr   s                    r2   feedz_HopReader.feedH  s   CHH-.*/*;UYYv&
(U->uyy34G"G,'1%'=e4$,W[[-A$B! %D"DI00U5FZZ\F$UYY%?@M(]->->v-F*-Tm//56.0n266'?$h,-5D*MM& % ?&>% 5u=> 6v5/45
 00U5FZZ\FMM& % ?&>% 5u=> 6v5/45
 //E4EZZ\FMMu% % >&=% 4e<= 6v5/45
 ?*u/@UYYw/06BEyy'94'		.(AB*6*B|GWGWX^G_clGl,rv@G@S$;<Y]!+E3!7Et!%-Tdmm6R6R6T2T
 >>u'8J%huyy/A&BDDUDUVE!$--"A"A"CDF (,D$JJ$$&#. ("'@G@SW[[%<Y].5T.A.wgkkRnFoswFw"'"'! #kk$($5$5#}};;=#'==#;#;#||)-)?)?$DL "MIIG
 II@ ZZ\F!99]+y8 $,EIIn,E#FL#/$//0CTJ !7!34:'&&',UFLLA'l# "'g??!>??3V3-c233||JJc"I !%&&r4   c                |   | j                   rg S d| _         g }| j                  1| j                  |j                  t	        | j                               n| j
                  s}| j                  qt        j                  | j                        }t        |j                  d            }|| j                  | j                  |d<   |j                  t        d|             |j                  | j                         |j                  d | j                  D               d| _        | j                  j!                          |S )zOpen the wire for this hop: its message_start (raw for stream A;
        suppressed or id-rewritten for a spliced hop), the queued seam frames,
        then anything else held.TNr   idr  c              3  2   K   | ]  }t        |        y wr8   )r/  ).0helds     r2   	<genexpr>z#_HopReader._open.<locals>.<genexpr>  s     D&t,D   )r  r  r  r~   r/  r  r  _copydeepcopyr   r@   r  r.  extendr  r  r5  )r:   r   r  r   s       r2   r,  z_HopReader._open  s     <<I <<+.t/?/?@AT%6%6%B..):):;K{y9:G"t'7'7'C $ 0 0MM%=>d''(DDD

r4   c                V    | j                   | j                  rg S | j                         S )zCFrames still owed when the stream ends without a chainable refusal.)r   r  r,  r9   s    r2   finish_framesz_HopReader.finish_frames  s#    <<#t||Izz|r4   c           	         | j                   | j                   S t        d| j                  | j                  | j                  j                         | j                  j                  | j                  | j                        S )zCThe outcome once the hop's stream is fully consumed (or cut early).Nr(  )	r   r  r  r  r  r1  r   r  r  r9   s    r2   r   z_HopReader.finish  sc    <<#<<++))==//1}}//<<!33
 	
r4   N)r   r   r   r   r   z_SpliceInfo | Noner   r   r   
str | Noner   list[bytes]rI   rJ   )rI   r   )r8  r   rI   rK  rI   rK  )rI   r  )rL   rM   rN   rO   rP   r;   propertyr   r<  r,  rH  r   r1   r4   r2   r   r     s    .  U  	
 #   ! 
2  x't.
r4   r   c              #     K   t        j                  |       D ]*  }|j                  |      D ]  }|  |j                  * n |j	                         D ]  }|  |j                         S w)zKFeed one hop's SSE events through `reader`, yielding the frames to forward.)r   
raw_eventsr<  r   rH  r   rf   r   r8  r   s       r2   r   r     su       * [[% 	EK	>>%	
 %%' ==?s   ?A.,A.c                  K   t        j                  |       2 3 d{   }|j                  |      D ]  }| 	 |j                  1 |j	                         D ]  }| 	 y7 H6 w)u   Feed one hop's SSE events through `reader`, yielding the frames to forward.

    The outcome is read from `reader.finish()` afterwards — async generators
    cannot return a value.
    N)r   rO  r<  r   rH  rP  s       r2   r   r     sr      !++H5  c[[% 	EK	>>%%%' 5s+   A)A'A%A'(A)	A)%A''A)c                      e Zd ZU dZded<   	 ded<   	 ded<   	 ded	<   	 ded
<   ded<   ded<   ded<   ded<   ded<   ded<   	 ddZed d       Zd!dZd"dZ	d#dZ
d$dZd%dZd&dZd'dZy)(r   z9Bookkeeping shared across the hops of one spliced stream.r   r   r   r   rJ  r   rw   primary_modelr/   	List[Any]r   partialr   r   last_refusalzDict[str, Any] | Nonelast_start_eventr   r   c                     || _         g | _        y r8   )_body_pending_seams)r:   r_   s     r2   r;   z_ChainState.__init__&  s    
+-r4   c                   |j                   J  | |      }||_        |j                  |_        |j                  |_        t        |j                  xs i j                  d            }||j                  d      nd}t        |t              r|nd|_
        |j                   j                  |_        g |_        |j                   j                  rt        |j                        ng |_        |j"                  xs |j                  |_        |j                   |_        |j                  |_        t+        |j                   |j                        |_        |S )u   The chain state after stream A's chainable refusal.

        `body` is the original request params (pre-pin) — the base every hop
        patches; `initial_model` is the model the initial request queried.
        Nr   r>  )r   rS  r   r   r   r   r  r@   ry   rw   r   r/   r   r   _to_prefill_blocksr  rU  r  r   rV  rW  _declined_iteration_entriesr   )clsr_   re   r   r   start_messagestart_ids          r2   r   z_ChainState.begin*  s    ***D	+"--!.. '"5"5";!@!@!KL.;.G=$$T*T'1(C'@8doo++
>Eoo>_>_*7>>:eg #33Ju7J7J$__!(!4!46wH[H[\r4   c                   | j                   }| xj                   dz  c_         | j                  j                  t        dd|t	        | j
                  || j                  j                        d      t        dd|d      g       || _        y)a  Queue the reached hop's `fallback` seam block at the next monotonic index.

        Queued seams are flushed by the hop reader once output reaches the wire,
        so a chain of pre-stream declines lines its seams up after the serving
        hop's message_start.
        r`   r  )r  r6   r  r"  r  r6   N)r   rZ  rF  r.  r   r   rV  r   )r:   r   
seam_indexs      r2   r   z_ChainState.queue_seamE  s     __
1"") 5!+)4T__hPTPaPaPjPj)k *5IT^,_`
	
 #r4   c                ,    t        | j                        S r8   )r3  rZ  r9   s    r2   r   z_ChainState.pending_seam_frames]  s    D''((r4   c                F    d| _         | j                  j                          y )NT)r   rZ  r5  r9   s    r2   r   z_ChainState.mark_opened`  s    !!#r4   c                6    g | j                   | j                  S r8   )r   rU  r9   s    r2   r   z_ChainState.continuationd  s    **T\\**r4   c                6   t        | j                  |      j                         D ci c]  \  }}|dk7  s|| }}}| j                  t	        | j                        |d<   |r/|j                  d      }g t        |t              r|ng d|d|d<   |S c c}}w )u  The hop's request body: the entry applied as a patch against the
        ORIGINAL request params (never a previous hop's patched body), extended
        by the continuation.

        The server-side `fallbacks` param is stripped — it is mutually exclusive
        with a credit-token retry. When the refusal granted no prefill claim the
        appended turn is omitted entirely and the same-body form is sent.
        r[   r&  messages	assistant)rolecontent)rp   rY  itemsr/   r3   r@   ry   r3  )r:   r   r   keyvaluer_   rh  s          r2   r   z_ChainState.hop_bodyg  s     *4DJJ)F)L)L)N 
%3RUYdRdCJ 
  
 ::!,?

,KD()xx
+H (48(b $> D  
s
   BBc                   |j                   J |j                   j                  | _        || _        |j                   j                  rt	        |j
                        ng | _        | j                  j                  t        |j                   |             |j                   | _
        |j                  |j                  | _        |j                  | _        y)z7Fold a refused hop's outcome in, readying the next hop.N)r   r/   r   r   r\  r  rU  r   rF  r]  rV  r  rW  r   )r:   r   ra   r   s       r2   r   z_ChainState.absorb_refusal}  s    ***__**
 	=D__=^=^)'..9df:7??ERS#OO*$+$7$7D!!,,r4   c                L   g }| j                   s}| j                  qt        j                  | j                        }t	        |j                  d            }|| j                  | j                  |d<   |j                  t        d|             |j                  | j                         t        j                  | j                  j                        }t	        |j                  d            }|;t	        |j                  d            }||j                  dv r|j                  nd|d<   t	        |j                  d	            xs i }t        j                  | j                        |d
<   ||d	<   |j                  t        d|             |j                  t        dddi             |S )uS  Degrade to the suppressed refusal when every remaining entry failed
        over HTTP: replay its message_delta verbatim — `recommended_model`
        stamped from the final failure (the failed model for capacity errors,
        `null` otherwise) and `usage.iterations` carrying the recorded chain —
        then message_stop.
        Nr   r>  r  r$  r%  )i  i  r)  r   r   r#  message_stopr  )r   rW  rD  rE  r   r@   r   r~   r.  rF  rZ  rV  r   r   ra   r   )	r:   r   r   r  r   r   r$  r:  r   s	            r2   r   z#_ChainState.terminal_failure_frames  sU    !~~$"7"7"C..)>)>?K{y9:G"t'B $MM%=>d))*t006677+,uyy89G"@GR\@\w}}bf+,7+,2#nnT__=lgeOU34eNV^,DEFr4   N)r_   r   rI   rJ   )r_   r   re   rw   r   r  rI   r   )r   rw   rI   rJ   rL  rH   )rI   	list[Any])r   r&   r   rr  rI   r   )r   r  ra   rw   r   rr  rI   rJ   )r   r   rI   rK  )rL   rM   rN   rO   rP   r;   classmethodr   r   r   r   r   r   r   r   r1   r4   r2   r   r   	  s    CO;O=2 4 
OO++$$I.  4#0)$+,
-r4   r   c                d   | j                   j                  d      }t        |t              ri|rgd t	        d|      D        }|D cg c]  }|i |ddi }}|r:t        |      dk(  r*t        |d   j                  d      t              s||d   d<   |S t        d|| j                         gS c c}w )	uS  The `usage.iterations` entries a declined hop contributes to the chain.

    The hop's refusal self-reports its iterations: adopt them, retyped to
    `message` (every one of them declined — a server-stitched envelope labels
    its last hop `fallback_message`). A single-entry self-report describes the
    hop itself and gains its model — `model_label`, the caller-spelled primary
    or the chain entry's id — when the wire didn't name one; a multi-entry
    self-report (a server-tool loop) is kept verbatim. Without a self-report,
    one entry is built from the refusal's usage.
    r   c              3  2   K   | ]  }t        |        y wr8   )r   )r@  r   s     r2   rB  z._declined_iteration_entries.<locals>.<genexpr>  s     QEQrC  rT  r  r   r`   r   ra   )r   r@   ry   r3  r   ru   rw   _to_iteration_usage)rj   model_labelreporteddict_entriesr   entriess         r2   r]  r]    s     }}  .H(D!hQT+x5PQS_(u%chct)EE)E69)E(u(u7|q GAJNN74KS)Q&1
7#N	;FGG )vs   B-
B-c                    | j                  d      }t        |t              r8|r6t        t	        d|      d         }|i |d|j                  d      xs |dS t        d||       S )zThe serving hop's `fallback_message` completer entry: its own
    self-reported iteration relabeled, or one built from its delta usage.r   rT  rC   fallback_messagera   )r  ra   )r@   ry   r3  r   r   rv  )delta_usagera   rx  lasts       r2   r7  r7    sl     |,H(D!h[(3B78\d\$6'ARA[V[\\15+FFr4   c                  P    e Zd ZU dZded<   	 dddZddZddZddZddZ	dd	Z
y
)r
  a/  Block bookkeeping for one stream of the splice: accumulates each content
    block from its deltas (for the continuation prefill), shifts wire indices
    by `index_base` so they stay monotonic across hops, and tracks which blocks
    are still open so a refusal that cuts mid-block can close them.
    r   r   c                <    || _         || _        g | _        g | _        y r8   )_index_baser   _blocksr,  )r:   r   s     r2   r;   z_BlockTracker.__init__  s    %$9; "
r4   c                L    | j                   D cg c]  \  }}|	 c}}S c c}}w )z/The accumulated content blocks, in start order.)r  )r:   _blocks      r2   r1  z_BlockTracker.content_blocks  s    &*ll3(!U333s    c                j   |j                  d      }t        |t              syt        |j                  d            }| j                  j                  ||t        |      ni f       || j                  z   }||d<   | j                  j                  |       t        | j                  |dz         | _
        y)z7Track a content_block_start, shifting `event["index"]`.r6   Nr  r`   )r@   ry   r   r   r  r~   dictr  r,  maxr   )r:   r   r6   r  shifteds        r2   r-  z_BlockTracker.start  s    		'"%% ?!;<U=;TD$7Z\]^$*** g

'"doow{;r4   c                    |j                  d      }t        |t              syt        |j                  d            }|t	        | j
                  ||       || j                  z   |d<   y)zQApply a content_block_delta to its accumulating block, shifting `event["index"]`.r6   Nr$  )r@   ry   r   r   _apply_deltar  r  )r:   r   r6   r$  s       r2   r$  z_BlockTracker.delta  sZ    		'"%%7+,ue4!1!11gr4   c                    |j                  d      }t        |t              sy|| j                  z   }||d<   || j                  v r| j                  j                  |       t        | j                  |dz         | _        y)z6Track a content_block_stop, shifting `event["index"]`.r6   Nr`   )r@   ry   r   r  r,  remover  r   )r:   r   r6   r  s       r2   r0  z_BlockTracker.stop  sj    		'"%%$*** gdjj JJg&doow{;r4   c              #     K   | j                   D ]  }t        dd|d        | j                   j                          yw)z4content_block_stop events for any blocks still open.r"  rb  N)r,  r.  r5  )r:   r6   s     r2   r4  z_BlockTracker.close_open_blocks  s@     ZZ 	^E,7KV[.\]]	^

s   >A N)r   )r   r   rI   rJ   )rI   list[dict[str, Any]])r   r   rI   rJ   rI   zIterator[bytes])rL   rM   rN   rO   rP   r;   r1  r-  r$  r0  r4  r1   r4   r2   r
  r
    s/     O8#4
<2	<r4   r
  c                   t        fd| D        d      }|y|j                  d      }|dk(  rAt        |j                  d      xs d      t        |j                  d      xs d      z   |d<   y|dk(  rAt        |j                  d      xs d      t        |j                  d	      xs d      z   |d<   y|d
k(  rS|j                  d      }t        |t              sg }||d<   t        d|      j                  |j                  d             y|dk(  rAt        |j                  d      xs d      t        |j                  d      xs d      z   |d<   y|dk(  r|j                  d      |d<   yy)zAApply a content_block_delta to the accumulating block at `index`.c              3  4   K   | ]  \  }}|k(  s|  y wr8   r1   )r@  block_indexr  r6   s      r2   rB  z_apply_delta.<locals>.<genexpr>  s     Q.KK5<P%Qs   Nr  
text_deltatextrb   input_json_delta_partial_jsonpartial_jsoncitations_delta	citationsrT  citationthinking_deltathinkingsignature_delta	signature)nextr@   rw   ry   r3  r   r~   )r  r6   r$  r  
delta_typer  s    `    r2   r  r  	  sW   Q&QSWXE}6"J\!EIIf-34s599V;L;RPR7SSf	)	)!$UYY%?%E2!FUYYWeMfMljlIm!mo	(	(IIk*	)T*I!*E+[)$++EIIj,AB	'	'		* 5 ;<s599ZCXC^\^?__j	(	("YY{3k 
)r4   c                   g }| D ]  }|j                  d      dk(  r|j                  d      }t        |t              s|j                  |       K|j	                         D ci c]  \  }}|dk7  s|| }}}t        |      }||n|j                  d      |d<   |j                  |        |r?|d   j                  d      dv r)|j                          |r|d   j                  d      dv r)|S c c}}w )u  Convert a hop's accumulated response blocks to the appended assistant turn.

    A `fallback_has_prefill_claim` refusal guarantees the partial output is
    resendable, so the blocks go out near-verbatim. Three rewrites apply:
    `fallback` seam blocks (wire markers, not content) are dropped, tool inputs
    are reassembled from their accumulated `input_json_delta` JSON
    (content_block_start carries `input: {}`), and trailing thinking blocks are
    stripped — the server rejects an assistant turn whose final block is
    `thinking`, so a refusal that cut the stream mid-thought would otherwise
    400 the continuation. A partial that was nothing but thinking strips to
    empty, and the hop falls back to the same-body form.
    r  r  r  inputrC   )r  redacted_thinking)r@   ry   rw   r~   rl  r*  pop)response_blocksoutr  r  rm  rn  parseds          r2   r\  r\    s     C  
99V
*yy1,,JJu.3kkmV
Uso?UeVVL)#)#5599W;Mg

5
 #b'++f%)JJ	 #b'++f%)JJJ Ws   #C21C2c                D   | j                  d      }t        |t              s| S d}g }t        d|      D ]  }t	        |      }||j                  d      nd}|t        |t              s|j                  |       Gt        d|      }|D cg c]$  }t        |      r|j                  d      dk(  r#|& }	}t        |	      t        |      k(  r|j                  |       d}|	s|j                  d	      d
k(  r|j                  i |d|	i        |s| S i | d|iS c c}w )u  A copy of `body` with `{type: "fallback"}` seam blocks filtered out of the
    replayed message history; `body` itself when there are none.

    An assistant turn left with no content by the strip — a seam-only turn — is
    dropped whole; the server rejects empty-content turns.rh  FrT  Nrk  r  r  Trj  ri  )r@   ry   r3  r   r   r~   r   ru   )
r_   rh  strippedstripped_messagesr   message_dictrk  content_listr  kepts
             r2   ro   ro   @  s9    xx
#Hh%H#%X. D(1=1I,""9-tz'4'@$$W-K1#/l%599U[K\`jKjllt9L))$$W-((0K?  !BL!B)T!BCD 2d2J 122 ms   $D0Dc           
        t        j                  | j                  j                         D ci c]  \  }}t	        |t
              s|| c}}      j                  dd      }|j                  d      D ch c]  }|j                          c}t        j                  fd|D              }| j                  j                         D ci c]  \  }}|j                         dk7  s|| }}}|s|r!dj                  t        d|g|            |d<   | j                  t        |t!        d                  S c c}}w c c}w c c}}w )	zA copy of `request` with `betas` appended to its `anthropic-beta` header
    (skipping values already present) and the middleware's helper-telemetry tag
    appended to `x-stainless-helper`. Single `request.copy()` for both.
    zanthropic-betarb   ,c              3  P   K   | ]  }t        |      vst        |        y wr8   )rw   )r@  r   existings     r2   rB  z+_with_middleware_headers.<locals>.<genexpr>h  s      WDSYh=Vc$iWs   &&z, Nzfallback-refusal-middleware)headers)r   Headersr  rl  ry   rw   r@   splitstripr  fromkeysr   joinfilterrq   r    r#   )	rd   rU   kvr   rn  	additionsr  r  s	           @r2   rn   rn   _  s    mmgoo.C.C.E\daTUWZI[QT\]aabrtvwG+2==+=>%>HWEWWI ' 5 5 7Y11779HX;Xq!tYGY)$(IIfTG;Pi;P.Q$R !<<g}Eb7c d<ee ]>Ys   D:
D:
7E E(Ec                h    t        | t              r"| j                  | j                  j                  S y)zEThe refusal's minted credit token; only the beta surface carries one.N)ry   r$   r%  r&  r   s    r2   r{   r{   o  s,    ';'G,@,@,L##999r4   c                h    t        | t              r"| j                  | j                  j                  S y)zOThe policy category that caused the refusal; only the beta surface carries one.N)ry   r$   r%  r   r  s    r2   r|   r|   v  s,    ';'G,@,@,L##,,,r4   c                    dd| id|id|ddS )zBThe synthetic `fallback` content block marking one model boundary.r  ra   rj   )r  r   )r  fromr   triggerr1   )r   r   r   s      r2   r   r   }  s)     *%!%8<	 r4   c           
        t        t        | j                  j                  d                  }|t	        |j                  d      t              syt        i |dg |t        d|d         i      j                  d      }| j                  j                         }dD ]
  }||v s||=  t        j                  | j                  ||| j                        S )zA copy of the served hop's response with `seams` prepended to its
    `content`, or `None` when the body isn't the expected message shape.

    The caller has already parsed the response, so its body is buffered.
    utf-8Nrk  rT  zcontent-encodingzcontent-length)r   r  rk  rd   )r   r*  rk  decodery   r@   r3  r   r   encoder  rq   r   Responser   rd   )originalr   r   r_   r  headers         r2   _seamed_http_responser    s     z("2"2"9"9'"BCDGjY)?F_'_9.^.^['R[J\8].^_`gghopD##%G8  W  >>((  	 r4   c           	         t        | j                  |      }|| S t        || j                  | j                  d| j
                  | j                  | j                        S NFr   )r  rr   r   r   r   r   r   r   rf   r   r   s      r2   r   r     s^    
 6 6
>C
{!!''!!,, r4   c           	         t        | j                  |      }|| S t        || j                  | j                  d| j
                  | j                  | j                        S r  )r  rr   r   r   r   r   r   r   r  s      r2   r   r     s^    
 6 6
>C
{!!''!!,, r4   c                    t        | t        d|            }t        |j                  d            }|Ct        t        | j                  d            xs i |      }|r||d<   |S |j	                  dd       |S )u  `entry` applied as a patch against `body`: a field set to a value
    overrides it, a field explicitly `None` unsets it (absent from the retried
    request — not sent as `null`), an absent field keeps the original value.

    `output_config` patches one level deep: its subfields follow the same
    set / `None`-unsets / absent-keeps rule against the original request's
    `output_config`; the whole object is dropped when nothing is left.

    Always a fresh dict; `body` is never mutated.r   output_configN)_patchr   r   r@   r  )r_   r   patchedr  mergeds        r2   rp   rp     sy     T4 0%89GUYY78M /!:;Ar=Q'-GO$ N KK.Nr4   c                    t        |       }|j                         D ]  \  }}||j                  |d       |||<   ! |S )z`overrides` applied flat against `base`: a key set to a value overrides
    it, a key explicitly `None` unsets it, an absent key keeps the base value.
    Always a fresh dict.N)r  rl  r  )r   	overridesr  rm  rn  s        r2   r  r    sJ     4jGoo' !
U=KKT" GCL	!
 Nr4   c                >    t        | |      }|rt        |      |d<   |S )zThe non-streaming retry body: the fallback entry applied as a patch
    against the original params, plus the refusal's credit token when it minted one.r&  )rp   r3   )r_   r  credit_tokenr  s       r2   r}   r}     s(     h'F*=l*K&'Mr4   c                L    	 t        j                  |       S # t        $ r Y y w xY wr8   )r   loadsr   )r  s    r2   r*  r*    s(    zz$ s    	##c                0    t        j                  | d      S )N)r  :)
separators)r   dumpsrn  s    r2   r   r     s    ::e
33r4   c                4    t        |       rt        d|       S d S )Nr   )r   r   r  s    r2   r   r     s    ,3EN4 %(DDr4   c                h    	 t        j                  | j                               S # t        $ r Y y w xY wr8   )r   r  readr   rf   s    r2   r   r     s.    zz(--/** s   "% 	11c                   K   	 t        j                  | j                          d {         S 7 # t        $ r Y y w xY wwr8   )r   r  areadr   r  s    r2   r   r     s8     zz 00110 s,   A "1 /1 A 1 	=A =A c                L    t        | t        |            j                  d      S )Nr   r+  r  )_serialize_sser   r  )r   payloads     r2   r.  r.    s    K,@AHHQQr4   c                    | j                   r-dj                  | j                         dz   j                  d      S t        | j                  | j
                        j                  d      S )zForward a decoded event in its original wire bytes, preserving SSE fields
    beyond `event:`/`data:` (`id:`, `retry:`, comment lines). Falls back to
    re-serializing for events with no raw lines.
    
z

r  r  )r   r  r  r  r   r+  )r8  s    r2   r/  r/    sN    
 ww		#''"V+33G<<		9@@IIr4   c                d    d}| 	|d|  dz  }|j                  d      D ]  }|d| dz  } |dz   S )zSerialize an event back to its SSE wire form (`event: ...\ndata: ...\n\n`).

    Multi-line `data` is emitted as one `data:` line per line, matching the
    spec. The inverse of the decoder behind `Stream.raw_events`.
    rb   zevent: r  zdata: )r  )r   r+  r  lines       r2   r  r    sW     Cr""

4  !vR  !:r4   c           	         |xs i }| ||j                  d      xs d|j                  d      xs d|j                  d      xs d|j                  d      xs d|j                  d      dS )Ninput_tokensr   output_tokenscache_read_input_tokenscache_creation_input_tokenscache_creation)r  ra   r  r  r  r  r  )r@   )r  ra   r   us       r2   rv  rv    sp     	An-2/41#$55)B#C#Hq'(uu-J'K'Pq%% 01 r4   c                    |xs i }i || xs i }|j                         D ]"  \  }}|	|j                  |      ||   ||<   $ |S )z0Fill `None` fields on `primary` from `fallback`.)rl  r@   )primaryr  r  rm  rn  s        r2   r2  r2  .  s^    ~2H9X9'-R9Ciik %
U=X\\#.:}CH% Jr4   c                    | j                   j                         }dD ]
  }||v s||=  t        j                  | j                  ||| j
                        S )zA synthetic response standing in for `original`, with `stream` as its body.

    The spliced frames are emitted post-decode, so the original's
    content-encoding/length headers no longer describe the body.
    r  )r   r  rt   rd   )r  rq   r   r  r   rd   )r  rt   r  r  s       r2   r   r   8  sa     ##%G8  W  >>((  	 r4   c                  8    e Zd ZddZedd       Zedd       Zy)r   c                    || _         y r8   _framesr:   r   s     r2   r;   z_FrameByteStream.__init__M  	    r4   c                    | j                   S r8   r  r9   s    r2   __iter__z_FrameByteStream.__iter__P  r  r4   c                8    | j                   j                          y r8   )r  r   r9   s    r2   r   z_FrameByteStream.closeT  s    r4   N)r   r   rI   rJ   r  rH   )rL   rM   rN   r;   r   r  r   r1   r4   r2   r   r   L  s/        r4   r   c                  8    e Zd ZddZedd       Zedd       Zy)r   c                    || _         y r8   r  r  s     r2   r;   z_AsyncFrameByteStream.__init__Z  r  r4   c                    | j                   S r8   r  r9   s    r2   	__aiter__z_AsyncFrameByteStream.__aiter__]  r  r4   c                T   K   | j                   j                          d {    y 7 wr8   )r  r   r9   s    r2   r   z_AsyncFrameByteStream.aclosea  s     ll!!###s   (&(N)r   r   rI   rJ   )rI   AsyncIterator[bytes]rH   )rL   rM   rN   r;   r   r  r   r1   r4   r2   r   r   Y  s/       $ $r4   r   )r/   rw   rI   r'   )rf   httpx.Responser   r   rI   z#Generator[bytes, None, _HopOutcome])rf   r  r   r   rI   r  )rj   r   rw  rw   rI   r  )r}  r   ra   rw   rI   r   )r  z list[tuple[int, dict[str, Any]]]r6   r   r$  r   rI   rJ   )r  r  rI   rr  )r_   r   rI   r   )rd   r   rU   r+   rI   r   )r   zMessage | BetaMessagerI   rJ  )r   rw   r   rw   r   rJ  rI   r   )r  r  r   r  rI   zhttpx.Response | None)rf   r   r   r  rI   r   )rf   r   r   r  rI   r   )r_   r   r   r&   rI   r   )r   r   r  r   rI   r   )r_   r   r  r&   r  rJ  rI   r   )r  rw   rI   r   )rn  r   rI   rw   )rn  rK   rI   r   )rf   r  rI   r   )r   rw   r  r   rI   bytes)r8  r   rI   r  )r   rJ  r+  rw   rI   rw   )r  z&Literal['message', 'fallback_message']ra   rw   r   r   rI   r   )r  r   r  r   rI   r   )r  r  rt   z,httpx.SyncByteStream | httpx.AsyncByteStreamrI   r  )l
__future__r   rq   rD  r   loggingtypingr   r   r   r   r   r	   r
   r   r   r   r   contextvarsr   r   typing_extensionsr   r   r   _utilsr   _modelsr   _requestr   	_responser   r   
_streamingr   r   r   _exceptionsr   _middlewarer   r   r   _base_clientr    types.messager!   _stainless_helpersr#   types.beta.beta_messager$   types.anthropic_beta_paramr%   types.beta.beta_fallback_paramr&   +types.beta.beta_fallback_credit_token_paramr'   __all__	getLoggerr*   rP   r   r,   r3   r(   r=   r?   r)   r   r   r   r  r   r   r   r   r]  r7  r
  r  r\  ro   rn   r{   r|   r   r  r   r   rp   r  r}   r*  r   r   r   r   r.  r/  r  rv  r2  r   SyncByteStreamr   AsyncByteStreamr   r1   r4   r2   <module>r      s4   "       * /     " 6 > > ) > > ) $ . 2 < ? W # (g''(BC^ C0O- O >3* *< 9CCblp8q5 q S]*BS O 
j	'J j	'`(y () S) S3) 34[
 [
|	[ [|H,G; ;B4,B3>f ,*
4ERJ
09<EZ&R(
u++ 

$E11 
$r4   