§
    ÚŽ’j³e  ã                   ó4  — d 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
mZmZ ddlmZmZ ddlmZ dd	lmZmZ d
dlmZm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#m$Z$m%Z%m&Z&m'Z'm(Z( ddl)m*Z* e
rddl+m,Z, ddl-m.Z. neZ,eZ. G d„ de¦  «        Z/dS )z1The OpenAI Chat Completions model implementation.é    N)ÚOrderedDict)Údatetime)ÚLiteralÚAnyÚAsyncGeneratorÚTYPE_CHECKINGÚListÚType)Ú	BaseModelÚFieldé   )Ú_build_streaming_wav_header)Ú_generate_idÚ_flatten_json_schemaé   )ÚChatModelBaseÚ_TOOL_CHOICE_LITERAL_MODES)ÚChatResponseÚStructuredResponse)Ú	ChatUsage)ÚOpenAICredential)ÚFormatterBaseÚOpenAIChatFormatter)ÚMsgÚThinkingBlockÚToolCallBlockÚ	TextBlockÚ	DataBlockÚBase64Source)Ú
ToolChoice)ÚChatCompletion)ÚAsyncStreamc                   ó„  ‡ — e Zd ZU dZ G d„ de¦  «        ZdZed         ed<   	 	 	 	 	 	 	 	 	 d+de	de
dddedededededz  dee
ef         dz  dee
ef         dz  ddfˆ fd„Zedeee         df         fd„¦   «         Z	 	 d,de
dee         dee         dz  dedz  dedeeedf         z  fd„Zd ed!edeedf         fd"„Z	 d-d ed!e d$e
defd%„Z!	 d.de
dee         d&ee         ez  dedz  d'ede"fˆ fd(„Z#dee         dz  dedz  deee         dz  e
ez  dz  f         fd)„Z$e%dee         dee         fd*„¦   «         Z&ˆ xZ'S )/ÚOpenAIChatModelz"The OpenAI Chat Completions model.c                   óR  — e Zd ZU dZ edddd¬¦  «        Zedz  ed<    edd	d
¬¦  «        Ze	ed<    eddd¬¦  «        Z
ed         dz  ed<    eddddd¬¦  «        Zedz  ed<    eddddd¬¦  «        Zedz  ed<    eddd¬¦  «        Ze	ed<    eddd ¬¦  «        Zedz  ed!<   dS )"úOpenAIChatModel.Parametersz)The parameters for the OpenAI Chat model.Nz
Max Tokensz0The maximum number of tokens for the LLM output.r   )ÚdefaultÚtitleÚdescriptionÚgtÚ
max_tokensFÚThinkingz…Whether to enable reasoning for reasoning models (e.g. o3, o4-mini, gpt-5.5). Use reasoning_effort to control the depth of reasoning.)r'   r(   r)   Úthinking_enablezReasoning Effortz°Controls the depth of reasoning for reasoning models (e.g. o3, o4-mini, gpt-5.5). Supported values are model-dependent and may include: none, minimal, low, medium, high, xhigh.)ÚnoneÚminimalÚlowÚmediumÚhighÚxhighÚreasoning_effortÚTemperaturez#The temperature for the LLM output.r   )r'   r(   r)   ÚgeÚleÚtemperaturezTop Pz#The top P value for the LLM output.é   )r'   r(   r)   r*   r7   Útop_pTzParallel Tool Callsz&Whether to enable parallel tool calls.Úparallel_tool_callsÚVoiceup  Voice for audio output on omni-style models (e.g. ``gpt-audio-mini``). Setting this implicitly asks the model to speak its response â€” ``modalities`` is filled in automatically. Supported voices vary by model â€” see the model card's ``voice.suggestions``. Any value the API accepts works â€” the suggestions are convenience-only. Leave unset for text-only responses.Úvoice)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r+   ÚintÚ__annotations__r-   Úboolr4   r   r8   Úfloatr:   r;   r=   Ústr© ó    úRC:\Projects\DSCons\.venv\Lib\site-packages\agentscope\model\_openai_chat\_model.pyÚ
Parametersr&   '   s­  € € € € € € Ø7Ð7à!& ØØØJØð	"
ñ "
ô "
ˆ
�C˜$‘Jð 	
ð 	
ñ 	
ð !& ØØð2ð	!
ñ !
ô !
ˆ˜ð 	
ð 	
ñ 	
ð ˆEØØ$ð'ð		
ñ 	
ô 	
ð 	ØÐGÔHÈ4ÑOð	
ð 	
ñ 	
ð %* EØØØ=ØØð%
ñ %
ô %
ˆ�U˜T‘\ð 	
ð 	
ñ 	
ð $˜eØØØ=ØØð
ñ 
ô 
ˆˆu�t‰|ð 	
ð 	
ñ 	
ð %* EØØ'Ø@ð%
ñ %
ô %
Ð˜Tð 	
ð 	
ñ 	
ð "˜EØØðð	
ñ 
ô 
ˆˆs�T‰zð 	
ð 	
ñ 	
ð 	
ð 	
rH   rJ   Úopenai_chatÚtypeNTr   ç      ð?é ô Ú
credentialÚmodelÚ
parametersz!OpenAIChatModel.Parameters | NoneÚstreamÚmax_retriesÚretry_delayÚcontext_sizeÚ	formatterÚclient_kwargsÚ
extra_bodyÚreturnc           	      óŠ  •— t          ¦   «                              |||p|                      ¦   «         ||||¬¦  «         |pt          ¦   «         | _        |	pi | _        |
�t          |
¦  «        nd| _        ddl} |j	        d| j
        j                             ¦   «         | j
        j        | j
        j        dœ| j        ¤Ž| _        dS )a+  Initialize the OpenAI chat model.

        Args:
            credential (`OpenAICredential`):
                The OpenAI credential used to authenticate API calls.
            model (`str`):
                The OpenAI model name, e.g. ``gpt-4.1``.
            parameters (`OpenAIChatModel.Parameters | None`, defaults to             `None`):
                The OpenAI Chat API parameters. When ``None``, the default
                parameters will be used.
            stream (`bool`, defaults to `True`):
                Whether to enable streaming output.
            max_retries (`int`, defaults to `3`):
                The maximum number of retries for the OpenAI API.
            retry_delay (`float`, defaults to `1.0`):
                Seconds to sleep between retry attempts.
            context_size (`int`, defaults to `128000`):
                The model context size used for context compression.
            formatter (`FormatterBase | None`, defaults to `None`):
                The formatter that converts ``Msg`` objects to the format
                required by the OpenAI API. When ``None``, an
                ``OpenAIChatFormatter`` instance will be used.
            client_kwargs (`dict[str, Any] | None`, defaults to `None`):
                Extra keyword arguments forwarded to ``openai.AsyncClient``
                (e.g. ``timeout``, ``default_headers``, ``http_client``).
            extra_body (`dict[str, Any] | None`, defaults to `None`):
                Additional request body fields forwarded to
                OpenAI-compatible APIs.
        )rO   rP   rQ   rR   rS   rT   rU   Nr   )Úapi_keyÚorganizationÚbase_urlrG   )ÚsuperÚ__init__rJ   r   rV   rW   ÚdictrX   ÚopenaiÚAsyncClientrO   r[   Úget_secret_valuer\   r]   Úclient)ÚselfrO   rP   rQ   rR   rS   rT   rU   rV   rW   rX   ra   Ú	__class__s               €rI   r_   zOpenAIChatModel.__init__p   sä   ø€ õV 	‰Œ×ÒØ!ØØ!Ð6 T§_¢_Ñ%6Ô%6ØØ#Ø#Ø%ð 	ñ 	
ô 	
ð 	
ð #Ð;Õ&9Ñ&;Ô&;ˆŒØ*Ð0¨bˆÔØ.8Ð.D�$˜zÑ*Ô*Ð*È$ˆŒàˆˆˆà*<¨&Ô*<ð +
Ø”OÔ+×<Ò<Ñ>Ô>ØœÔ5Ø”_Ô-ð+
ð +
ð Ô ð	+
ð +
ˆŒˆˆrH   .c                 ó>   — dd l }|j        |j        |j        |j        fS )Nr   )ra   ÚAPIConnectionErrorÚAPITimeoutErrorÚRateLimitErrorÚInternalServerError)Úclsra   s     rI   Ú_get_retryable_exceptionsz)OpenAIChatModel._get_retryable_exceptions±   s/   € àˆˆˆð Ô%ØÔ"ØÔ!ØÔ&ð	
ð 	
rH   Ú
model_nameÚmessagesÚtoolsÚtool_choiceÚgenerate_kwargsc              ‹   óÞ  K  — | j                              |¦  «        ƒ d{V —†}||| j        dœ}| j        j        �| j        j        |d<   | j        j        �| j        j        |d<   | j        j        �| j        j        |d<   | j        j        r| j        j        r| j        j        |d<   | j        j	        �| j        j	        ddœ|d	<   d
d	g|d<   | j
        �t          | j
        ¦  «        |d<   |                     |¦  «         |                      ||¦  «        \  }}	|r||d<   | j        j        sd|d<   |	�|	|d<   | j        rddi|d<   t          j        ¦   «         }
 | j        j        j        j        di |¤Žƒ d{V —†}|                     d	¦  «        }t-          |t          ¦  «        r|                     dd¦  «        nd}| j        r|                      |
|¦  «        S |                      |
||¦  «        S )a9  Call the OpenAI Chat Completions API.

        Args:
            model_name (`str`):
                The model name to use for this call.
            messages (`list`):
                A list of message dicts with ``role`` and ``content`` keys.
            tools (`list[dict]`, default `None`):
                The tools JSON schemas.
            tool_choice (`ToolChoice | None`, optional):
                Controls which (if any) tool is called by the model.
            **generate_kwargs (`Any`):
                Extra keyword arguments forwarded to the API.

        Returns:
            `ChatResponse | AsyncGenerator[ChatResponse, None]`:
                A ``ChatResponse`` when streaming is disabled, or an async
                generator of ``ChatResponse`` objects when streaming is
                enabled.
        N)rP   ro   rR   Úmax_completion_tokensr8   r:   r4   Úpcm16)r=   ÚformatÚaudioÚtextÚ
modalitiesrX   rp   Fr;   rq   Úinclude_usageTÚstream_optionsrv   ÚwavrG   )rV   rv   rR   rQ   r+   r8   r:   r-   r4   r=   rX   r`   ÚupdateÚ_format_toolsr;   r   Únowrd   ÚchatÚcompletionsÚcreateÚgetÚ
isinstanceÚ_parse_stream_responseÚ_parse_completion_response)re   rn   ro   rp   rq   rr   Úformatted_messagesÚkwargsÚ	fmt_toolsÚfmt_tool_choiceÚstart_datetimeÚresponseÚ	audio_cfgÚ	audio_fmts                 rI   Ú	_call_apizOpenAIChatModel._call_api¼   si  è è € ð8 $(¤>×#8Ò#8¸Ñ#BÔ#BÐBÐBÐBÐBÐBÐBÐð  Ø*Ø”kð"
ð "
ˆð Œ?Ô%Ð1Ø.2¬oÔ.HˆFÐ*Ñ+àŒ?Ô&Ð2Ø$(¤OÔ$?ˆF�=Ñ!àŒ?Ô Ð,Ø"œoÔ3ˆF�7‰Oð ŒOÔ+ð	Jà”Ô0ð	Jð *.¬Ô)IˆFÐ%Ñ&àŒ?Ô Ð,ð œÔ.Ø!ðð ˆF�7‰Oð %+¨GÐ#4ˆF�<Ñ àŒ?Ð&Ý#'¨¬Ñ#8Ô#8ˆF�<Ñ à�Š�oÑ&Ô&Ð&à%)×%7Ò%7¸¸{Ñ%KÔ%KÑ"ˆ	�?àð 	6Ø'ˆF�7‰OØ”?Ô6ð 6Ø05�Ð,Ñ-àÐ&Ø$3ˆF�=Ñ!àŒ;ð 	?Ø(7¸Ð'>ˆFÐ#Ñ$å!œ™œˆØ<˜œÔ)Ô5Ô<ÐFÐF¸vÐFÐFÐFÐFÐFÐFÐFÐFˆà—J’J˜wÑ'Ô'ˆ	õ ˜)¥TÑ*Ô*ðˆI�MŠM˜( EÑ*Ô*Ð*àð 	ð Œ;ð 	ð ×.Ò.ØØñô ð ð
 ×.Ò.ØØØñ
ô 
ð 	
rH   r‹   rŒ   c                óÊ  K  — d}d}t          ¦   «         }t          ¦   «         }t          ¦   «         }t          ¦   «         }t          ¦   «         }	|4 ƒd{V —†}
|
2 3 d{V —†}t          g d|¬¦  «        }t          |dd¦  «        p|}||_        |j        rn|j        }t          |dd¦  «        }t          |j        |j        t          j
        ¦   «         |z
                       ¦   «         |rt          |dd¦  «        nd¬¦  «        }|j        s|j        s|r||_        |W V — ŒÅ|j        d         }|j        }t          |d	d¦  «        }t          |t           ¦  «        st          |d
d¦  «        }t          |t           ¦  «        r|r|                     ||¬¦  «         t          |dd¦  «        pd}t          |dd¦  «        }|�¹t          |t$          ¦  «        r1|                     dd¦  «        pd}|                     dd¦  «        pd}n&t          |dd¦  «        pd}t          |dd¦  «        pd}|r||z  }|rDt)          j        |¦  «        }|st-          ¦   «         |z   }d}n|}|                     ||d¬¦  «         |r|                     ||¬¦  «         t          |dd¦  «        pg D ]„}|j        }t          |dd¦  «        }|rt          |dd¦  «        nd}|rt          |dd¦  «        nd}||	vr|j        |pdf|	|<   |	|         \  }}|                     |j        p||p||pd¬¦  «         Œ…|j        s|r||_        |W V — �Œå6 	 ddd¦  «        ƒd{V —† dS # 1 ƒd{V —†swxY w Y   dS )u3  Parse the OpenAI Chat streaming response.

        Upstream sends raw PCM16 (24kHz, 16-bit mono â€” OpenAI's only
        streaming-supported audio format). We prefix the first audio
        chunk with a streaming WAV header so the frontend can start
        playback immediately; downstream accumulation is handled by
        ``ChatResponse.append_data_block``.

        Args:
            start_datetime (`datetime`):
                The start datetime of the response generation.
            response (`AsyncStream`):
                The OpenAI async stream object.

        Yields:
            `ChatResponse`:
                Incremental ``ChatResponse`` objects with ``is_last=False``.
                The base class ``__call__`` accumulates them and emits the
                final ``is_last=True`` chunk.
        FN)ÚcontentÚis_lastÚidr“   Úprompt_tokens_detailsÚcached_tokensr   ©Úinput_tokensÚoutput_tokensÚtimeÚcache_input_tokensÚreasoning_contentÚ	reasoning)Úblock_idÚthinkingr‘   Ú rw   ÚdataÚ
transcriptTz	audio/wav)r�   r    Ú
media_type)r�   rx   Ú
tool_callsÚfunctionÚnameÚ	argumentsÚunknown)r�   r¥   Úinput)r   r   r   Úgetattrr“   Úusager   Úprompt_tokensÚcompletion_tokensr   r   Útotal_secondsÚchoicesr‘   Údeltar„   rF   Úappend_thinkingr`   rƒ   Úbase64Ú	b64decoder   Úappend_data_blockÚappend_textÚindexÚappend_tool_call)re   r‹   rŒ   Úaudio_header_sentrª   Úresponse_idÚtext_idÚthinking_idÚaudio_idÚtool_call_mappingrR   ÚchunkÚ	delta_resÚuÚdetailsÚchoicer¯   Údelta_thinkingÚ
delta_textÚdelta_audioÚaudio_chunkÚtranscript_chunkÚ	pcm_bytesÚpayloadÚ	tool_callrµ   ÚfnÚ
delta_nameÚ
delta_argsÚ	stored_idÚstored_names                                  rI   r…   z&OpenAIChatModel._parse_stream_response%  s7  è è € ð6 #(ÐàˆÝ'™>œ>ˆÝ#‘~”~ˆÝ'™>œ>ˆÝ$™œˆå"-¡-¤-Ðàð v	$ð v	$ð v	$ð v	$ð v	$ð v	$ð v	$˜vØ%ð u$ð u$ð u$ð u$ð u$ð u$ð u$�eÝ(ØØ!Ø"ðñ ô �	õ & e¨T°4Ñ8Ô8ÐG¸K�Ø*�	”à”;ð Øœ�AÝ% aÐ)@À$ÑGÔG�GÝ%Ø%&¤_Ø&'Ô&9Ý&œl™nœn¨~Ñ=×LÒLÑNÔNð #ð,­7Ø#Ø+Øñ,ô ,ð ,ð ðñ ô �Eð ”}ð Ø Ô(ð (¨Eð (Ø*/˜	œØ'˜˜˜˜Øàœ qÔ)�Øœ�õ ")¨Ð0CÀTÑ!JÔ!J�Ý! .µ#Ñ6Ô6ð GÝ%,¨U°KÀÑ%FÔ%F�NÝ˜n­cÑ2Ô2ð °~ð Ø×-Ò-Ø!,Ø!/ð .ñ ô ð õ % U¨I°tÑ<Ô<ÐBÀ�
õ & e¨W°dÑ;Ô;�ØÐ*Ý! +­tÑ4Ô4ð 	Ø&1§o¢o°f¸bÑ&AÔ&AÐ&GÀR˜à'ŸOšO¨L¸"Ñ=Ô=ÐCÀð )Ð(õ '.¨k¸6À2Ñ&FÔ&FÐ&LÈ"˜å# K°¸rÑBÔBÐHÀbð )ð (ð 7Ø"Ð&6Ñ6˜
Ø"ð Ý$*Ô$4°[Ñ$AÔ$A˜	Ø0ð 0Ý&AÑ&CÔ&CÀiÑ&O˜GØ04Ð-Ð-à&/˜Gð "×3Ò3Ø%-Ø!(Ø'2ð 4ñ ô ð ð ð Ø×)Ò)Ø!(Ø'ð *ñ ô ð õ ")¨°¸dÑ!CÔ!CÐ!IÀrð ð �IØ%œO�EÝ  ¨J¸Ñ=Ô=�BØ>@Ð!J¥¨¨V°TÑ!:Ô!:Ð!:Àd�JØCEÐ!O¥¨¨[¸$Ñ!?Ô!?Ð!?È4�Jð Ð$5Ð5Ð5à%œLØ&Ð3¨)ð4Ð)¨%Ñ0ð
 .?¸uÔ-EÑ*�I˜{à×.Ò.Ø!*¤Ð!:°Ø'Ð6¨;Ø(Ð.¨Bð /ñ ô ð ð ð Ô$ð $¨ð $Ø&+�I”OØ#�O�O�O�Oùðk  &˜vðv	$ð v	$ð v	$ñ v	$ô v	$ð v	$ð v	$ð v	$ð v	$ð v	$ð v	$ð v	$ð v	$ð v	$ð v	$ð v	$ð v	$ð v	$ð v	$ð v	$ð v	$ð v	$ð v	$ð v	$øøøð v	$ð v	$ð v	$ð v	$ð v	$ð v	$s   ÁMÁL=ÁK MÍ
MÍMr|   Úaudio_formatc           
      óH  — g }|j         �rø|j         d         }t          |j        dd¦  «        }t          |t          ¦  «        st          |j        dd¦  «        }t          |t          ¦  «        r%|r#|                     t          |¬¦  «        ¦  «         |j        j        r-|                     t          |j        j        ¬¦  «        ¦  «         t          |j        dd¦  «        }|�Ðt          |t          ¦  «        r-| 
                    dd	¦  «        }| 
                    d
d	¦  «        }	n&t          |dd	¦  «        pd	}t          |d
d	¦  «        pd	}	|j        j        s%|	r#|                     t          |	¬¦  «        ¦  «         |r5|                     t          t          |d|› �¬¦  «        ¬¦  «        ¦  «         |j        j        pg D ]@}
|                     t          |
j        |
j        j        |
j        j        ¬¦  «        ¦  «         ŒAd}|j        rn|j        }t          |dd¦  «        }t)          |j        |j        t/          j        ¦   «         |z
                       ¦   «         |rt          |dd¦  «        nd¬¦  «        }|d|dœ}t          |dd¦  «        }|r||d<   t5          di |¤ŽS )a&  Parse the OpenAI Chat non-streaming response.

        Args:
            start_datetime (`datetime`):
                The start datetime of the response generation.
            response (`ChatCompletion`):
                The OpenAI chat completion object.
            audio_format (`str`, defaults to ``"wav"``):
                The audio format requested (used to set the media type on
                the output ``DataBlock``).

        Returns:
            `ChatResponse`:
                A single ``ChatResponse`` with ``is_last=True``.
        r   r›   Nrœ   )rž   )rx   rw   r    rŸ   r¡   zaudio/)r    r¢   )Úsource)r“   r¥   r¨   r”   r•   r–   T)r‘   r’   rª   r“   rG   )r®   r©   Úmessager„   rF   Úappendr   r‘   r   r`   rƒ   r   r   r£   r   r“   r¤   r¥   r¦   rª   r   r«   r¬   r   r   r­   r   )re   r‹   rŒ   rÏ   Úcontent_blocksrÁ   rœ   Ú	audio_objÚ
audio_dataÚaudio_transcriptrÉ   rª   r¿   rÀ   Úresp_kwargsr¸   s                   rI   r†   z*OpenAIChatModel._parse_completion_responseÂ  s  € ð. ð 	ð Ôñ *	ØÔ% aÔ(ˆFÝ ¤Ð0CÀTÑJÔJˆIÝ˜i­Ñ-Ô-ð GÝ# F¤N°KÀÑFÔF�	Ý˜)¥SÑ)Ô)ð I¨ið IØ×%Ò%¥m¸YÐ&GÑ&GÔ&GÑHÔHÐHàŒ~Ô%ð NØ×%Ò%¥i°V´^Ô5KÐ&LÑ&LÔ&LÑMÔMÐMõ   ¤°¸Ñ>Ô>ˆIØÐ$Ý˜i­Ñ.Ô.ð Ø!*§¢¨v°rÑ!:Ô!:�JØ'0§}¢}°\À2Ñ'FÔ'FÐ$Ð$å!(¨°F¸BÑ!?Ô!?Ð!EÀ2�Jå 	¨<¸Ñ<Ô<ÐBÀð %ð ”~Ô-ð LÐ2Bð LØ"×)Ò)­)Ð9IÐ*JÑ*JÔ*JÑKÔKÐKØð Ø"×)Ò)Ý!Ý#/Ø%/Ø+B°LÐ+BÐ+Bð$ñ $ô $ðñ ô ñô ð ð $œ^Ô6Ð<¸"ð ð �	Ø×%Ò%Ý!Ø$œ<Ø&Ô/Ô4Ø'Ô0Ô:ðñ ô ñô ð ð ð ˆØŒ>ð 	Ø”ˆAÝ˜aÐ!8¸$Ñ?Ô?ˆGÝØœ_ØÔ1Ý”l‘n”n ~Ñ5×DÒDÑFÔFð ð$¥7ØØ#Øñ$ô $ð $ð ðñ ô ˆEð &ØØð'
ð '
ˆõ
 ˜h¨¨dÑ3Ô3ˆØð 	,Ø +ˆK˜ÑåÐ*Ð*˜kÐ*Ð*Ð*rH   Ústructured_modelrˆ   c           
   ‹   óD  •K  — ddl }	  t          ¦   «         j        d||||dœ|¤Žƒ d{V —†S # |j        $ rh}dt	          |¦  «        vr‚ t          j        d|› d�d¬¦  «          t          ¦   «         j        d|||t          d	¬
¦  «        dœ|¤Žƒ d{V —†cY d}~S d}~ww xY w)ae  OpenAI-compatible override for structured output.

        Some third-party providers that expose an OpenAI-compatible API (e.g.
        DeepSeek via DashScope) reject forced ``tool_choice`` when thinking
        mode is active.  When such a ``BadRequestError`` is encountered, this
        method automatically retries with ``tool_choice="auto"``.
        r   N)rn   ro   rÙ   rq   rq   z)Forced tool_choice rejected by provider (z$), retrying with tool_choice='auto'.r   )Ú
stacklevelÚauto)ÚmoderG   )ra   r^   Ú _call_api_with_structured_outputÚBadRequestErrorrF   ÚwarningsÚwarnr    )	re   rn   ro   rÙ   rq   rˆ   ra   Úerf   s	           €rI   rÞ   z0OpenAIChatModel._call_api_with_structured_output#  sZ  øè è € ð 	ˆˆˆð	ØA�™œÔAð Ø%Ø!Ø!1Ø'ð	ð ð
 ðð ð ð ð ð ð ð ð øð Ô%ð 	ð 	ð 	Ø¥C¨¡F¤FÐ*Ð*ØåŒMð4¸Að 4ð 4ð 4àðñ ô ð ð
 B�™œÔAð Ø%Ø!Ø!1Ý&¨FÐ3Ñ3Ô3ð	ð ð
 ðð ð ð ð ð ð ð ð ð ð ð ð ð øøøøð	øøøs   ‰#- ­
B·ABÂBÂBc                 óþ   ‡— |rA|r?|                       ||¦  «         |j        r"t          |j        ¦  «        Šˆfd„|D ¦   «         }|r|                      |¦  «        }|s|dfS |j        }|t
          vr	|dd|idœfS ||fS )aÖ  Validate, filter, and format tools and tool_choice for the OpenAI
        Chat Completions API.

        When ``tool_choice.tools`` is specified the schemas list is filtered
        to only those tools. When ``tool_choice.mode`` is a specific tool name
        (str) the model is forced to call exactly that tool without needing to
        filter the list, preserving prompt-cache efficiency.

        Tool parameter schemas are flattened (``$ref`` / ``$defs`` resolved
        inline) so that providers which do not support JSON Schema references
        (e.g. GLM-5.x via OpenCode Go) receive a self-contained schema.

        Args:
            tools (`list[dict] | None`, optional):
                The raw tool schemas.
            tool_choice (`ToolChoice | None`, optional):
                The tool choice configuration.

        Returns:
            `tuple[list[dict] | None, str | dict | None]`:
                A tuple of (formatted_tools, formatted_tool_choice).
        c                 ó4   •— g | ]}|d          d         ‰v ¯|‘ŒS )r¤   r¥   rG   )Ú.0ÚtÚalloweds     €rI   ú
<listcomp>z1OpenAIChatModel._format_tools.<locals>.<listcomp>l  s,   ø€ ÐNÐNÐN˜q¨Q¨z¬]¸6Ô-BÀgÐ-MÐ-M˜Ð-MÐ-MÐ-MrH   Nr¤   r¥   )rL   r¤   )Ú_validate_tool_choicerp   ÚsetÚ_flatten_tool_schemasrÝ   r   )re   rp   rq   rÝ   rç   s       @rI   r~   zOpenAIChatModel._format_toolsM  sÃ   ø€ ð6 ð 	O˜5ð 	OØ×&Ò& {°EÑ:Ô:Ð:ØÔ ð OÝ˜kÔ/Ñ0Ô0�ØNÐNÐNÐN EÐNÑNÔN�àð 	6Ø×.Ò.¨uÑ5Ô5ˆEàð 	Ø˜$�;ÐàÔˆàÕ1Ð1Ð1Ø :¸FÀD¸>ÐJÐJÐJÐJà�dˆ{ÐrH   c                 ó€  — g }| D ]¸}|                      d¦  «        }t          |t          ¦  «        s|                     |¦  «         ŒB|                      d¦  «        }t          |t          ¦  «        s|                     |¦  «         Œ‚t	          |¦  «        }||uri |¥di |¥d|i¥i¥}|                     |¦  «         Œ¹|S )aS  Inline ``$ref`` / ``$defs`` in each tool's parameter schema.

        Args:
            tools (`list[dict]`):
                The list of tool dicts, each with a ``"function"`` key
                containing the tool name, description and ``"parameters"``
                JSON schema.

        Returns:
            `list[dict]`:
                A new list where each tool's ``parameters`` schema has all
                local ``$ref`` / ``$defs`` resolved inline.  Tools whose
                schema contained no references are returned unchanged (same
                object identity).
        r¤   rQ   )rƒ   r„   r`   rÓ   r   )rp   ÚresultÚtoolÚfuncÚparamsÚflats         rI   rë   z%OpenAIChatModel._flatten_tool_schemas{  sÞ   € ð& ˆØð 	 ð 	 ˆDØ—8’8˜JÑ'Ô'ˆDÝ˜d¥DÑ)Ô)ð Ø—’˜dÑ#Ô#Ð#ØØ—X’X˜lÑ+Ô+ˆFÝ˜f¥dÑ+Ô+ð Ø—’˜dÑ#Ô#Ð#ØÝ'¨Ñ/Ô/ˆDØ˜6Ð!Ð!ØI˜$ÐI 
Ð,H¨tÐ,H°\À4Ð,HÐ,HÐIÐI�Ø�MŠM˜$ÑÔÐÐØˆrH   )NTr   rM   rN   NNN)NN)r|   )N)(r>   r?   r@   rA   r   rJ   rL   r   rC   r   rF   rD   rB   rE   r   r`   r   r_   ÚclassmethodÚtupler
   Ú	Exceptionrm   Úlistr   r    r   r   r�   r   r"   r…   r!   r†   r   rÞ   r~   Ústaticmethodrë   Ú__classcell__)rf   s   @rI   r$   r$   $   s’  ø€ € € € € € Ø,Ð,ðD
ð D
ð D
ð D
ð D
�Yñ D
ô D
ð D
ðL $1€Dˆ'�-Ô
 Ð0Ð0Ñ0Ø%ð ;?ØØØ Ø"Ø*.Ø/3Ø,0ð?
ð ?
à$ð?
ð ð?
ð 8ð	?
ð
 ð?
ð ð?
ð ð?
ð ð?
ð ! 4Ñ'ð?
ð ˜C ˜H”~¨Ñ,ð?
ð ˜˜c˜”N TÑ)ð?
ð 
ð?
ð ?
ð ?
ð ?
ð ?
ð ?
ðB ð
¨%°°Y´ÀÐ0DÔ*Eð 
ð 
ð 
ñ „[ð
ð $(Ø)-ðg
ð g
àðg
ð �s”)ðg
ð �DŒz˜DÑ ð	g
ð
   $Ñ&ðg
ð ðg
ð 
˜ |°TÐ'9Ô:Ñ	:ðg
ð g
ð g
ð g
ðR[$à ð[$ð ð[$ð 
˜ dÐ*Ô	+ð	[$ð [$ð [$ð [$ðB "ð	_+ð _+à ð_+ð !ð_+ð ð	_+ð
 
ð_+ð _+ð _+ð _+ðL *.ð(ð (àð(ð �s”)ð(ð ˜yœ/¨DÑ0ð	(ð
   $Ñ&ð(ð ð(ð 
ð(ð (ð (ð (ð (ð (ðT,à�DŒz˜DÑ ð,ð   $Ñ&ð,ð 
ˆt�DŒz˜DÑ  #¨¡*¨tÑ"3Ð3Ô	4ð	,ð ,ð ,ð ,ð\ ð Ø�DŒzð à	ˆdŒð ð  ð  ñ „\ð ð  ð  ð  ð  rH   r$   )0rA   rà   r±   Úcollectionsr   r   Útypingr   r   r   r   r	   r
   Úpydanticr   r   Ú_utils._audior   Ú_utils._commonr   r   Ú_baser   r   Ú_model_responser   r   Ú_model_usager   rO   r   rV   r   r   rÒ   r   r   r   r   r   r   rî   r    Úopenai.types.chatr!   ra   r"   r$   rG   rH   rI   ú<module>r     sú  ðà 7Ð 7Ø €€€Ø €€€Ø #Ð #Ð #Ð #Ð #Ð #Ø Ð Ð Ð Ð Ð Ø JÐ JÐ JÐ JÐ JÐ JÐ JÐ JÐ JÐ JÐ JÐ JÐ JÐ JÐ JÐ Jà %Ð %Ð %Ð %Ð %Ð %Ð %Ð %à 8Ð 8Ð 8Ð 8Ð 8Ð 8Ø @Ð @Ð @Ð @Ð @Ð @Ð @Ð @Ø =Ð =Ð =Ð =Ð =Ð =Ð =Ð =Ø >Ð >Ð >Ð >Ð >Ð >Ð >Ð >Ø $Ð $Ð $Ð $Ð $Ð $Ø *Ð *Ð *Ð *Ð *Ð *Ø ;Ð ;Ð ;Ð ;Ð ;Ð ;Ð ;Ð ;ðð ð ð ð ð ð ð ð ð ð ð ð ð ð ð ð Ð Ð Ð Ð Ð àð Ø0Ð0Ð0Ð0Ð0Ð0Ø"Ð"Ð"Ð"Ð"Ð"Ð"à€NØ€Kðx	ð x	ð x	ð x	ð x	�mñ x	ô x	ð x	ð x	ð x	rH   