Ë
    uPêjÝ=  ã                   óð   — d Z ddlZddlmZ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 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 er	ddlmZ  e Z!neZ!de"de#fd„Z$ G d„ de«      Z%y)aJ  
GitHub Copilot Responses API Configuration.

This module provides the configuration for GitHub Copilot's Responses API,
which is required for models like gpt-5.3-codex that only support the /responses endpoint.

Implementation based on analysis of the copilot-api project by caozhiyuan:
https://github.com/caozhiyuan/copilot-api
é    N)ÚTYPE_CHECKINGÚAnyÚFinal)Úverbose_logger)ÚDEFAULT_MAX_RECURSE_DEPTH)ÚAuthenticationError)ÚOpenAIResponsesAPIConfig)ÚResponseInputParamÚ!ResponsesAPIOptionalRequestParams)ÚGenericLiteLLMParams)ÚLlmProviders)Ú_cached_get_model_info_helperé   )ÚAuthenticator)ÚDEFAULT_GITHUB_COPILOT_API_BASEÚGetAPIKeyErrorÚget_copilot_default_headers)ÚLoggingÚmodelÚreturnc                 ó¨  — 	 t        | d¬«      }|j	                  d«      }|dk(  ry|d	k(  ry|j	                  d
«      }t        |t        «      rt        j                  j	                  |«      nd}t        |t        «      r|j	                  d«      nd}t        |t        «      xr d|v S # t        $ r!}t        j                  d| |«       Y d}~yd}~ww xY w)aþ  
    Gate native /v1/responses dispatch per github_copilot model.

    Resolution (first match wins): mode "responses" -> True; mode "chat" ->
    False (opt-out wins for dual-endpoint models); "/v1/responses" in
    supported_endpoints -> True; else False. Unknown model -> False (the bridge
    always works since every Copilot model supports /chat/completions).

    Reads merged model info (per-deployment model_info applied via the router's
    register_model, which also clears the cache used here).
    Úgithub_copilot)r   Úcustom_llm_providerzGgithub_copilot_supports_responses_api: get_model_info failed for %s: %sNFÚmodeÚ	responsesTÚchatÚkeyÚsupported_endpointsz/v1/responses)r   Ú	Exceptionr   ÚdebugÚgetÚ
isinstanceÚstrÚlitellmÚ
model_costÚdictÚlist)r   ÚinfoÚer   r   Úraw_infoÚ	endpointss          úy/home/oem/CyberBrain26-unified/.venv/lib/python3.12/site-packages/litellm/llms/github_copilot/responses/transformation.pyÚ%github_copilot_supports_responses_apir-   *   sÊ   € ðÜ3¸%ÐUeÔfˆð —(‘(˜6Ó"€DØˆ{ÒØØˆv‚~Øð —‘˜%“€CÜ5?ÀÄSÔ5I”g×(Ñ(×,Ñ,¨SÔ1Èt€HÜ>HÈÔSWÔ>X�x—|‘|Ð$9Ô:Ð^b€IÜ�i¤Ó&ÒG¨?¸iÐ+GÐGøô' ò Ü×ÑØUØØô	
ô
 ûðús   ‚B' Â'	CÂ0CÃCc            	       óf  ‡ — e Zd ZdZd ˆ fd„Zedefd„«       Zdede	fˆ fd„Z
deded	edefd
„Zdedededefˆ fd„Zdedefd„Zdedededz  defd„Zdedz  dedefd„Zdeeef   deeef   fd„Zdedz  deez  dz  fd„Zdeez  defd„Zdeez  defd„Zdefdedededefd„Zdefd„Zˆ xZS )!ÚGithubCopilotResponsesAPIConfiga>  
    Configuration for GitHub Copilot's Responses API.

    Inherits from OpenAIResponsesAPIConfig since GitHub Copilot's Responses API
    is compatible with OpenAI's Responses API specification.

    Key differences from OpenAI:
    - Uses OAuth Device Flow authentication (handled by Authenticator)
    - Uses api.githubcopilot.com as the API base
    - Requires specific headers for VSCode/Copilot integration
    - Supports vision requests with special header
    - Requires X-Initiator header based on input analysis

    Reference: https://api.githubcopilot.com/
    r   Nc                 óN   •— t         ‰| �  «        t        «       | _        i | _        y )N)ÚsuperÚ__init__r   ÚauthenticatorÚ _stream_item_ids_by_output_index)ÚselfÚ	__class__s    €r,   r2   z(GithubCopilotResponsesAPIConfig.__init___   s    ø€ Ü‰ÑÔÜ*›_ˆÔØ@BˆÕ-ó    c                 ó"   — t         j                  S )z.Return the GitHub Copilot provider identifier.)r   ÚGITHUB_COPILOT©r5   s    r,   r   z3GithubCopilotResponsesAPIConfig.custom_llm_providerd   s   € ô ×*Ñ*Ð*r7   r   c                 ó"   •— t         ‰| �  |«      S )z›
        Get supported parameters for GitHub Copilot Responses API.

        GitHub Copilot supports all standard OpenAI Responses API parameters.
        )r1   Úget_supported_openai_params)r5   r   r6   s     €r,   r<   z;GithubCopilotResponsesAPIConfig.get_supported_openai_paramsi   s   ø€ ô ‰wÑ2°5Ó9Ð9r7   Úresponse_api_optional_paramsÚdrop_paramsc                 ó   — t        |«      S )z¬
        Map parameters for GitHub Copilot Responses API.

        GitHub Copilot uses the same parameter format as OpenAI,
        so no transformation is needed.
        )r&   )r5   r=   r   r>   s       r,   Úmap_openai_paramsz1GithubCopilotResponsesAPIConfig.map_openai_paramsq   s   € ô Ð0Ó1Ð1r7   Úparsed_chunkÚlogging_objc                 óJ   •— | j                  |«      }t        ‰| �	  |||¬«      S )N)r   rA   rB   )Ú_normalize_stream_item_idr1   Útransform_streaming_response)r5   r   rA   rB   r6   s       €r,   rE   z<GithubCopilotResponsesAPIConfig.transform_streaming_response   s5   ø€ ð ×5Ñ5°lÓCˆÜ‰wÑ3ØØ%Ø#ð 4ó 
ð 	
r7   c                 óR  — |j                  d«      }t        |t        «      s|S |j                  d«      dk(  rT|j                  d«      }t        |t        «      r1t        |j                  d«      t        «      r|d   | j
                  |<   |S | j
                  j                  |«      }|€|S t        |j                  d«      t        «      rt        |«      }||d<   |S |j                  d«      dk(  r7|j                  d«      }t        |t        «      rt        |«      }i |¥d|i¥|d<   |S )aÁ  Rewrite streamed item ids to one stable id per output_index.

        GitHub Copilot tags each event of a single output item with a different
        item id, so clients that key streaming state by item id (e.g. the Vercel
        AI SDK) crash with "reasoning part <id> not found" / "text part <id> not
        found". Every sub-event carries a top-level ``item_id`` (whatever the
        item type), so its presence is the rewrite signal; output_item.added /
        .done instead nest the id under ``item``. The anchor is keyed by
        output_index and taken from output_item.added, which the protocol always
        emits first, so it is written before any sub-event reads it. Copilot
        accepts that id paired with the final encrypted_content next turn, so
        multi-turn replay is unaffected.

        State is keyed by output_index on this config, which
        ProviderConfigManager builds fresh per request, so it is stream-scoped.
        Úoutput_indexÚtypezresponse.output_item.addedÚitemÚidÚitem_idzresponse.output_item.done)r!   r"   Úintr&   r#   r4   )r5   rA   rG   rI   Ú	stable_ids        r,   rD   z9GithubCopilotResponsesAPIConfig._normalize_stream_item_idŒ   s&  € ð" +×.Ñ.¨~Ó>ˆÜ˜,¬Ô,ØÐà×Ñ˜FÓ#Ð'CÒCØ×#Ñ# FÓ+ˆDÜ˜$¤Ô%¬*°T·X±X¸d³^ÄSÔ*IØFJÈ4Áj�×5Ñ5°lÑCØÐà×@Ñ@×DÑDÀ\ÓRˆ	ØÐØÐä�l×&Ñ& yÓ1´3Ô7Ü Ó-ˆLØ&/ˆL˜Ñ#ð Ðð ×Ñ˜fÓ%Ð)DÒDØ×#Ñ# FÓ+ˆDÜ˜$¤Ô%Ü# LÓ1�Ø'@¨$Ð'@°°iÑ'@�˜VÑ$àÐr7   ÚheadersÚlitellm_paramsc                 óÎ  — 	 | j                   j                  «       }|st        |dd¬«      ‚t        |«      }i |¥|¥}| j	                  |«      }|�W| j                  |«      }||d<   t        j                  d|«       | j                  |«      rd|d<   t        j                  d	«       t        j                  d
|«       |S # t        $ r}	t        |dt        |	«      ¬«      ‚d}	~	ww xY w)a   
        Validate environment and set up headers for GitHub Copilot API.

        Uses the Authenticator to obtain GitHub Copilot API key via OAuth Device Flow,
        then configures all required headers for the Responses API.

        Headers include:
        - Authorization with API key
        - Standard GitHub Copilot headers (editor-version, user-agent, etc.)
        - X-Initiator based on input analysis
        - copilot-vision-request if vision content detected
        - User-provided extra_headers (merged with priority)
        r   zNGitHub Copilot API key is required. Please authenticate via OAuth Device Flow.)r   Úllm_providerÚmessageNzX-Initiatorz0GitHub Copilot Responses API: Set X-Initiator=%sÚtruezcopilot-vision-requestz4GitHub Copilot Responses API: Enabled vision requestzJGitHub Copilot Responses API: Successfully configured headers for model %s)r3   Úget_api_keyr   r   Ú_get_input_from_paramsÚ_get_initiatorr   r    Ú_has_vision_inputr   r#   )
r5   rN   r   rO   Úapi_keyÚdefault_headersÚmerged_headersÚinput_paramÚ	initiatorr)   s
             r,   Úvalidate_environmentz4GithubCopilotResponsesAPIConfig.validate_environment¶   s  € ð&(	à!×/Ñ/×;Ñ;Ó=ˆGáÜ)ØØ!1Ølôð ô &AÀÓ%IˆOð %C Ð$B¸'Ð$BˆNð "&×!<Ñ!<¸^Ó!LˆKð Ð&Ø#'×#6Ñ#6°{Ó#C�	Ø09�˜}Ñ-Ü×$Ñ$Ð%WÐYbÔcð ×)Ñ)¨+Ô6Ø?E�NÐ#;Ñ<Ü"×(Ñ(Ð)_Ô`ä× Ñ Ð!mÐotÔuà!Ð!øäò 	Ü%ØØ-Ü˜A›ôð ûð	ús   ‚B<B? Â?	C$ÃCÃC$Úapi_basec                 ó¨   — |xs9 | j                   j                  «       xs t        j                  d«      xs t        }|j                  d«      }|› d�S )zQ
        Get the complete URL for GitHub Copilot Responses API endpoint.
        ÚGITHUB_COPILOT_API_BASEú/z
/responses)r3   Úget_api_baseÚosÚgetenvr   Úrstrip)r5   r^   rO   Úeffective_api_bases       r,   Úget_complete_urlz0GithubCopilotResponsesAPIConfig.get_complete_urló   sb   € ð ò /Ø×!Ñ!×.Ñ.Ó0ò/ä�y‰yÐ2Ó3ò/ô /ð	 	ð 0×6Ñ6°sÓ;Ðð %Ð% ZÐ0Ð0r7   rI   c                 óò   — |j                  d«      dk(  rb|j                  d«      }i }|j                  «       D ]"  \  }}|dk(  r|�|||<   Œ|dk(  r|€Œ|€Œ|||<   Œ$ t        j                  d|du«       |S |S )a  
        Handle reasoning items for GitHub Copilot, preserving encrypted_content.

        GitHub Copilot uses encrypted_content in reasoning items to maintain
        conversation state across turns. The parent class strips this field
        when converting to OpenAI's ResponseReasoningItem model, which causes
        "encrypted content could not be verified" errors on multi-turn requests.

        This override preserves encrypted_content while still filtering out
        status=None which OpenAI's API rejects.
        rH   Ú	reasoningÚencrypted_contentNÚstatuszHGitHub Copilot reasoning item processed, encrypted_content preserved: %s)r!   Úitemsr   r    )r5   rI   rj   Úfiltered_itemÚkÚvs         r,   Ú_handle_reasoning_itemz6GithubCopilotResponsesAPIConfig._handle_reasoning_item	  s¦   € ð �8‰8�FÓ˜{Ò*à'+§x¡xÐ0CÓ'DÐð 46ˆMØŸ
™
›ò )‘��1àÐ+Ò+Ø(Ð4Ø+,˜ aÑ(Øà˜’= Q YØà‘=Ø'(�M !Ò$ð)ô × Ñ ØZØ!¨Ð-ôð !Ð Øˆr7   c                 ó:   — |€yt        |d«      r|j                  S y)zÅ
        Extract input parameter from litellm_params.

        The input parameter contains the conversation history and is needed
        for vision detection and initiator determination.
        NÚinput)Úhasattrrr   )r5   rO   s     r,   rU   z6GithubCopilotResponsesAPIConfig._get_input_from_params2  s*   € ð Ð!Øô �> 7Ô+Ø!×'Ñ'Ð'ð r7   r[   c                 ó  — t        |t        «      ryt        |t        «      rf|D ]a  }t        |t        «      sŒd|vs|j	                  d«      s y|j	                  d«      }t        |t        «      sŒM|j                  «       dk(  sŒa y y)a†  
        Determine X-Initiator header value based on input analysis.

        Based on copilot-api's hasAgentInitiator logic:
        - Returns "agent" if input contains assistant role or items without role
        - Returns "user" otherwise

        Args:
            input_param: The input parameter (string or list of input items)

        Returns:
            "agent" or "user"
        ÚuserÚroleÚagentÚ	assistant)r"   r#   r'   r&   r!   Úlower)r5   r[   rI   rv   s       r,   rV   z.GithubCopilotResponsesAPIConfig._get_initiatorD  s€   € ô �k¤3Ô'Øô �k¤4Ô(Ø#ò #�Ü! $¬Ô-Øð  Ñ%¨T¯X©X°fÔ-=Ù"ð —x‘x Ó'�Ü˜d¤CÕ(¨T¯Z©Z«\¸[Ó-HÙ"ð#ð r7   c                 ó$   — | j                  |«      S )aw  
        Check if input contains vision content (images).

        Based on copilot-api's hasVisionInput and containsVisionContent logic.
        Recursively searches for input_image type in the input structure.

        Args:
            input_param: The input parameter to analyze

        Returns:
            True if input contains image content, False otherwise
        ©Ú_contains_vision_content)r5   r[   s     r,   rW   z1GithubCopilotResponsesAPIConfig._has_vision_inputh  s   € ð ×,Ñ,¨[Ó9Ð9r7   r   ÚvalueÚdepthÚ	max_depthc                 ó€  ‡ ‡‡— ‰‰kD  rt        j                  d‰«       y|€yt        |t        «      rt	        ˆˆˆ fd„|D «       «      S t        |t
        «      sy|j                  d«      }t        |t        «      r|j                  «       dk(  ryd|v r,t        |d   t        «      rt	        ˆˆˆ fd„|d   D «       «      S y)	zŠ
        Recursively check if a value contains vision content.

        Looks for items with type="input_image" in the structure.
        zQ[GitHub Copilot] Max recursion depth %s reached while checking for vision contentFc              3   óL   •K  — | ]  }‰j                  |‰d z   ‰¬«      –— Œ y­w©é   )r~   r   Nr{   ©Ú.0rI   r~   r   r5   s     €€€r,   ú	<genexpr>zKGithubCopilotResponsesAPIConfig._contains_vision_content.<locals>.<genexpr>ˆ  s)   øè ø€ ÒsÐei�t×4Ñ4°TÀÈÁÐV_Ð4×`Ñsùó   ƒ!$rH   Úinput_imageTÚcontentc              3   óL   •K  — | ]  }‰j                  |‰d z   ‰¬«      –— Œ y­wr‚   r{   r„   s     €€€r,   r†   zKGithubCopilotResponsesAPIConfig._contains_vision_content.<locals>.<genexpr>•  s,   øè ø€ ò Ø^b�×-Ñ-¨d¸%À!¹)ÈyÐ-×Yñùr‡   )	r   Úwarningr"   r'   Úanyr&   r!   r#   ry   )r5   r}   r~   r   Ú	item_types   ` `` r,   r|   z8GithubCopilotResponsesAPIConfig._contains_vision_contentw  sÃ   ú€ ð �9ÒÜ×"Ñ"ØcÐenôð àˆ=Øô �eœTÔ"ÜÕsÐmrÔsÓsÐsô ˜%¤Ô&Øð !Ÿ9™9 VÓ,ˆ	Ü�i¤Ô%¨)¯/©/Ó*;¸}Ò*LØð ˜Ñ¤*¨U°9Ñ-=¼tÔ"DÜõ ØfkÐluÑfvôó ð ð r7   c                  ó   — y)zBGitHub Copilot does not support native WebSocket for Responses APIF© r:   s    r,   Úsupports_native_websocketz9GithubCopilotResponsesAPIConfig.supports_native_websocket›  s   € àr7   )r   N) Ú__name__Ú
__module__Ú__qualname__Ú__doc__r2   Úpropertyr   r   r#   r'   r<   r   Úboolr&   r@   ÚLiteLLMLoggingObjr   rE   rD   r   r]   rg   rp   r
   rU   rV   rW   r   rL   r|   r�   Ú__classcell__)r6   s   @r,   r/   r/   N   s²  ø„ ñõ Cð
 ð+ \ò +ó ð+ð:°ð :¸õ :ð2à&Gð2ð ð2ð ð	2ð
 
ó2ð
àð
ð ð
ð 'ð	
ð
 
õ
ð(°dð (¸tó (ðT;àð;ð ð;ð -¨tÑ3ð	;ð
 
ó;ðz1à˜‘*ð1ð ð1ð 
ó	1ð,%¨4°°S°©>ð %¸dÀ3ÈÀ8¹nó %ðRÐ5IÈDÑ5Pð ÐUXÐ[mÑUmÐptÑUtó ð$"¨#Ð0BÑ*Bð "Àsó "ðH:¨SÐ3EÑ-Eð :È$ó :ð ABÐTmñ "¨cð "¸#ð "Ècð "Ðrvó "ðH¨4÷ r7   r/   )&r”   rc   Útypingr   r   r   r$   Úlitellm._loggingr   Úlitellm.constantsr   Úlitellm.exceptionsr   Ú,litellm.llms.openai.responses.transformationr	   Úlitellm.types.llms.openair
   r   Úlitellm.types.routerr   Úlitellm.types.utilsr   Úlitellm.utilsr   r3   r   Úcommon_utilsr   r   r   Ú*litellm.litellm_core_utils.litellm_loggingr   Ú_LiteLLMLoggingObjr—   r#   r–   r-   r/   r�   r7   r,   ú<module>r¥      s{   ðñó 
ß ,Ñ ,ã Ý +Ý 7Ý 2Ý Q÷õ 6Ý ,Ý 7å )÷ñ ñ ÝXà*ÑàÐð!H°ð !H¸ó !HôHOÐ&>õ Or7   