Ë
    uPêj¼B  ã                   óš   — d Z ddlmZmZmZ ddlmZmZmZm	Z	m
Z
 ddlZddlmZmZ ddlmZ ddlmZ ddlmZmZ d	d
lmZ  G d„ de«      Zy)zV
Translates from OpenAI's `/v1/chat/completions` to DeepSeek's `/v1/chat/completions`
é    )Ú	CoroutineÚMappingÚSequence)ÚAnyÚFinalÚLiteralÚcastÚoverloadN)Úconvert_content_list_to_strÚextract_search_results_text©Úget_secret_str)ÚAllMessageValues)Úsupports_reasoningÚsupports_visioné   )ÚOpenAIGPTConfigc                   óŽ  ‡ — e Zd Zdedefˆ fd„Zdededededef
ˆ fd„Zdee	   dee	   fd	„Z
edee	   ded
ed   deeeee	   f   fd„«       Ze	 d&dee	   ded
ed   dee	   fd„«       Z	 d&dee	   ded
edee	   eeeee	   f   z  fˆ fd„Zde	dede	fd„Zde	dee   defd„Zededefd„«       Zededefd„«       Zde	dee   de	fd„Zdededefd„Zededefd„«       Zdedee	   dedededefˆ fd„Zdedee	   dedededefˆ 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!z  d"ed!z  dededed$ed!z  defd%„Zˆ xZS )(ÚDeepSeekChatConfigÚmodelÚreturnc                 óL   •— t         ‰| �  |«      }|j                  ddg«       |S )zF
        DeepSeek reasoner models support thinking parameter.
        ÚthinkingÚreasoning_effort)ÚsuperÚget_supported_openai_paramsÚextend)Úselfr   ÚparamsÚ	__class__s      €ún/home/oem/CyberBrain26-unified/.venv/lib/python3.12/site-packages/litellm/llms/deepseek/chat/transformation.pyr   z.DeepSeekChatConfig.get_supported_openai_params   s+   ø€ ô ™Ñ;¸EÓBˆØ�‰�zÐ#5Ð6Ô7Øˆó    Únon_default_paramsÚoptional_paramsÚdrop_paramsc                 óò   •— t         ‰| �  ||||«      }|j                  dd«      }|j                  dd«      }t        |t        «      r|j                  d«      dv rd|d   i|d<   |S |�d|dk(  rdndi|d<   |S )	aí  
        Map OpenAI params to DeepSeek params.

        Handles `thinking` and `reasoning_effort` parameters for DeepSeek reasoner models.
        DeepSeek supports `{"type": "enabled"}` and `{"type": "disabled"}` - no budget_tokens
        like Anthropic. `reasoning_effort="none"` is the OpenAI-style way to ask for thinking
        off, so it maps to `{"type": "disabled"}`; any other effort keeps thinking on.

        Reference: https://api-docs.deepseek.com/guides/thinking_mode
        r   Nr   Útype)ÚenabledÚdisabledÚnoner)   r(   )r   Úmap_openai_paramsÚpopÚ
isinstanceÚdictÚget)r   r#   r$   r   r%   Úthinking_valuer   r    s          €r!   r+   z$DeepSeekChatConfig.map_openai_params   s©   ø€ ô$  ™'Ñ3Ð4FÈÐY^Ð`kÓlˆð !0× 3Ñ 3°JÀÓ EˆØ"1×"5Ñ"5Ð6HÈ$Ó"OÐô �n¤dÔ+°×0BÑ0BÀ6Ó0JÐNeÑ0eØ+1°>À&Ñ3IÐ*JˆO˜JÑ'ð Ðð Ð)Ø+1ÐAQÐU[ÒA[±:ÐajÐ*kˆO˜JÑ'àÐr"   Úmessagesc                 óÞ  — g }|D ]å  }|j                  d«      dk(  r¾|j                  d«      s­t        t        t        |«      «      }|j                  d«      xs i }|j                  d«      }|r(||d<   t        |«      }|j                  dd«       ||d<   n$t        j
                  j                  d«       d|d<   |j                  t        t        |«      «       ŒÕ|j                  |«       Œç |S )uU  
        DeepSeek thinking mode requires `reasoning_content` to be passed back on
        every assistant message in multi-turn conversations. If it is missing,
        the API returns:
          "The reasoning_content in the thinking mode must be passed back to the API."

        For each assistant message that is missing `reasoning_content`:
          1. Promote it from `provider_specific_fields["reasoning_content"]` if present
             (LiteLLM stores provider-specific response fields there).
          2. Otherwise inject a single space â€” the minimum value the API accepts.
        ÚroleÚ	assistantÚreasoning_contentÚprovider_specific_fieldsNa­  DeepSeek thinking mode: assistant message is missing `reasoning_content` and none was saved in `provider_specific_fields`. A single-space placeholder is being injected to satisfy API validation, but the model will receive a blank reasoning chain for this turn, which may silently degrade multi-turn response quality. Preserve `reasoning_content` from the original assistant response when building multi-turn conversation history.ú )	r/   r.   r	   r,   ÚlitellmÚverbose_loggerÚwarningÚappendr   )r   r1   ÚresultÚmsgÚpatchedÚprovider_fieldsÚstoredÚcleaneds           r!   Ú_fill_reasoning_contentz*DeepSeekChatConfig._fill_reasoning_content@   sé   € ð 13ˆØò 	#ˆCØ�w‰w�v‹ +Ò-°c·g±gÐ>QÔ6RÜœt¤D¨#›Ó/�Ø")§+¡+Ð.HÓ"IÒ"OÈR�Ø(×,Ñ,Ð-@ÓA�ÙØ39�GÐ/Ñ0Ü" ?Ó3�GØ—K‘KÐ 3°TÔ:Ø:A�GÐ6Ò7ä×*Ñ*×2Ñ2ðRô	ð 47�GÐ/Ñ0Ø—‘œdÔ#3°WÓ=Õ>à—‘˜cÕ"ð1	#ð2 ˆr"   Úis_asyncTc                  ó   — y ©N© ©r   r1   r   rC   s       r!   Ú_transform_messagesz&DeepSeekChatConfig._transform_messagesh   s   € ð 7:r"   Fc                  ó   — y rE   rF   rG   s       r!   rH   z&DeepSeekChatConfig._transform_messagesm   s   € ð "%r"   c                 óÜ   •— t        d„ |D «       «      xr t        |d¬«      }|D �cg c]  }| j                  ||¬«      ‘Œ }}|rt        ‰| �  ||d¬«      S t        ‰| �  ||d¬«      S c c}w )aø  
        DeepSeek vision models accept image_url content blocks in user
        messages (https://api-docs.deepseek.com/guides/vision), so those
        content lists are forwarded as-is, with any search_results text
        appended as a trailing text block. Every other message keeps the
        historical string collapse (which also folds search_results text
        into string content); a list with no extractable text stays
        unchanged, matching what DeepSeek historically received.
        c              3   óZ   K  — | ]#  }t        |j                  d «      t        «      –— Œ% y­w)ÚcontentN)r-   r/   Úlist)Ú.0Úmessages     r!   ú	<genexpr>z9DeepSeekChatConfig._transform_messages.<locals>.<genexpr>�   s%   è ø€ ò $
Ø9@ŒJ�w—{‘{ 9Ó-¬t×4ñ$
ùs   ‚)+Údeepseek©r   Úcustom_llm_provider)rO   Úforward_imagesT)r1   r   rC   F)Úanyr   Ú_forward_or_collapse_contentr   rH   )r   r1   r   rC   rT   rO   Útransformedr    s          €r!   rH   z&DeepSeekChatConfig._transform_messagesu   s—   ø€ ô !$ñ $
ØDLô$
ó !
ò !Kä E¸zÔJð 	ð nvö
ØbiˆD×-Ñ-°gÈnÐ-Õ]ð
ˆð 
ñ Ü‘7Ñ.¸È5Ð[_Ð.Ó`Ð`ä‘7Ñ.¸È5Ð[`Ð.ÓaÐaùò
s   §A)rO   rT   c                 óî   — |j                  d«      }|r6t        |t        «      r&| j                  ||¬«      r| j	                  ||¬«      S t        |¬«      }|r||k(  r|S i |¥d|i¥}t        t        |«      S )a   
        Returns the vision-forwardable message with any search_results text
        appended as a text block; every other message keeps the historical
        string collapse, which extracts the text from a content list and
        folds search_results text into string content.
        rL   )rO   rL   )rO   )r/   r-   rM   Ú_is_vision_forwardable_contentÚ_with_search_results_text_blockr   r	   r   )r   rO   rT   rL   Ú	collapsedÚcollapsed_messages         r!   rV   z/DeepSeekChatConfig._forward_or_collapse_content�   sƒ   € ð !Ÿ™ YÓ/ˆáÜ˜7¤DÔ)Ø×3Ñ3¸GÈWÐ3ÔUà×7Ñ7ÀÐQXÐ7ÓYÐYÜ6¸wÔGˆ	Ù˜I¨Ò0ØˆNØ#D gÐ#D¨y¸)Ñ#DÐÜÔ$Ð&7Ó8Ð8r"   rL   c                 ó|   ‡ — |j                  d«      dk7  ryt        ˆ fd„|D «       «      syt        d„ |D «       «      S )aG  
        True only for a user message whose content list holds well-formed
        text and image_url blocks with at least one image; a block missing
        its payload falls back to the string collapse instead of crashing
        or reaching the wire malformed. The model capability gate lives in
        the caller.
        r3   ÚuserFc              3   ó@   •K  — | ]  }‰j                  |«      –— Œ y ­wrE   )Ú_is_forwardable_block)rN   Úblockr   s     €r!   rP   zDDeepSeekChatConfig._is_vision_forwardable_content.<locals>.<genexpr>«   s   øè ø€ ÒJ¸�4×-Ñ-¨e×4ÑJùs   ƒc              3   óh   K  — | ]*  }t        |t        «      xr |j                  d «      dk(  –— Œ, y­w)r'   Ú	image_urlN©r-   r.   r/   )rN   ra   s     r!   rP   zDDeepSeekChatConfig._is_vision_forwardable_content.<locals>.<genexpr>­   s.   è ø€ ÒeÐTY”:˜e¤TÓ*ÒO¨u¯y©y¸Ó/@ÀKÑ/OÓOÑeùs   ‚02)r/   ÚallrU   )r   rO   rL   s   `  r!   rY   z1DeepSeekChatConfig._is_vision_forwardable_content¡   s<   ø€ ð �;‰;�vÓ &Ò(ØÜÓJÀ'ÔJÔJØÜÑeÐ]dÔeÓeÐer"   ra   c                 óâ   — t        | t        «      sy| j                  d«      }|dk(  r$t        j	                  | j                  d«      «      S |dk(  rt        | j                  d«      t
        «      S y)z>A dict block typed text or image_url that carries its payload.Fr'   rc   Útext)r-   r.   r/   r   Ú_is_image_url_payloadÚstr)ra   Ú
block_types     r!   r`   z(DeepSeekChatConfig._is_forwardable_block¯   sb   € ô ˜%¤Ô&ØØ!ŸI™I fÓ-ˆ
Ø˜Ò$Ü%×;Ñ;¸E¿I¹IÀkÓ<RÓSÐSØ˜ÒÜ˜eŸi™i¨Ó/´Ó5Ð5Ør"   Úpayloadc                 ó¶   — t        | t        «      rt        | «      S t        | t        «      sy| j	                  d«      }t        |t        «      xr t        |«      S )zGA url string or an object carrying one, per the OpenAI image_url shape.FÚurl)r-   ri   Úboolr   r/   )rk   rm   s     r!   rh   z(DeepSeekChatConfig._is_image_url_payload»   sI   € ô �gœsÔ#Ü˜“=Ð Ü˜'¤7Ô+ØØ—[‘[ Ó'ˆÜ˜#œsÓ#Ò1¬¨S«	Ð1r"   c                 ó  — t        t        t        t        f   |«      }t	        |j                  d«      «      }|s|S g |¢d|dœ‘}i |j                  «       D ��ci c]  \  }}|dk7  sŒ||“Œ c}}¥d|i¥}t        t        |«      S c c}}w )zæ
        Appends the message's search_results text as a trailing text block,
        keeping the context that the string collapse used to fold in, and
        drops the non-OpenAI search_results key from the wire message.
        Úsearch_resultsrg   )r'   rg   rL   )r	   r   ri   Úobjectr   r/   Úitemsr   )	r   rO   rL   Úmessage_fieldsÚsearch_textÚforwarded_contentÚkeyÚvalueÚ	forwardeds	            r!   rZ   z2DeepSeekChatConfig._with_search_results_text_blockÅ   s    € ô !%¤W¬S´&¨[Ñ%9¸7Ó CˆÜ8¸×9KÑ9KÐL\Ó9]Ó^ˆÙØˆNØ#T WÐ#T°vÀ{Ñ.SÐ#TÐð
Ø,:×,@Ñ,@Ó,B×^™j˜c 5ÀcÐM]ÓF]ˆs�E‰zÓ^ð
àÐ(ñ
ˆ	ô Ô$ iÓ0Ð0ùó _s   ÁBÁ'Bc                 óŽ   — |j                  d«      }t        |d¬«      xr& t        |t        «      xr |j                  d«      dk(  S )zâ
        Returns True only when thinking mode is actually active for this request:
          - model supports reasoning (capability check)
          - user explicitly passed thinking={"type": "enabled"} (opt-in check)
        r   rQ   rR   r'   r(   )r/   r   r-   r.   )r   r   r$   r   s       r!   Ú_thinking_mode_activez(DeepSeekChatConfig._thinking_mode_activeÖ   sH   € ð *×-Ñ-¨jÓ9ˆä UÀ
ÔKò 2Ü˜8¤TÓ*ò2à—‘˜VÓ$¨	Ñ1ð	
r"   c           
      óà  — | j                  d«      }t        |t        «      r|s| S dt        dt        fd„}dt        dt
        dz  fd„}dt        dt        t
           dt        fd	„}|D �cg c]  } ||«      sŒ|‘Œ }}t        |«      t        |«      k(  r| S t        |D �ch c]I  } ||«      s?t        |t        «      rt        |j                  d
«      «      nt        |«      j                  ’ŒK c}«      }t        j                  j                  d|«       | j                  «       D ��	ci c]  \  }}	|dk7  sŒ||	“Œ }
}}	|re|D ��ch c]  } ||«      }|€Œ|’Œ }}} ||
j                  d«      |«      s)|
j                  «       D ��	ci c]  \  }}	|dk7  sŒ||	“Œ }
}}	i |
¥d|i¥S |
j                  «       D ��	ci c]  \  }}	|dvsŒ||	“Œ c}	}S c c}w c c}w c c}	}w c c}}w c c}	}w c c}	}w )a¨  
        DeepSeek's /chat/completions only accepts tools of type "function".

        Requests bridged from /v1/responses can carry responses-API-native tool
        types (e.g. a Codex CLI tool typed "namespace"); DeepSeek rejects the
        whole request with `unknown variant '<type>', expected 'function'` (issue
        #30722). Drop the unsupported entries so the function tools still go
        through, and drop the now-dangling tool_choice/parallel_tool_calls when
        nothing callable survives.

        When a specific `tool_choice` points at a dropped tool, clear it so the
        sanitized request does not reference a tool DeepSeek will never receive.
        ÚtoolsÚtoolr   c                 óN   — t        | t        «      xr | j                  d«      dk(  S )Nr'   Úfunctionrd   )r}   s    r!   Ú_is_function_toolzEDeepSeekChatConfig._drop_unsupported_tools.<locals>._is_function_toolö   s"   € Ü˜d¤DÓ)ÒL¨d¯h©h°vÓ.>À*Ñ.LÐLr"   Nc                 ó²   — t        | t        «      sy | j                  d«      }t        |t        «      sy |j                  d«      }t        |t        «      r|S d S )Nr   Úname©r-   r.   r/   ri   )r}   r   r‚   s      r!   Ú_get_function_tool_namezKDeepSeekChatConfig._drop_unsupported_tools.<locals>._get_function_tool_nameù   sL   € Ü˜d¤DÔ)ØØ"Ÿh™h zÓ2ˆHÜ˜h¬Ô-ØØ"Ÿ,™, vÓ.ˆDÜ% d¬CÔ0�4Ð:°dÐ:r"   Útool_choiceÚfunction_tool_namesc                 óà   — t        | t        «      sy| j                  d«      dk7  ry| j                  d«      }t        |t        «      sy|j                  d«      }t        |t        «      xr ||v S )NTr'   r   Fr‚   rƒ   )r…   r†   r   r‚   s       r!   Ú"_tool_choice_matches_function_toolzVDeepSeekChatConfig._drop_unsupported_tools.<locals>._tool_choice_matches_function_tool  sd   € Ü˜k¬4Ô0ØØ�‰˜vÓ&¨*Ò4ØØ)Ÿo™o¨jÓ9ˆHÜ˜h¬Ô-ØØ"Ÿ,™, vÓ.ˆDÜ˜d¤CÓ(ÒH¨TÐ5HÐ-HÐHr"   r'   zwDeepSeek chat completions only supports function tools; dropping unsupported tool type(s) %s before sending the request)r…   Úparallel_tool_calls)r/   r-   rM   rq   rn   ri   ÚsetÚlenÚsortedr.   r'   Ú__name__r8   r9   r:   rr   )r$   r|   r€   r„   rˆ   r}   Úfunction_toolsÚdropped_typesÚkÚvrA   r‚   r†   s                r!   Ú_drop_unsupported_toolsz*DeepSeekChatConfig._drop_unsupported_toolsã   s  € ð '×*Ñ*¨7Ó3ˆÜ˜%¤Ô&©eØ"Ð"ð	M¤Fð 	M¬tó 	Mð	;¬&ð 	;´S¸4±Zó 	;ð		I¼Fð 		IÔY\Ô]`ÑYað 		IÔfjó 		Ið 38Ö S¨$Ñ;LÈTÕ;R¢Ð SˆÐ SÜˆ~Ó¤# e£*Ò,Ø"Ð"ä%ð "öàÙ(¨Ô.ô *4°D¼$Ô)?”�D—H‘H˜VÓ$Ô%ÄTÈ$ÃZ×EXÑEXÑXòó 
ˆô 	×Ñ×&Ñ&ðEàô	
ð %4×$9Ñ$9Ó$;×L™D˜A˜q¸qÀG»|�1�a‘4ÐLˆÑLÙà!/÷*ØÑ=TÐUYÓ=Z°DÐ`dÑ`p’ð*Ðñ *ñ 6°g·k±kÀ-Ó6PÐReÔfØ,3¯M©M«O×R¡D A q¸qÀMÓ?Q˜1˜a™4ÐR�ÑRØ7�gÐ7˜w¨Ñ7Ð7Ø!(§¡£×d™˜˜A°AÐ=cÒ4c��1‘ÓdÐdùò3 !Tùò
ùó Mùó*ùó SùãdsC   Á*GÁ8GÂ AGÄ(GÄ6GÅGÅGÆG$ÆG$Æ8G*ÇG*Úlitellm_paramsÚheadersc                 ó–   •— | j                  |«      }| j                  ||¬«      r| j                  |«      }t        ‰| �  |||||¬«      S )aÊ  
        Ensures `reasoning_content` is forwarded on assistant messages for
        multi-turn thinking-mode conversations (issue #28045).

        Only runs when thinking mode is actually active - guarded by both
        supports_reasoning() (model capability) and optional_params["thinking"]
        (user explicitly enabled it), preventing spurious injection on models
        like deepseek-v3.2 that support thinking as opt-in but not always-on.
        ©r   r$   ©r   r1   r$   r“   r”   )r’   rz   rB   r   Útransform_request©r   r   r1   r$   r“   r”   r    s         €r!   r˜   z$DeepSeekChatConfig.transform_request(  s^   ø€ ð" ×6Ñ6°ÓGˆØ×%Ñ%¨EÀ?Ð%ÔSØ×3Ñ3°HÓ=ˆHÜ‰wÑ(ØØØ+Ø)Øð )ó 
ð 	
r"   c              ƒ   ó²   •K  — | j                  |«      }| j                  ||¬«      r| j                  |«      }t        ‰| �  |||||¬«      ƒ d{  –—† S 7 Œ­w)u–   
        Async equivalent of transform_request â€” applies the same reasoning_content
        fix for multi-turn thinking-mode conversations.
        r–   r—   N)r’   rz   rB   r   Úasync_transform_requestr™   s         €r!   r›   z*DeepSeekChatConfig.async_transform_requestD  sl   øè ø€ ð ×6Ñ6°ÓGˆØ×%Ñ%¨EÀ?Ð%ÔSØ×3Ñ3°HÓ=ˆHÜ‘WÑ4ØØØ+Ø)Øð 5ó 
÷ 
ð 	
ð 
ús   ƒAAÁAÁAÚapi_baseNÚapi_keyc                 óN   — |xs t        d«      xs d}|xs t        d«      }||fS )NÚDEEPSEEK_API_BASEúhttps://api.deepseek.com/betaÚDEEPSEEK_API_KEYr   )r   rœ   r�   Údynamic_api_keys       r!   Ú$_get_openai_compatible_provider_infoz7DeepSeekChatConfig._get_openai_compatible_provider_info[  s5   € ð Òeœ~Ð.AÓBÒeÐFeˆØ!(Ò!N¬NÐ;MÓ,NˆØ˜Ð(Ð(r"   Ústreamc                 ó:   — |sd}|j                  d«      s|› d�}|S )zc
        If api_base is not provided, use the default DeepSeek /chat/completions endpoint.
        r    z/chat/completions)Úendswith)r   rœ   r�   r   r$   r“   r¤   s          r!   Úget_complete_urlz#DeepSeekChatConfig.get_complete_urlb  s-   € ñ Ø6ˆHà× Ñ Ð!4Ô5Ø"˜Ð#4Ð5ˆHàˆr"   )FrE   ) r�   Ú
__module__Ú__qualname__ri   rM   r   r.   rn   r+   r   rB   r
   r   r   r   rH   rV   r   rq   rY   Ústaticmethodr`   rh   rZ   rz   r’   r˜   r›   Útupler£   r§   Ú__classcell__)r    s   @r!   r   r      sj  ø„ ð°ð ¸õ ð!à ð!ð ð!ð ð	!ð
 ð!ð 
õ!ðF&°Ð5EÑ0Fð &È4ÐP`ÑKaó &ðP ð:ØÐ-Ñ.ð:Ø7:ð:ØFMÈdÁmð:à	�3˜˜TÐ"2Ñ3Ð3Ñ	4ò:ó ð:ð ð
 $)ñ	%àÐ'Ñ(ð%ð ð%ð ˜%‘.ð	%ð
 
ÐÑ	ò%ó ð%ð NSñbØÐ-Ñ.ðbØ7:ðbØFJðbà	ÐÑ	 )¨C°°dÐ;KÑ6LÐ,LÑ"MÑ	Mõbð09Ð4Dð 9ÐVZð 9Ð_oó 9ð(fÐ6Fð fÐQYÐZ`ÑQað fÐfjó fð ð	 Vð 	°ò 	ó ð	ð ð2 vð 2°$ò 2ó ð2ð1Ð7Gð 1ÐRZÐ[aÑRbð 1Ðgwó 1ð"
¨3ð 
Àð 
È$ó 
ð ðBe°ð Be¸$ò Beó ðBeðH
àð
ð Ð'Ñ(ð
ð ð	
ð
 ð
ð ð
ð 
õ
ð8
àð
ð Ð'Ñ(ð
ð ð	
ð
 ð
ð ð
ð 
õ
ð.)Ø˜d™
ð)Ø-0°4©Zð)à	ˆs�T‰z˜3 ™:Ð%Ñ	&ó)ð #ñà˜‘*ðð �t‘ðð ð	ð
 ðð ðð �t‘ðð 
÷r"   r   )Ú__doc__Úcollections.abcr   r   r   Útypingr   r   r   r	   r
   r8   Ú8litellm.litellm_core_utils.prompt_templates.common_utilsr   r   Úlitellm.secret_managers.mainr   Úlitellm.types.llms.openair   Úlitellm.utilsr   r   Úopenai.chat.gpt_transformationr   r   rF   r"   r!   ú<module>rµ      s<   ðñ÷ 9Ñ 8ß 6Õ 6ã ÷õ 8Ý 6ß =å =ô`˜õ `r"   