o
    ưi~                     @   s  d 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 ddlZddlZddlZddlZddlZddlmZ ddlmZ ddlmZmZmZmZ ddlmZmZmZm Z m!Z!m"Z" ddl#m$Z$m%Z%m&Z&m'Z' dd	lm(Z(m)Z)m*Z*m+Z+m,Z,m-Z-m.Z.m/Z/ d
dl0m1Z1 ddl2m3Z3m4Z4 ddl5m6Z6 ddl7m8Z8 erddl9m:Z: ddl;m<Z< 	d%de
e de=de>de=de=de?de
ee@ejAf  deBde
e= deeejCf fddZD	d%de
e de=de>de=de=de?de
ee@ejAf  deBde
e= deeejCf fdd ZEG d!d" d"e1ZFG d#d$ d$ZGdS )&zE
Calling + translation logic for anthropic's `/v1/messages` endpoint
    N)
TYPE_CHECKINGAnyCallableDictListLiteralOptionalTupleUnioncast)RESPONSE_FORMAT_TOOL_NAME)map_finish_reason)AsyncHTTPHandlerHTTPHandler_get_httpx_clientget_async_httpx_client)ContentBlockDeltaContentBlockStartContentBlockStopMessageBlockDeltaMessageStartBlock
UsageDelta)#ChatCompletionRedactedThinkingBlockChatCompletionThinkingBlockChatCompletionToolCallChunk#ChatCompletionToolCallFunctionChunk)DeltaGenericStreamingChunkLlmProvidersModelResponseModelResponseStreamStreamingChoicesUsage_generate_id   )BaseLLM   )AnthropicErrorprocess_anthropic_headers)!update_headers_with_filtered_beta   )AnthropicConfigCustomStreamWrapper)
BaseConfigclientapi_baseheadersdatamodelmessagestimeout	json_modespeedreturnc
              
      s  | d u rt j} z| j|||d|dI d H }
W nT tjyK } z't|dd }t|dd }|d u r8|r8t|dd }t|jj|j	 I d H |dd }~w t
yk } zt jD ]	}t||r^|qUtdt|dd }~ww t|
 d||	d	}|j|d
|d|id ||
jfS )NTr1   r2   streamr5   r1   responsestatus_codemessager1     r=   r>   Fstreaming_responsesync_streamr6   r7    complete_input_dictinputapi_keyoriginal_responseadditional_args)litellmZmodule_level_aclientposthttpxHTTPStatusErrorgetattrr'   r;   r=   Zaread	ExceptionLITELLM_EXCEPTION_TYPES
isinstancestrModelResponseIteratorZaiter_lines	post_callr1   )r/   r0   r1   r2   r3   r4   logging_objr5   r6   r7   r;   eerror_headerserror_response	exceptioncompletion_stream r\   Z/home/app/Keep/.python/lib/python3.10/site-packages/litellm/llms/anthropic/chat/handler.py	make_callG   sN   



r^   c
              
   C   s(  | d u rt j} z| j|||d|d}
W nQ tjyD } z$t|dd }t|dd }|d u r4|r4t|dd }t|jj|j	 |dd }~w t
yd } zt jD ]	}t||rW|qNtdt|dd }~ww |
jdkrzt|
dd }t|
j|
	 |dt|
 d||	d	}|j|d
dd|id ||
jfS )NTr9   r1   r;   r<   r?   r@      rA   rD   zfirst stream response receivedrE   rF   )rK   Zmodule_level_clientrL   rM   rN   rO   r'   r;   r=   readrP   rQ   rR   rS   rT   
iter_linesrU   r1   )r/   r0   r1   r2   r3   r4   rV   r5   r6   r7   r;   rW   rX   rY   rZ   response_headersr[   r\   r\   r]   make_sync_call|   sT   





rc   c                       s  e Zd Zd fddZdddi fdedededed	ed
ede	e
ejf dee dedefddZdi dfdedededed	ed
ede	e
ejf dededededddee de	edf fddZddi dfdededededed	ed
edede	e
ejf defddZdd Z  ZS )AnthropicChatCompletionr8   Nc                    s   t    d S N)super__init__self	__class__r\   r]   rg      s   z AnthropicChatCompletion.__init__r3   r4   r0   custom_prompt_dictmodel_responseprint_verboser5   r/   r2   r6   c                    sj   ddl m} d|d< t|||t|||||||r|dnd d
I d H \}}|||d|t|d}|S )	Nr   r,   Tr:   r7   
r/   r0   r1   r2   r3   r4   rV   r5   r6   r7   	anthropicr[   r3   custom_llm_providerrV   Z_response_headers),litellm.litellm_core_utils.streaming_handlerr-   r^   jsondumpsgetr(   )ri   r3   r4   r0   rl   rm   rn   r5   r/   encodingrH   rV   r:   _is_function_callr2   r6   optional_paramslitellm_params	logger_fnr1   r-   r[   Zstreamwrapperr\   r\   r]   acompletion_stream_function   s.   z3AnthropicChatCompletion.acompletion_stream_functionry   rz   provider_configr.   r-   c                    s   |p	t tjjd}z|j||||dI d H }W nS tyk } zG|
j||	t|d|id t|dd}t|dd }t|dt|}t|d	d }|d u rS|rSt|dd }|r`t	|dr`t|d|}t
|||d
d }~ww |j||||
|	||||||dS )N)Zllm_provider)r1   rt   r5   rE   rF   r=   r?   r1   textr;   r>   r=   r1   r3   Zraw_responserm   rV   rH   Zrequest_datar4   ry   rz   rw   r6   )r   rK   r   Z	ANTHROPICrL   rP   rU   rS   rO   hasattrr'   transform_response)ri   r3   r4   r0   rl   rm   rn   r5   rw   rH   rV   r:   rx   r2   ry   r6   rz   r}   r{   r1   r/   Zasync_handlerr;   rW   r=   rX   
error_textrY   r\   r\   r]   acompletion_function   sV   z,AnthropicChatCompletion.acompletion_functionrr   c           !      C   s  ddl m} ddlm} t|}|dd }|dd}|dd}|dd  d}t|}t j|	|||i |d|i|d	}t	||d
}|j
|t|d}|d u r_td| d| |j||i |d|i||d}|
j||	|||dd |d|  |du r!|du r|d ||d< | jd2i d|d|d|d|d|d|d|d|d|	d|
d|d|d|d|d |d!|d"|d#|d$|d urt|tr|S d S | jd2i d|d|d|d|d|d|d|d|d|	d%|d|
d|d|d|d |d!|d"|d$|d|d#|S |du rP||d< t|||t||||
|||r?|d&nd d'
\}}|||d(|
t|d)S |d u s[t|tsctd#|id*}n|}z|j||t||d+}W nK ty } z>t|d,d-}t|d"d }t|d.t|}t|d/d } |d u r| rt| d"d }| rt| d.rt| d.|}t|||d0d }~ww |j ||||
|	||||||d1S )3Nr   r,   )ProviderConfigManagerr:   r6   Fis_vertex_requestZvertex_count_tokens_location)rH   r1   r3   r4   ry   rz   )r1   provider)r3   r   z%Provider config not found for model: z and provider: )r3   r4   ry   rz   r1   )rE   r0   r1   )rG   rH   rJ   z_is_function_call: Tz,makes async anthropic streaming POST requestr3   r4   r2   r0   rl   rm   rn   rw   rH   rV   ry   rx   rz   r{   r1   r5   r/   r}   r7   ro   rp   rq   )params)r1   r2   r5   r=   r?   r~   r;   r   r   r\   )!rs   r-   Zlitellm.utilsr   copydeepcopypopr+   Zvalidate_environmentr)   Zget_provider_chat_configr   
ValueErrorZtransform_requestZpre_callr|   rR   r   r   rc   rt   ru   rv   r(   r   r   rL   rP   rO   rS   r   r'   r   )!ri   r3   r4   r0   rr   rl   rm   rn   rw   rH   rV   ry   r5   rz   Zacompletionr{   r1   r/   r-   r   r:   r6   r   rx   configr2   r[   r;   rW   r=   rX   r   rY   r\   r\   r]   
completion,  s~  

			

	

	


	
z"AnthropicChatCompletion.completionc                 C   s   d S re   r\   rh   r\   r\   r]   	embedding  s   z!AnthropicChatCompletion.embedding)r8   N)__name__
__module____qualname__rg   rS   listdictr   r   r
   floatrM   Timeoutr   r   boolr|   r   r   r   __classcell__r\   r\   rj   r]   rd      s    	
B

R
 Brd   c                
   @   s  e Zd Z	d2dedee dee fddZdefd	d
Zdee	e
f defddZde	deeee eeeef  eeef f fddZdeeeef  dee fddZdedeeef deee eeef f fddZde	defddZde	defddZdedee deeee f fddZde	deeee eeeef  f fd d!Zd"edee fd#d$Zd%edee fd&d'Zd(d) Zd*d+ Z d,d- Z!d.d/ Z"dedefd0d1Z#dS )3rT   FNrC   r6   r7   c                 C   s\   || _ | j | _g | _d| _|| _|| _t | _d| _d| _	d| _
d| _d | _g | _g | _d S )NFrD   Z
valid_json)rB   response_iteratorcontent_blocks
tool_indexr6   r7   r#   response_idis_response_format_toolconverted_response_format_toolaccumulated_json
chunk_typecurrent_content_block_typeweb_search_resultscompaction_blocks)ri   rB   rC   r6   r7   r\   r\   r]   rg     s   
zModelResponseIterator.__init__r8   c                 C   s   d}t | jdkrdS | jd d d dks!| jd d d dkr#dS | jD ]}|d d dkr:||d d	d7 }q&t |dkrCd
S dS )zN
        Check if the tool call block so far has been an empty string
        rD   r   FdeltatypeZ
text_deltaZthinking_deltaZinput_json_deltapartial_jsonT)lenr   rv   )ri   argsblockr\   r\   r]   check_empty_tool_call_args  s   
z0ModelResponseIterator.check_empty_tool_call_argsanthropic_usage_chunkc                 C   s   t  jtt|d | jdS )N)Zusage_objectreasoning_contentr7   )r+   Zcalculate_usager   r   r7   )ri   r   r\   r\   r]   _handle_usage+  s   z#ModelResponseIterator._handle_usagechunkc                 C   s0  d}d}i }t di |}g }| j| d|d v r"|d d }npd|d v r@| jdv r?ttddd|d d d| jd	}nRd
|d v rO|d d
 |d
< nCd|d v s[d|d v rxtd|d dpedt	|d dpnddg}||d< nd|d v r|d ddkrd|d d d|d< ||||fS )zC
        Helper function to handle the content block delta
        rD   Nr~   r   r   tool_useserver_tool_usefunctionname	argumentsidr   r   indexZcitationthinking	signature)r   r   r   thinking_blockscontentr   Zcompaction_deltar   r   r\   )
r   r   appendr   r   r   r   r   rv   rS   )ri   r   r~   r   provider_specific_fieldscontent_blockr   r\   r\   r]   _content_block_delta_helper0  sL   	




z1ModelResponseIterator._content_block_delta_helperr   c                 C   sB   d}|D ]}t tt |d}|du rd}|dur||7 }q|S )z.
        Handle the reasoning content
        Nr   rD   )r   r   rS   rv   )ri   r   r   r   Zthinking_contentr\   r\   r]   _handle_reasoning_contentl  s   	z/ModelResponseIterator._handle_reasoning_contentcontent_block_startr   c                 C   s&   t d|d d dg}||d< ||fS )z6
        Handle the redacted thinking content
        redacted_thinkingr   r2   )r   r2   r   )r   )ri   r   r   r   r\   r\   r]   !_handle_redacted_thinking_content~  s   	
z7ModelResponseIterator._handle_redacted_thinking_contentc                 C   sJ   ddl m}m} |di ddkr|di |}|S |di |}|S )Nr   )ContentBlockStartTextContentBlockStartToolUser   r   r   r\   )litellm.types.llms.anthropicr   r   rv   )ri   r   r   r   r   r\   r\   r]   get_content_block_start  s   z-ModelResponseIterator.get_content_block_startc              
   C   s  z| ddp	d}d}d }d}d }i }d }d }	d}
|dkr3	 | j|d\}}}	}|	r1| j|	d}nz|dkr&	 | j|d}g | _|d d | _|d d d	krY|d d	 }nT|d d d
ksi|d d dkr|  jd7  _t|d d dt|d d dd| jd}d|d v r|d d }|rt	t
ttf ||d< n|d d dkr| j||d\}	}n|d d dkr| j|d  | j|d< d|d  ddd|d< n|d d dr%|d d }|dkr| j|d  | j|d< n|dkr
| j|d  | j|d< n|dkr%t| dsg | _| j|d  | j|d< n|d krStd3i | | jd!v rL|  }|rLtd dtd d"d| jd}d#| _d | _nZ|d$krYnT|d%krn| |\}}}|rm||d&< n?|d'kr	 td3i |}d(|d) v r| j|d) d( d*}n |d+kr	 | d+i pi }| d)d pt|}t|d,d-| j||d.\}}tt|
t||d ur|gnd |r|nd |	r|	nd |d/|d0g|| jd1}|W S  t j!y   t"d2| w )4Nr   rD   r   Zcontent_block_deltar   )r   r   r   r~   r   r   r*   r   r   r   r   r   Zcallerr   )r   r   Z
compactionr   r   r   Zcompaction_startZ_tool_resultZweb_search_tool_resultr   Zweb_fetch_tool_resultZtool_search_tool_resulttool_resultsZcontent_block_stopr   z{}FZtool_resultmessage_delta	containermessage_startusager>   r   errorr?   )r>   r=   )r~   r   )r   
tool_callsr   r   r   )r   r   finish_reason)choicesr   r   z"Failed to decode JSON from chunk: r\   )#rv   r   r   r   r   r   r   r   r   r   r   rS   r   r   r   r   endswithr   r   r   r   r   r   _handle_message_deltar   r   r'   _handle_json_mode_chunkr    r!   r   r   rt   JSONDecodeErrorr   )ri   r   Z
type_chunkr~   r   r   r   r   r   r   r   r   Zcaller_datacontent_typeZis_emptyr   Zmessage_start_blockZ_error_dictr>   returned_chunkr\   r\   r]   chunk_parser  s$  	
	
 












z"ModelResponseIterator.chunk_parserr~   r   c                 C   sz   | j r|du r||fS |ddur!|di dd}|tk| _| jr9tj|gd}|dur9|jp3d}d}d| _||fS )a  
        If JSON mode is enabled, convert the tool call to a message.

        Anthropic returns the JSON schema as part of the tool call
        OpenAI returns the JSON schema as part of the content, this handles placing it in the content

        Tool streaming follows Anthropic's fine-grained streaming pattern:
        - content_block_start: Contains complete tool info (id, name, empty arguments)
        - content_block_delta: Contains argument deltas (partial_json)
        - content_block_stop: Signals end of tool

        Reference: https://docs.anthropic.com/en/docs/agents-and-tools/tool-use/fine-grained-tool-streaming

        Args:
            text: str
            tool_use: Optional[ChatCompletionToolCallChunk]
        Returns:
            Tuple[str, Optional[ChatCompletionToolCallChunk]]

            text: The text to use in the content
            tool_use: The ChatCompletionToolCallChunk to use in the chunk response
        Nr   r   r   rD   )r   T)r6   rv   r   r   r+   Z!_convert_tool_response_to_messager   r   )ri   r~   r   Z	tool_namer>   r\   r\   r]   r   w  s   

z-ModelResponseIterator._handle_json_mode_chunkc                 C   sZ   t d	i |}t|d ddpdd}| jrd}| j|d d}|d d}|||fS )
z
        Handle message_delta event for finish_reason, usage, and container.

        Args:
            chunk: The message_delta chunk

        Returns:
            Tuple of (finish_reason, usage, container)
        r   Zstop_reasonstop)r   r   r   r   Nr\   )r   r   rv   r   r   )ri   r   r   r   r   r   r\   r\   r]   r     s   

z+ModelResponseIterator._handle_message_deltadata_strc                 C   sF   |  j |7  _ zt| j }d| _ | j|dW S  tjy"   Y dS w )a  
        Handle partial JSON chunks by accumulating them until valid JSON is received.

        This fixes network fragmentation issues where SSE data chunks may be split
        across TCP packets. See: https://github.com/BerriAI/litellm/issues/17473

        Args:
            data_str: The JSON string to parse (without "data:" prefix)

        Returns:
            ModelResponseStream if JSON is complete, None if still accumulating
        rD   r   N)r   rt   loadsr   r   )ri   r   	data_jsonr\   r\   r]   _handle_accumulated_json_chunk  s   z4ModelResponseIterator._handle_accumulated_json_chunkstr_linec                 C   s^   |dd }| j dkr| |S zt|}| j|dW S  tjy.   d| _ | | Y S w )a  
        Parse SSE data line, handling both complete and partial JSON chunks.

        Args:
            str_line: The SSE line starting with "data:"

        Returns:
            ModelResponseStream if parsing succeeded, None if accumulating partial JSON
           Nr   r   )r   r   rt   r   r   r   )ri   r   r   r   r\   r\   r]   _parse_sse_data  s   



z%ModelResponseIterator._parse_sse_datac                 C   s   | S re   r\   rh   r\   r\   r]   __iter__  s   zModelResponseIterator.__iter__c                 C   s>  	 z| j  }W n< ty2   | jr0zt| j}d| _| j|dW  Y S  tjy/   Y tw t tyD } zt	d| d }~ww z:|}t
|tra|d}|d}|dkra||d  }|drs| |}|d urr|W S ntdddd d	d d
W S W n ty   t ty } z
t	d| d| d }~ww qNTrD   r   z#Error receiving chunk from stream: utf-8data:r   Fr   )r~   is_finishedr   r   r   r   zError parsing chunk: z,
Received chunk: )r   __next__StopIterationr   rt   r   r   r   r   RuntimeErrorrR   bytesdecodefind
startswithr   r   ri   r   r   rW   r   r   resultr\   r\   r]   r     s\   




zModelResponseIterator.__next__c                 C   s   | j  | _| S re   )rB   	__aiter__async_response_iteratorrh   r\   r\   r]   r   "  s   zModelResponseIterator.__aiter__c                    sF  	 z
| j  I d H }W n< ty6   | jr4zt| j}d| _| j|dW  Y S  tjy3   Y tw t tyH } zt	d| d }~ww z:|}t
|tre|d}|d}|dkre||d  }|drw| |}|d urv|W S ntdddd d	d d
W S W n ty   t ty } z
t	d| d| d }~ww qr   )r   	__anext__StopAsyncIterationr   rt   r   r   r   r   r   rR   r   r   r   r   r   r   r   r\   r\   r]   r   &  s^   




zModelResponseIterator.__anext__c                 C   sj   |}t |tr|d}|d}|dkr||d }|dr/t|dd }| j|dS t| j	dS )a%  
        Convert a string chunk to a GenericStreamingChunk

        Note: This is used for Anthropic pass through streaming logging

        We can move __anext__, and __next__ to use this function since it's common logic.
        Did not migrate them to minmize changes made in 1 PR.
        r   r   r   Nr   r   )r   )
rR   r   r   r   r   rt   r   r   r    r   )ri   r   r   r   r   r\   r\   r]   "convert_str_chunk_to_generic_chunkR  s   	



z8ModelResponseIterator.convert_str_chunk_to_generic_chunk)FN)$r   r   r   r   r   rS   rg   r   r
   r   r   r"   r   r	   r   r   r   r   r   r   r   r   r   r   r   r    r   r   r   r   r   r   r   r   r   r   r\   r\   r\   r]   rT     sl    
!
<



 [
,0
-,rT   re   )H__doc__r   rt   typingr   r   r   r   r   r   r   r	   r
   r   rM   rK   Zlitellm.litellm_core_utilsZlitellm.typesZlitellm.types.utilsZlitellm.constantsr   Z'litellm.litellm_core_utils.core_helpersr   Z&litellm.llms.custom_httpx.http_handlerr   r   r   r   r   r   r   r   r   r   r   Zlitellm.types.llms.openair   r   r   r   r   r   r   r   r    r!   r"   r#   baser%   Zcommon_utilsr'   r(   Z&litellm.anthropic_beta_headers_managerr)   Ztransformationr+   rs   r-   Z)litellm.llms.base_llm.chat.transformationr.   rS   r   r   r   r   r   ZHeadersr^   rc   rd   rT   r\   r\   r\   r]   <module>   s    0 (	

?	

:  >