Ë
    tPêj(!  ã                   ó�  — U d Z ddlZddlZddlZddlmZ ddl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 d
Zeed<   dZeed<   dZeed<   dZeed<   dededz  fd„Zdedefd„Z ed¬«       G d„ d«      «       Zdeeef   dz  dedz  fd„Z G d„ de«      Z e«       Z eed<   deeef   dz  deeef   dz  fd „Z!y)!a‘  
OAuth M2M (client_credentials) support for A2A agents that target Databricks
App endpoints.

Databricks Apps reject static bearer tokens; they require a short-lived OAuth
access token minted from the workspace OIDC token endpoint. When an agent is
registered with a ``databricks_oauth`` block in its ``litellm_params``, LiteLLM
fetches that token via the client_credentials grant, caches it until shortly
before expiry, and attaches it as the outbound ``Authorization`` header on every
call the proxy makes to the agent.

Config example::

    agents:
      - agent_name: my-databricks-app
        agent_card_params:
          url: https://my-app-1234.aws.databricksapps.com
        litellm_params:
          databricks_oauth:
            client_id: os.environ/DATABRICKS_CLIENT_ID
            client_secret: os.environ/DATABRICKS_CLIENT_SECRET
            workspace_url: https://dbc-abc123.cloud.databricks.com
é    N)Ú	dataclass)ÚAnyÚFinal)Úverbose_logger)ÚInMemoryCache)Úget_async_httpx_client)Úget_secret_str)ÚhttpxSpecialProviderÚdatabricks_oauthÚDATABRICKS_OAUTH_PARAMzall-apisÚ_DEFAULT_SCOPEé<   Ú_TOKEN_EXPIRY_BUFFER_SECONDSi  Ú_DEFAULT_TTL_SECONDSÚvalueÚreturnc                 ó`   — t        | t        «      sy| j                  d«      rt        | «      S | S )z=Resolve a config value, expanding ``os.environ/`` references.Nzos.environ/)Ú
isinstanceÚstrÚ
startswithr	   )r   s    ús/home/oem/CyberBrain26-unified/.venv/lib/python3.12/site-packages/litellm/proxy/agent_endpoints/databricks_oauth.pyÚ_resolve_secretr   .   s-   € ä�eœSÔ!ØØ×Ñ˜Ô&Ü˜eÓ$Ð$Ø€Ló    Úworkspace_urlc                 ól   — | j                  «       j                  d«      }|j                  d«      }|› d�S )z=Build the workspace OIDC token endpoint from a workspace URL.ú/z/serving-endpointsz/oidc/v1/token)ÚstripÚrstripÚremovesuffix)r   Úbases     r   Ú_token_url_from_workspacer!   7   s9   € à×ÑÓ ×'Ñ'¨Ó,€DØ×ÑÐ1Ó2€DØˆV�>Ð"Ð"r   T)Úfrozenc                   óL   — e Zd ZU eed<   eed<   eed<   eed<   edefd„«       Zy)ÚDatabricksAppOAuthConfigÚ	client_idÚclient_secretÚ	token_urlÚscoper   c                 óÔ   — t        j                  | j                  j                  «       «      j	                  «       d d }| j
                  › d| j                  › d| j                  › d|› �S )Né   ú|)ÚhashlibÚsha256r&   ÚencodeÚ	hexdigestr'   r%   r(   )ÚselfÚsecret_digests     r   Ú	cache_keyz"DatabricksAppOAuthConfig.cache_keyE   s^   € ô  'Ÿ~™~¨d×.@Ñ.@×.GÑ.GÓ.IÓJ×TÑTÓVÐWZÐXZÐ[ˆØ—.‘.Ð!  4§>¡>Ð"2°!°D·J±J°<¸qÀÀÐPÐPr   N)Ú__name__Ú
__module__Ú__qualname__r   Ú__annotations__Úpropertyr2   © r   r   r$   r$   >   s3   … àƒNØÓØƒNØƒJàðQ˜3ò Qó ñQr   r$   Úlitellm_paramsc                 ó@  — | sy| j                  t        «      }|€yt        |t        «      s(t	        dt        › dt        |«      j                  › �«      ‚t        |j                  d«      «      }t        |j                  d«      «      }t        |j                  d«      «      }d|fd|fd|ffD ��cg c]	  \  }}|s|‘Œ }}}|rt	        ddj                  |«      › �«      ‚t        |j                  d	«      «      xs t        }t        ||t        |«      |¬
«      S c c}}w )a8  Build a Databricks App OAuth config from an agent's ``litellm_params``.

    Returns ``None`` when the agent has no ``databricks_oauth`` block. Raises
    ``ValueError`` when the block is present but incomplete, so misconfiguration
    surfaces loudly instead of silently sending an unauthenticated request.
    Nú'z+' must be a mapping of OAuth settings, got r%   r&   r   z:Databricks App OAuth config is missing required field(s): z, r(   )r%   r&   r'   r(   )Úgetr   r   ÚdictÚ
ValueErrorÚtyper3   r   Újoinr   r$   r!   )	r9   Úrawr%   r&   r   Únamer   Úmissingr(   s	            r   Úparse_databricks_oauth_configrD   M   s2  € ñ Øà×#Ñ#Ô$:Ó;€CØ
€{ØÜ�cœ4Ô Ü˜1Ô3Ð4Ð4_Ô`dÐehÓ`i×`rÑ`rÐ_sÐtÓuÐuä& s§w¡w¨{Ó';Ó<€IÜ*¨3¯7©7°?Ó+CÓD€MÜ*¨3¯7©7°?Ó+CÓD€Mð
 ˜)Ð$Ø˜mÐ,Ø˜mÐ,ð
÷áˆD�%ñ
 ò 	ð€Gñ ñ ÜÐUÐVZ×V_ÑV_Ð`gÓVhÐUiÐjÓkÐkä" 3§7¡7¨7Ó#3Ó4ÒF¼€Eä#ØØ#Ü+¨MÓ:Øô	ð ùós   Â0Dc                   ó’   ‡ — e Zd ZdZdˆ fd„Zdedej                  fd„Zdeddfˆ fd„Z	dˆ fd	„Z
d
edefd„Zd
edeeef   fd„Zˆ xZS )ÚDatabricksAppOAuthTokenCachea  In-memory cache for Databricks App OAuth client_credentials tokens.

    Keyed by token endpoint + client_id + scope so distinct agents and service
    principals never share a token. A per-key ``asyncio.Lock`` collapses
    concurrent fetches into a single token request.
    r   Nc                 ó<   •— t         ‰| �  t        ¬«       i | _        y )N)Údefault_ttl)ÚsuperÚ__init__r   Ú_locks©r0   Ú	__class__s    €r   rJ   z%DatabricksAppOAuthTokenCache.__init__�   s   ø€ Ü‰ÑÔ%9ÐÔ:Ø/1ˆ�r   r2   c                 ó^   — | j                   j                  |t        j                  «       «      S ©N)rK   Ú
setdefaultÚasyncioÚLock)r0   r2   s     r   Ú	_get_lockz&DatabricksAppOAuthTokenCache._get_lock…   s   € Ø�{‰{×%Ñ% i´·±³Ó@Ð@r   Úkeyc                 ó\   •— t         ‰| �  |«       | j                  j                  |d «       y rO   )rI   Ú_remove_keyrK   Úpop)r0   rT   rM   s     €r   rV   z(DatabricksAppOAuthTokenCache._remove_keyˆ   s$   ø€ ô 	‰Ñ˜CÔ Ø�‰�‰˜˜TÕ"r   c                 óV   •— t         ‰| �  «        | j                  j                  «        y rO   )rI   Úflush_cacherK   ÚclearrL   s    €r   rY   z(DatabricksAppOAuthTokenCache.flush_cacheŽ   s   ø€ Ü‰ÑÔØ�‰×ÑÕr   Úconfigc              ƒ   óÐ  K  — |j                   }| j                  |«      }|�|S | j                  |«      4 ƒd {  –—†  | j                  |«      }|�|cd d d «      ƒd {  –—†  S | j                  |«      ƒ d {  –—† \  }}|dkD  r| j	                  |||¬«       n| j
                  j                  |d «       |cd d d «      ƒd {  –—†  S 7 Œ�7 Œl7 ŒT7 Œ# 1 ƒd {  –—†7  sw Y   y xY w­w)Nr   )Úttl)r2   Ú	get_cacherS   Ú_fetch_tokenÚ	set_cacherK   rW   )r0   r[   r2   ÚcachedÚtokenr]   s         r   Úasync_get_tokenz,DatabricksAppOAuthTokenCache.async_get_token’   sà   è ø€ Ø!×+Ñ+ˆ	à—‘ 	Ó*ˆØÐØˆMà—>‘> )Ó,÷ 	ñ 	Ø—^‘^ IÓ.ˆFØÐ!Ø÷	÷ 	ñ 	ð
  $×0Ñ0°Ó8×8‰JˆE�3ð
 �QŠwØ—‘˜y¨%°S�Õ9à—‘—‘ 	¨4Ô0Ø÷	÷ 	ò 	øð 	øð
 9øð	ø÷ 	÷ 	ñ 	üst   ‚7C&¹C	ºC&½CÁC&ÁCÁC&Á$CÁ8CÁ9>CÂ7C&ÃCÃC&ÃC&ÃCÃC&ÃC#ÃCÃC#ÃC&c              ƒ   ó¾  K  — t        t        j                  ¬«      }t        j                  d|j
                  «       t        j                  |j                  › d|j                  › �j                  «       «      j                  «       }	 |j                  |j
                  d|j                  dœd|› �ddœ¬	«      ƒ d {  –—† }|j)                  «       }t+        |t,        «      s"t!        dt/        |«      j0                  › d�«      ‚|j3                  d«      }|st!        d«      ‚|j3                  d«      }	 |�t5        |«      nt6        }	t;        |	t<        z
  d«      }
||
fS 7 Œ # t        j                  $ r(}t!        d
|j"                  j$                  › �«      |‚d }~wt        j&                  $ r}t!        d|› �«      |‚d }~ww xY w# t8        t         f$ r	 t6        }	Y Œ“w xY w­w)N)Úllm_providerz+Fetching Databricks App OAuth token from %sú:Úclient_credentials)Ú
grant_typer(   zBasic z!application/x-www-form-urlencoded)ÚAuthorizationzContent-Type)ÚdataÚheadersz6Databricks App OAuth token request failed with status z+Databricks App OAuth token request failed: zBDatabricks App OAuth token response returned non-object JSON (got ú)Úaccess_tokenz:Databricks App OAuth token response missing 'access_token'Ú
expires_inr   )r   r
   ÚA2Ar   Údebugr'   Úbase64Ú	b64encoder%   r&   r.   ÚdecodeÚpostr(   ÚhttpxÚHTTPStatusErrorr>   ÚresponseÚstatus_codeÚ	HTTPErrorÚjsonr   r=   r?   r3   r<   Úintr   Ú	TypeErrorÚmaxr   )r0   r[   ÚclientÚ
basic_authrw   ÚexcÚbodyrm   Úraw_expires_inrn   r]   s              r   r_   z)DatabricksAppOAuthTokenCache._fetch_token©   sØ  è ø€ Ü.Ô<P×<TÑ<TÔUˆä×ÑÐJÈF×L\ÑL\Ô]ä"×,Ñ,°×0@Ñ0@Ð/AÀÀ6×CWÑCWÐBXÐ-Y×-`Ñ-`Ó-bÓc×jÑjÓlˆ
ð	[Ø$*§K¡KØ× Ñ à"6Ø#Ÿ\™\ñð
 (.¨j¨\Ð%:Ø$Gñð %0ó 
%÷ 
ˆHð$ —m‘m“oˆÜ˜$¤Ô%ÜØTÔUYÐZ^ÓU_×UhÑUhÐTiÐijÐkóð ð #Ÿh™h ~Ó6ˆÙÜÐYÓZÐZà $§¡¨Ó 6ˆð	.Ø0>Ð0Jœ˜^Ô,ÔPdˆJô ˜Ô&BÑBÀAÓFˆØ˜SÐ Ð ðG
ùô ×$Ñ$ò 	ÜØHÈÏÉ×IaÑIaÐHbÐcóàðûô �‰ò 	[ÜÐJÈ3È%ÐPÓQÐWZÐZûð	[ûô  œ:Ð&ò 	.Ü-ŠJð	.üsm   ‚BGÂ4E Â<EÂ=E ÃA1GÄ3G ÅGÅE ÅF?Å2#FÆF?Æ+F:Æ:F?Æ?GÇGÇGÇGÇG)r   N)r3   r4   r5   Ú__doc__rJ   r   rQ   rR   rS   rV   rY   r$   rc   Útupler{   r_   Ú__classcell__)rM   s   @r   rF   rF   y   sp   ø„ ñõ2ðA 3ð A¨7¯<©<ó Að#˜sð # tõ #õðÐ,Dð Èó ð.*!Ð)Að *!ÀeÈCÐQTÈHÁo÷ *!r   rF   Ú databricks_app_oauth_token_cachec              ƒ   ór   K  — t        | «      }|€yt        j                  |«      ƒ d{  –—† }dd|› �iS 7 Œ­w)z Return ``{"Authorization": "Bearer <token>"}`` for a Databricks App agent.

    Returns ``None`` when the agent is not configured for Databricks App OAuth.
    Nri   zBearer )rD   r†   rc   )r9   r[   rb   s      r   Ú"resolve_databricks_app_auth_headerrˆ   Ù   sE   è ø€ ô 2°.ÓA€FØ€~Øä9×IÑIÈ&ÓQ×Q€EØ˜w u gÐ.Ð/Ð/ð Rús   ‚'7©5ª7)"rƒ   rQ   rq   r,   Údataclassesr   Útypingr   r   ru   Úlitellm._loggingr   Úlitellm.caching.in_memory_cacher   Ú&litellm.llms.custom_httpx.http_handlerr   Úlitellm.secret_managers.mainr	   Úlitellm.types.llms.custom_httpr
   r   r6   r   r   r   r   r   r!   r$   r=   rD   rF   r†   rˆ   r8   r   r   ú<module>r�      s  ðòó0 Û Û Ý !ß ã å +Ý 9Ý IÝ 7Ý ?à 2Ð ˜Ó 2à"€�Ó "Ø&(Ð ˜eÓ (Ø"Ð �eÓ "ð˜3ð  3¨¡:ó ð#¨Sð #°Só #ñ �$Ô÷Qð Qó ðQð)Ø˜˜c˜‘N TÑ)ð)à Ñ$ó)ôXZ! =ô Z!ñz +GÓ*HÐ   %Ó Hð0Ø˜˜c˜‘N TÑ)ð0à	ˆ#ˆsˆ(�^�dÑô0r   