Ë
    uPêjã<  ã                   óð   — d dl mZmZmZ d dlmZmZ d dl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 d d	lm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!  G d„ de!«      Z" G d„ de «      Z#y)é    )ÚAsyncIteratorÚIteratorÚMapping)ÚAnyÚFinalN)Úverbose_logger)ÚXAI_API_BASE)ÚAuthenticationError)Úfilter_value_from_dictÚstrip_name_from_messages)ÚXAIModelInfo)Ú-apply_server_side_tool_usage_details_to_usage)Úget_secret_str)ÚAllMessageValues)ÚChoicesÚModelResponseÚModelResponseStreamÚUsageé   )Ú$OpenAIChatCompletionStreamingHandlerÚOpenAIGPTConfigc                   ó�  ‡ — e Zd Zededz  fd„«       Zdedz  dedz  deedz  edz  f   fd„Z	 	 d&deded	e	e
   d
edededz  dedz  defˆ fd„Z	 d'dedz  dedz  ded
edededz  defˆ fd„Zdede	fd„Zdedefd„Zdedefd„Z	 d(ded
edededef
d„Z	 d(dee   ee   z  ez  dededz  defd„Zded	e	e
   d
edededefˆ fd„Zededdfd„«       Z	 	 d&dedej8                  deded	e	e
   d
edededz  dedz  defˆ fd„Zed eez  eeef   z  dz  ddfd!„«       Zded"eddfd#„Z ed$eeeef   z  dz  ddfd%„«       Z!ˆ xZ"S ))ÚXAIChatConfigÚreturnNc                  ó   — y)NÚxai© )Úselfs    úi/home/oem/CyberBrain26-unified/.venv/lib/python3.12/site-packages/litellm/llms/xai/chat/transformation.pyÚcustom_llm_providerz!XAIChatConfig.custom_llm_provider"   s   € àó    Úapi_baseÚapi_keyc                 ób   — |xs t        d«      xs t        }t        j                  |«      }||fS )Nr	   )r   r	   r   Úget_api_key)r   r"   r#   Údynamic_api_keys       r   Ú$_get_openai_compatible_provider_infoz2XAIChatConfig._get_openai_compatible_provider_info&   s3   € ð ÒMœ~¨nÓ=ÒMÄˆÜ!-×!9Ñ!9¸'Ó!BˆØ˜Ð(Ð(r!   ÚheadersÚmodelÚmessagesÚoptional_paramsÚlitellm_paramsc           	      ó>  •— ddl m}m}	m}
 t	        j
                  |«      } |
|«      r-|s+	 d |«       j                  «       › �|d<   d|vr	d|vrd	|d<   |S t        ‰| �-  |||||||¬
«      S # |	$ r+}t        || j                  xs dt        |«      ¬«      |‚d }~ww xY w)Nr   )ÚXAIOAuthAuthenticatorÚXAIOAuthErrorÚshould_use_xai_oauthzBearer ÚAuthorizationr   )r)   Úllm_providerÚmessagezcontent-typezContent-Typezapplication/json)r(   r)   r*   r+   r,   r#   r"   )Úlitellm.llms.xai.oauthr.   r/   r0   r   r%   Úget_access_tokenr
   r    ÚstrÚsuperÚvalidate_environment)r   r(   r)   r*   r+   r,   r#   r"   r.   r/   r0   r&   ÚexcÚ	__class__s                €r   r8   z"XAIChatConfig.validate_environment-   sÕ   ø€ ÷	
ñ 	
ô ".×!9Ñ!9¸'Ó!BˆÙ Ô/¹ðØ-4Ñ5JÓ5L×5]Ñ5]Ó5_Ð4`Ð+a�˜Ñ(ð  WÑ,°ÀwÑ1NØ*<�˜Ñ'ØˆNä‰wÑ+ØØØØ+Ø)Ø#Øð ,ó 
ð 	
øð !ò Ü)ØØ!%×!9Ñ!9Ò!B¸UÜ ›Hôð ð	ûðús   ¬A, Á,BÁ1&BÂBÚstreamc                 ó¦   •— ddl m}m} t        j                  |«      }	 ||«      r|	s |«       j                  «       }t        ‰
| �  ||	||||¬«      S )Nr   )r.   r0   )r"   r#   r)   r+   r,   r;   )r4   r.   r0   r   r%   Úget_api_baser7   Úget_complete_url)r   r"   r#   r)   r+   r,   r;   r.   r0   r&   r:   s             €r   r>   zXAIChatConfig.get_complete_urlU   s]   ø€ ÷ 	Wä!-×!9Ñ!9¸'Ó!BˆÙ Ô/¹Ù,Ó.×;Ñ;Ó=ˆHä‰wÑ'ØØ#ØØ+Ø)Øð (ó 
ð 	
r!   c                 óV  — g d¢}| j                  |«      r|j                  d«       | j                  |«      r|j                  d«       	 t        j                  || j
                  ¬«      r|j                  d«       |S # t        $ r!}t        j                  d|«       Y d }~|S d }~ww xY w)N)Ú
logit_biasÚlogprobsÚ
max_tokensÚnÚparallel_tool_callsÚpresence_penaltyÚresponse_formatÚseedr;   Ústream_optionsÚtemperatureÚtool_choiceÚtoolsÚtop_logprobsÚtop_pÚuserÚweb_search_optionsÚstopÚfrequency_penalty)r)   r    Úreasoning_effortz.Error checking if model supports reasoning: %s)	Ú_supports_stop_reasonÚappendÚ_supports_frequency_penaltyÚlitellmÚsupports_reasoningr    Ú	Exceptionr   Údebug)r   r)   Úbase_openai_paramsÚes       r   Úget_supported_openai_paramsz)XAIChatConfig.get_supported_openai_paramsm   s©   € ò%
Ðð. ×%Ñ% eÔ,Ø×%Ñ% fÔ-ð
 ×+Ñ+¨EÔ2Ø×%Ñ%Ð&9Ô:ð
	VÜ×)Ñ)°È4×KcÑKcÕdØ"×)Ñ)Ð*<Ô=ð "Ð!øô ò 	VÜ× Ñ Ð!QÐST×UÐUà!Ð!ûð	Vús   Á
2A> Á>	B(ÂB#Â#B(c                 ó   — d|v sd|v sd|v ryy)Nzgrok-3-miniúgrok-4úgrok-code-fastFTr   ©r   r)   s     r   rS   z#XAIChatConfig._supports_stop_reason™   s   € Ø˜EÑ! X°Ñ%6Ð:JÈeÑ:SØØr!   c                 ó   — d|v ryd|v ryy)z�
        From manual testing grok-4 does not support `frequency_penalty`

        When sent the model fails from xAI API
        r^   Fr_   Tr   r`   s     r   rU   z)XAIChatConfig._supports_frequency_penaltyž   s   € ð �uÑØØ˜uÑ$ØØr!   Únon_default_paramsÚdrop_paramsc                 ó  — | j                  |¬«      }|j                  «       D ]b  \  }}|dk(  r||d<   Œ|dk(  r@|�>g }|D ]"  }	t        |	d«      }	|	€Œ|j                  |	«       Œ$ t	        |«      dkD  sŒP||d<   ŒV||v sŒ[|€Œ^|||<   Œd |S )N)r)   Úmax_completion_tokensrB   rK   Ústrictr   )r\   Úitemsr   rT   Úlen)
r   rb   r+   r)   rc   Úsupported_openai_paramsÚparamÚvaluerK   Útools
             r   Úmap_openai_paramszXAIChatConfig.map_openai_paramsª   s¿   € ð *.×)IÑ)IÐPUÐ)IÓ)VÐØ.×4Ñ4Ó6ò 	3‰LˆE�5ØÐ/Ò/Ø05� Ò-Ø˜'Ò! eÐ&7Ø�Ø!ò +�DÜ1°$¸ÓA�DØÑ'ØŸ™ TÕ*ð+ô �u“: “>Ø/4�O GÒ,ØÐ1Ò1ØÑ$Ø-2�O EÒ*ð	3ð Ðr!   Ústreaming_responseÚsync_streamÚ	json_modec                 ó   — t        |||¬«      S )N)rn   ro   rp   )Ú!XAIChatCompletionStreamingHandler)r   rn   ro   rp   s       r   Úget_model_response_iteratorz)XAIChatConfig.get_model_response_iteratorÂ   s   € ô 1Ø1Ø#Øô
ð 	
r!   c                 ó@   •— t        |«      }t        ‰| �	  |||||«      S )zp
        Handle https://github.com/BerriAI/litellm/issues/9720

        Filter out 'name' from messages
        )r   r7   Útransform_request)r   r)   r*   r+   r,   r(   r:   s         €r   ru   zXAIChatConfig.transform_requestÎ   s(   ø€ ô ,¨HÓ5ˆÜ‰wÑ(¨°¸/È>Ð[bÓcÐcr!   Úchoicec                 ó¦   — | j                   dk(  rB| j                  j                  r+t        | j                  j                  «      dkD  rd| _         yyyy)zó
        Helper to fix finish_reason for tool calls when XAI API returns empty string.

        XAI API returns empty string for finish_reason when using tools,
        so we need to set it to "tool_calls" when tool_calls are present.
        Ú r   Ú
tool_callsN)Úfinish_reasonr3   ry   rh   )rv   s    r   Ú(_fix_choice_finish_reason_for_tool_callsz6XAIChatConfig._fix_choice_finish_reason_for_tool_callsÞ   sJ   € ð ×Ñ 2Ò%¨&¯.©.×*CÒ*CÌÈFÏNÉN×LeÑLeÓHfÐijÒHjØ#/ˆFÕ ð IkÐ*CÐ%r!   Úraw_responseÚmodel_responseÚrequest_datac                 ó²  •— t         ‰| �  |||||||||	|
|¬«      }|j                  r3|j                  D ]$  }t        |t        «      sŒ| j                  |«       Œ& 	 |j                  «       }| j                  ||«       | j                  |«       | j                  t        |dd«      «       |S # t        $ r }t        j                  d|«       Y d}~ŒSd}~ww xY w)a  
        Transform the response from the XAI API.

        XAI API returns empty string for finish_reason when using tools,
        so we need to fix this after the standard OpenAI transformation.

        Also handles X.AI web search usage tracking.
        )r)   r|   r}   Úlogging_objr~   r*   r+   r,   Úencodingr#   rp   z*Error extracting X.AI web search usage: %sNÚusage)r7   Útransform_responseÚchoicesÚ
isinstancer   r{   ÚjsonÚ)_enhance_usage_with_xai_web_search_fieldsrX   r   rY   Ú&_fold_reasoning_tokens_into_completionÚ)_normalize_openai_compatible_usage_totalsÚgetattr)r   r)   r|   r}   r€   r~   r*   r+   r,   r�   r#   rp   Úresponserv   Úraw_response_jsonr[   r:   s                   €r   rƒ   z XAIChatConfig.transform_responseé   sï   ø€ ô0  ™'Ñ4ØØ%Ø)Ø#Ø%ØØ+Ø)ØØØð 5ó 
ˆð ×ÒØ"×*Ñ*ò J�Ü˜f¤gÕ.Ø×AÑAÀ&ÕIðJð
	RØ'3×'8Ñ'8Ó':ÐØ×:Ñ:¸8ÐEVÔWð 	×3Ñ3°HÔ=Ø×6Ñ6´w¸xÈÐRVÓ7WÔXØˆøô ò 	RÜ× Ñ Ð!MÈq×QÑQûð	Rús   Á"B- Â-	CÂ6CÃCÚtargetc                 ód  — | €yt        | t        «      rt        | dd«      }n| }|€yt        |t        «      rÜ|j	                  d«      xs i }t        |t        «      rt        |j	                  d«      xs d«      }nt        t        |dd«      xs d«      }|dk  ryt        |j	                  d«      xs d«      }t        |j	                  d«      xs d«      }t        |j	                  d«      xs d«      }|||z   k(  ry|||z   |z   k7  ry||z   |d<   yt        |dd«      }|rt        t        |dd«      xs d«      nd}|dk  ryt        t        |dd«      xs d«      }t        t        |dd«      xs d«      }t        t        |dd«      xs d«      }|||z   k(  ry|||z   |z   k7  ry||z   |_        y)	a  Reconcile xAI Usage to the OpenAI invariant.

        xAI accounts ``reasoning_tokens`` separately from
        ``completion_tokens`` while still summing them into ``total_tokens``.
        OpenAI's contract (o1/o3) folds reasoning into ``completion_tokens``,
        so fold here to keep ``total = prompt + completion``. Idempotent.

        Accepts a ``ModelResponse`` (non-streaming), a ``Usage`` object, or a
        raw usage ``dict`` (streaming chunk) so streaming and non-streaming
        paths stay in sync.
        Nr‚   Úcompletion_tokens_detailsÚreasoning_tokensr   Úprompt_tokensÚcompletion_tokensÚtotal_tokens)r…   r   rŠ   ÚdictÚgetÚintr’   )r�   r‚   Údetailsr�   r‘   r’   r“   s          r   rˆ   z4XAIChatConfig._fold_reasoning_tokens_into_completion   sÜ  € ð ˆ>Øä�fœmÔ,Ü3:¸6À7ÈDÓ3Q‰EàˆEØˆ=Øä�eœTÔ"Ø—i‘iÐ ;Ó<ÒBÀˆGÜ˜'¤4Ô(Ü#& w§{¡{Ð3EÓ'FÒ'KÈ!Ó#LÑ ä#&¤w¨wÐ8JÈAÓ'NÒ'SÐRSÓ#TÐ Ø 1Ò$Øä §	¡	¨/Ó :Ò ?¸aÓ@ˆMÜ # E§I¡IÐ.AÓ$BÒ$GÀaÓ HÐÜ˜uŸy™y¨Ó8Ò=¸AÓ>ˆLà˜}Ð/@Ñ@Ò@Øð ˜}Ð/@Ñ@ÐCSÑSÒSØà):Ð=MÑ)MˆEÐ%Ñ&Øä˜%Ð!<¸dÓCˆÙPWœ3œw wÐ0BÀAÓFÒKÈ!ÔLÐ]^ÐØ˜qÒ ØäœG E¨?¸AÓ>ÒCÀ!ÓDˆÜ¤¨Ð/BÀAÓ FÒ KÈ!ÓLÐÜœ7 5¨.¸!Ó<ÒAÀÓBˆà˜=Ð+<Ñ<Ò<Øð ˜=Ð+<Ñ<Ð?OÑOÒOØà"3Ð6FÑ"FˆÕr!   rŒ   c                 ó  — t        |d«      r|j                  €y|j                  }|j                  d«      }t        |t        «      sy|j                  d«      }t        |t
        «      r#t        ||«       t        j                  d|«       yy)z–
        Copy usage.server_side_tool_usage_details from the provider usage block
        onto model_response.usage for tool cost calculation.
        r‚   NÚserver_side_tool_usage_detailsz'X.AI server_side_tool_usage_details: %s)	Úhasattrr‚   r•   r…   r”   r   r   r   rY   )r   r}   rŒ   r‚   Úresponse_usager—   s         r   r‡   z7XAIChatConfig._enhance_usage_with_xai_web_search_fieldsb  s   € ô
 �~ wÔ/°>×3GÑ3GÐ3OØà,×2Ñ2ˆØ 1× 5Ñ 5°gÓ >ˆÜ˜.¬$Ô/ØØ'×+Ñ+Ð,LÓMˆÜ�gœwÔ'Ü9¸%ÀÔIÜ× Ñ Ð!JÈGÕTð (r!   r‚   c                 ó°  — | €y t        | t        «      rht        | j                  d«      xs d«      }t        | j                  d«      xs d«      }||z   }t        | j                  d«      xs d«      |k  r|| d<   y t        | j                  xs d«      }t        | j
                  xs d«      }||z   }t        | j                  xs d«      |k  r|| _        y y )Nr‘   r   r’   r“   )r…   r”   r–   r•   r‘   r’   r“   )r‚   r‘   r’   Úexpected_totals       r   r‰   z7XAIChatConfig._normalize_openai_compatible_usage_totalss  sÖ   € ð ˆ=ØÜ�eœTÔ"Ü §	¡	¨/Ó :Ò ?¸aÓ@ˆMÜ # E§I¡IÐ.AÓ$BÒ$GÀaÓ HÐØ*Ð->Ñ>ˆNÜ�5—9‘9˜^Ó,Ò1°Ó2°^ÒCØ(6��nÑ%ØÜ˜E×/Ñ/Ò4°1Ó5ˆÜ × 7Ñ 7Ò <¸1Ó=ÐØ&Ð):Ñ:ˆÜˆu×!Ñ!Ò& QÓ'¨.Ò8Ø!/ˆEÕð 9r!   )NN)N)F)#Ú__name__Ú
__module__Ú__qualname__Úpropertyr6   r    Útupler'   r”   Úlistr   r8   Úboolr>   r\   rS   rU   rm   r   r   r   r   rs   ru   Ústaticmethodr   r{   ÚhttpxÚResponserƒ   r   rˆ   r‡   r‰   Ú__classcell__©r:   s   @r   r   r   !   s\  ø„ Øð S¨4¡Zò ó ðð)Ø˜d™
ð)Ø-0°4©Zð)à	ˆs�T‰z˜3 ™:Ð%Ñ	&ó)ð #Ø#ñ&
àð&
ð ð&
ð Ð'Ñ(ð	&
ð
 ð&
ð ð&
ð �t‘ð&
ð ˜‘*ð&
ð 
õ&
ð^ #ñ
à˜‘*ð
ð �t‘ð
ð ð	
ð
 ð
ð ð
ð �t‘ð
ð 
õ
ð0*"°ð *"¸ó *"ðX¨3ð °4ó ð

°ð 
¸ó 
ð" "ñà ðð ðð ð	ð
 ðð 
óð8 "'ñ	

à$ S™M¨M¸#Ñ,>Ñ>ÀÑNð

ð ð

ð ˜$‘;ð	

ð
 
ó

ðdàðdð Ð'Ñ(ðdð ð	dð
 ðdð ðdð 
õdð  ð0¸ð 0ÀTò 0ó ð0ð* #Ø!%ñ5àð5ð —n‘nð5ð &ð	5ð ð5ð Ð'Ñ(ð5ð ð5ð ð5ð �t‘ð5ð ˜$‘;ð5ð 
õ5ðn ð?GØ Ñ%¨¨S°#¨X©Ñ6¸Ñ=ð?Gà	ò?Gó ð?GðBUÈð UÐjnð UÐswó Uð" ð0Ø�t˜C ˜H‘~Ñ%¨Ñ,ð0à	ò0ó ô0r!   r   c                   ó(   ‡ — e Zd Zdedefˆ fd„Zˆ xZS )rr   Úchunkr   c                 óð   •— |j                  dg «      }t        |«      dk(  rd|v r
di ddœg|d<   d|v r5|d   �0t        j                  |d   «       t        j	                  |d   «       t
        ‰| �  |«      S )a³  
        Handle xAI-specific streaming behavior.

        xAI Grok sends a final chunk with empty choices array but with usage data
        when stream_options={"include_usage": True} is set.

        Example from xAI API:
        {"id":"...","object":"chat.completion.chunk","created":...,"model":"grok-4-1-fast-non-reasoning",
         "choices":[],"usage":{"prompt_tokens":171,"completion_tokens":2,"total_tokens":173,...}}
        r„   r   r‚   N)ÚindexÚdeltarz   )r•   rh   r   rˆ   r‰   r7   Úchunk_parser)r   r«   r„   r:   s      €r   r¯   z.XAIChatCompletionStreamingHandler.chunk_parserˆ  sƒ   ø€ ð Ÿ™ 9¨bÓ1ˆÜˆw‹<˜1Ò ¨EÑ!1ð +,°bÈ4Ñ PÐQˆE�)Ñà�eÑ  g¡Ð :Ü×@Ñ@ÀÀwÁÔPÜ×CÑCÀEÈ'ÁNÔSä‰wÑ# EÓ*Ð*r!   )rž   rŸ   r    r”   r   r¯   r¨   r©   s   @r   rr   rr   ‡  s   ø„ ð+ $ð +Ð+>÷ +ñ +r!   rr   )$Úcollections.abcr   r   r   Útypingr   r   r¦   rV   Úlitellm._loggingr   Úlitellm.constantsr	   Úlitellm.exceptionsr
   Ú8litellm.litellm_core_utils.prompt_templates.common_utilsr   r   Úlitellm.llms.xai.common_utilsr   Ú litellm.llms.xai.cost_calculatorr   Úlitellm.secret_managers.mainr   Úlitellm.types.llms.openair   Úlitellm.types.utilsr   r   r   r   Úopenai.chat.gpt_transformationr   r   r   rr   r   r!   r   ú<module>r¼      s_   ðß <Ñ <ß ã ã Ý +Ý *Ý 2÷õ 7õõ 8Ý 6÷ó ÷ôc0�Oô c0ôL+Ð(Lõ +r!   