o
    î6Wj}�  ã                   @  s”  U d dl mZ d dlZd dlZd dlZd dlZd dlZd dlZd dlZd dl	m
Z
mZmZmZmZmZ d dlmZ d dlZddlmZmZ ddlmZmZmZmZmZmZmZmZmZm Z m!Z!m"Z"m#Z#m$Z$m%Z%m&Z&m'Z'm(Z(m)Z)m*Z*m+Z+m,Z, dd	l-m.Z. e /e0¡Z1d
e2d< e
rŒddl3m4Z4 g d¢Z5d*dd„Z6dZ7dZ8dZ9dZ:dZ;d+dd„Z<G d d!„ d!ƒZ=G d"d#„ d#ƒZ>G d$d%„ d%ƒZ?G d&d'„ d'ƒZ@G d(d)„ d)e?ƒZAdS ),é    )ÚannotationsN)ÚTYPE_CHECKINGÚAnyÚDictÚUnionÚOptionalÚcast)Úoverrideé   )ÚAccessTokenÚIdentityTokenProvider)Ú	ENV_SCOPEÚENV_PROFILEÚENV_BASE_URLÚENV_AUTH_TOKENÚENV_CONFIG_DIRÚTOKEN_ENDPOINTÚDEFAULT_BASE_URLÚENV_WORKSPACE_IDÚENV_ORGANIZATION_IDÚOAUTH_API_BETA_HEADERÚENV_FEDERATION_RULE_IDÚENV_SERVICE_ACCOUNT_IDÚTOKEN_EXCHANGE_TIMEOUTÚENV_IDENTITY_TOKEN_FILEÚGRANT_TYPE_REFRESH_TOKENÚMANDATORY_REFRESH_SECONDSÚ_user_agentÚ_require_httpsÚ_active_profileÚ_config_file_pathÚ_credentials_file_pathÚresolve_identity_token_pathé   )ÚAnthropicErrorzlogging.LoggerÚlog)ÚWorkloadIdentityCredentials)ÚStaticTokenÚEnvTokenÚCredentialsFileÚInMemoryConfigÚIdentityTokenFileÚvaluer   ÚsourceúOptional[pathlib.Path]ÚreturnúOptional[int]c              
   C  s`   | du rdS zt | ƒW S  ttfy/ } z|durd|› �nd}t|› d| ›d�ƒ|‚d}~ww )z@Parse a credentials-file ``expires_at`` field into Unix seconds.Nzcredentials file at Úcredentialsz has invalid 'expires_at' u“   ; expected an integer Unix timestamp in seconds. The SDK does not parse ISO8601 â€” convert with int(datetime.timestamp()) before writing the file.)ÚintÚ	TypeErrorÚ
ValueErrorr$   )r,   r-   ÚerrÚwhere© r7   ús/home/esfera/Documents/content_generation/venv/lib/python3.10/site-packages/anthropic/lib/credentials/_providers.pyÚ_coerce_expires_at2   s   
ÿü€þr9   Úoauth_tokenz1.0Úoidc_federationÚ
user_oauthÚconfigúDict[str, Any]ÚauthÚNonec                 C  s´   ddd	„}|| d
t ƒ || dtƒ || dtƒ | d¡}|tkrL||dtƒ ||dtƒ ||dtƒ | d¡sHtj	 t
¡}|rJd|dœ|d< dS dS dS |tkrX||dtƒ dS dS )uÐ   Fill empty profile fields from corresponding ANTHROPIC_* env vars.

    The profile file is authoritative â€” this only fills fields the file left
    unset. Empty-string env values are treated as unset.
    Útargetr>   ÚkeyÚstrÚenv_varr/   r@   c                 S  s.   |   |¡stj  |¡}|r|| |< d S d S d S ©N)ÚgetÚosÚenviron)rA   rB   rD   Úvr7   r7   r8   ÚfillU   s   
ýz$_fill_missing_from_env.<locals>.fillÚbase_urlÚorganization_idÚworkspace_idÚtypeÚfederation_rule_idÚservice_account_idÚscopeÚidentity_tokenÚfile)r-   ÚpathN)rA   r>   rB   rC   rD   rC   r/   r@   )r   r   r   rF   ÚAUTH_TYPE_OIDC_FEDERATIONr   r   r   rG   rH   r   ÚAUTH_TYPE_USER_OAUTH)r=   r?   rJ   Ú	auth_typerI   r7   r7   r8   Ú_fill_missing_from_envN   s$   


ýÿrX   c                   @  s*   e Zd ZdZddd„Zdd	œddd„ZdS )r'   zQAn :class:`AccessTokenProvider` that always returns a fixed token with no expiry.ÚtokenrC   r/   r@   c                 C  ó
   || _ d S rE   )Ú_token)ÚselfrY   r7   r7   r8   Ú__init__p   ó   
zStaticToken.__init__F©Úforce_refreshr`   Úboolr   c                C  s   ~t | jd d�S )N©rY   Ú
expires_at)r   r[   )r\   r`   r7   r7   r8   Ú__call__s   s   zStaticToken.__call__N)rY   rC   r/   r@   ©r`   ra   r/   r   )Ú__name__Ú
__module__Ú__qualname__Ú__doc__r]   rd   r7   r7   r7   r8   r'   m   s    
r'   c                   @  s.   e Zd ZdZefddd„Zdd	œddd„ZdS )r(   zQAn :class:`AccessTokenProvider` that reads ``ANTHROPIC_AUTH_TOKEN`` at call time.rD   rC   r/   r@   c                 C  rZ   rE   )Ú_env_var)r\   rD   r7   r7   r8   r]   {   r^   zEnvToken.__init__Fr_   r`   ra   r   c                C  s6   ~t j | j¡}|d u rtd| j› d�ƒ‚t|d d�S )NzEnvironment variable zN is not set. Set it or pass an explicit `credentials=` provider to the client.rb   )rG   rH   rF   rj   r$   r   )r\   r`   r,   r7   r7   r8   rd   ~   s   ÿzEnvToken.__call__N)rD   rC   r/   r@   re   )rf   rg   rh   ri   r   r]   rd   r7   r7   r7   r8   r(   x   s    r(   c                   @  sö   e Zd ZdZ	d@ddœdAd
d„ZedBdd„ƒZedCdd„ƒZedDdd„ƒZdEdd„Z	dFdd„Z
dGdd„ZdHdd„ZdHd d!„ZdId#d$„ZdJd%d&„ZdJd'd(„ZdKd*d+„ZdHd,d-„Zd.d/œdLd3d4„Zd.d/œdMd6d7„ZdNd9d:„Zd.d/œdMd;d<„ZdOd>d?„ZdS )Pr)   uí  An :class:`AccessTokenProvider` backed by a named profile.

    A profile is a pair of files under the config directory
    (``~/.config/anthropic/`` by default; override with ``ANTHROPIC_CONFIG_DIR``):

    * ``configs/<profile>.json`` â€” non-secret. Holds the nested
      ``"authentication"`` object (discriminated by its ``"type"`` field), plus
      top-level ``organization_id``, ``workspace_id``, and ``base_url``.
      The ``authentication`` object may contain a ``credentials_path`` field
      overriding the credentials file location.
    * ``credentials/<profile>.json`` â€” secret (0600). Holds ``access_token``,
      ``expires_at``, and (for ``user_oauth`` with a ``client_id``)
      ``refresh_token``.

    The split keeps secret material out of files that may need to be readable
    by config-only consumers, and lets the SDK enforce 0600 on the credentials
    file without locking out config readers.

    Dispatches on the ``authentication.type`` discriminator:

    ``"oidc_federation"``
        OIDC workload identity federation. Lazily constructs a
        :class:`WorkloadIdentityCredentials` delegate from the nested auth
        fields plus the top-level ``organization_id`` and calls it to perform
        the jwt-bearer exchange.

    ``"user_oauth"``
        Output of an interactive PKCE login. If the auth block has a
        ``client_id``, performs ``refresh_token`` grants on expiry and
        writes the new tokens back to the credentials file (atomic replace,
        refresh-token rotation supported). Without a ``client_id``, the
        credentials file is treated as externally rotated â€” the SDK re-reads
        it on every invocation and returns whatever ``access_token`` is
        there, no refresh grant attempted. This is the pattern for a
        sidecar/daemon that mints the access token out-of-band.

    Args:
        profile: Profile name. ``None`` resolves via ``ANTHROPIC_PROFILE`` env
            â†’ ``<config_dir>/active_config`` pointer file â†’ ``"default"``.
    N)Úhttp_clientÚprofileúOptional[str]rk   úOptional[httpx.Client]r/   r@   c                C  sN   |d ur|nt ƒ | _t| jƒ| _d | _|| _d | _d | _d | _t	| _
d | _d S rE   )r   Ú_profiler    Ú_config_pathÚ_bound_base_urlÚ_http_clientÚ_owned_http_clientÚ_configÚ_credentials_pathr   Ú	_base_urlÚ_workload_delegate)r\   rl   rk   r7   r7   r8   r]   ³   s   
zCredentialsFile.__init__rC   c                 C  ó   | j S rE   )ro   ©r\   r7   r7   r8   rl   Æ   ó   zCredentialsFile.profileúpathlib.Pathc                 C  rx   rE   )rp   ry   r7   r7   r8   Úconfig_pathÊ   rz   zCredentialsFile.config_pathc                 C  s(   |   ¡ }| d¡}|rt|ƒ d¡S dS )u‰  The ``base_url`` declared in the profile config file, if any.

        Returns ``None`` when the config has no top-level ``base_url`` key â€”
        callers should fall back to their own default rather than the
        provider's bound/default value, so a profile that *doesn't* pin a
        host never overrides an explicit client setting. Loads the config
        on first access.
        rK   ú/N)Ú_load_configrF   rC   Úrstrip)r\   r=   Úrawr7   r7   r8   Úresolved_base_urlÎ   s   

z!CredentialsFile.resolved_base_urlrK   c                 C  sZ   |  d¡}t|| j› d�d� || _| jdur+|  | j¡| _t| j| j› d�d� dS dS )aÝ  Adopt the owning client's ``base_url`` as a fallback for the token
        exchange. Slots between the config file's own ``base_url`` field and
        the hard-coded default; a ``base_url`` in the config file still wins.

        The owning client binds exactly once at construction; sharing one
        instance across clients with different ``base_url`` values is
        unsupported and silently picks the last bind when the config file
        doesn't pin a host.
        r}   ú
: base_url©ÚfieldN)r   r   rp   rq   rt   Ú_resolve_base_urlrv   )r\   rK   Úboundr7   r7   r8   Úbind_base_urlÜ   s   


þzCredentialsFile.bind_base_urlr=   r>   c                 C  s0   |  d¡rt|d ƒ d¡S | jdur| jS tS )u+  base_url precedence: top-level config field â†’ bound (the owning
        client's base_url, via :meth:`bind_base_url`) â†’ default. Validated
        against the scheme/TLS rules so a malicious config with
        ``base_url="http://evil/"`` can't exfiltrate the assertion or refresh
        token.rK   r}   N)rF   rC   r   rq   r   ©r\   r=   r7   r7   r8   r…   ï   s
   

z!CredentialsFile._resolve_base_urlúDict[str, str]c                 C  s<   |   ¡ }i }|  ¡  d¡tkr| d¡}|rt|ƒ|d< |S )z×Return headers derived from the config file (e.g. ``workspace_id``).

        Eagerly reads the config if not yet loaded. The returned dict is
        suitable for merging into the client's default headers.
        rN   rM   zanthropic-workspace-id)r~   Ú_auth_blockrF   rU   rC   )r\   r=   ÚheadersrM   r7   r7   r8   Úextra_headersû   s   
zCredentialsFile.extra_headersc                 C  s¬  | j dur| j S z	| jjdd�}W n9 ty1 } ztd| j› d| j›dt› dt› d�	ƒ|‚d}~w tt	fyJ } ztd	| j› d
|› �ƒ|‚d}~ww zt
 |¡}W n t
jyk } ztd	| j› d|› �ƒ|‚d}~ww t|tƒs€td	| j› dt|ƒj› d�ƒ‚td|ƒ}| d¡}t|tƒsžtd	| j› dt› dt› d�ƒ‚td|ƒ}t||ƒ |  |¡| _t| j| j› d�d� | d¡}|rËt t|ƒ¡ ¡ | _nt| jƒ| _|| _ |S )zPRead and cache the config file, resolving ``base_url`` and ``credentials_path``.Núutf-8©ÚencodingzConfig file not found at ú
 (profile z). Set z' to select a different profile, or set z" to relocate the config directory.zConfig file at ú could not be read: ú is not valid JSON: z! must contain a JSON object, not Ú.r>   ÚauthenticationzV is missing the 'authentication' object. Expected shape: {"authentication": {"type": "ú"|"ú", ...}, ...}r‚   rƒ   Úcredentials_path)rt   rp   Ú	read_textÚFileNotFoundErrorr$   ro   r   r   ÚOSErrorÚUnicodeDecodeErrorÚjsonÚloadsÚJSONDecodeErrorÚ
isinstanceÚdictrN   rf   r   rF   rU   rV   rX   r…   rv   r   ÚpathlibÚPathrC   Ú
expanduserru   r!   )r\   r€   r5   Ú
raw_configr=   Úraw_authr?   r	   r7   r7   r8   r~     sb   
ÿÿÿü€€ÿ€ÿ
ÿ



þþÿ


zCredentialsFile._load_configc           	   
   C  s   | j dusJ ‚| j }tjdkr{z	tj|dd�}W n/ ty1 } ztd|› d| j›d�ƒ|‚d}~w tyG } ztd|› d	|› �ƒ|‚d}~ww t |j	¡rVtd|› d
�ƒ‚t 
|j	¡}|d@ rotd|› d|d›d|› d�ƒ‚|d@ r{t d|||¡ z|jdd�}W n1 tyœ } ztd|› d| j›d�ƒ|‚d}~w ttfy´ } ztd|› d|› �ƒ|‚d}~ww zt |¡}W n tjyÔ } ztd|› d|› �ƒ|‚d}~ww | d¡}|durþ|tkrþ| jduséJ ‚| jd  d¡}td|›dt›d|›�ƒ‚|S )uj  Read the credentials file. Re-reads on every call â€” daemons rotate it.

        On Unix, verifies the file is not group/world-readable. World-readable
        credentials files are refused outright; group-readable files log a
        warning but are accepted. The check is skipped on Windows where POSIX
        mode bits don't carry the same meaning.
        NÚposixF)Úfollow_symlinkszCredentials file not found at r�   z).úCredentials file at z could not be accessed: zu is a symlink; refusing to follow (move the real file into place to keep secret material on the expected filesystem).é   z is world-readable (mode z#oz); run `chmod 600 z` before retrying.é8   zMCredentials file at %s is group-readable (mode %#o); consider `chmod 600 %s`.r�   rŽ   r‘   r’   rN   r”   zcredentials file has type z; expected z for authentication.type )ru   rG   ÚnameÚstatr™   r$   ro   rš   ÚS_ISLNKÚst_modeÚS_IMODEr%   Úwarningr˜   r›   rœ   r�   rž   rF   ÚCREDENTIALS_FILE_TYPErt   )	r\   rT   Ú	file_statr5   Úmoder€   ÚcredsÚactualrW   r7   r7   r8   Ú_read_credentialsA  sn   
€€ÿ
ÿÿÿü€€ÿ€ÿ
ÿÿz!CredentialsFile._read_credentialsúhttpx.Clientc                 C  s.   | j dur| j S | jdu rtjtd�| _| jS )zFReturn an ``httpx.Client``, lazily creating (and tracking) one we own.N)Útimeout)rr   rs   ÚhttpxÚClientr   ry   r7   r7   r8   Ú_get_http_client{  s
   

z CredentialsFile._get_http_clientc                 C  s6   | j dur| j  ¡  d| _ | jdur| j ¡  dS dS )z3Close the owned ``httpx.Client`` if we created one.N)rs   Úcloserw   ry   r7   r7   r8   r¼   ƒ  s   


ÿzCredentialsFile.closec                 C  s   d| _ d| _dS )aÌ  Drop the cached config so the next call re-reads it from disk.

        ``CredentialsFile`` caches the parsed config across calls to keep the
        hot path cheap; a daemon that rotates a profile in place (e.g. flips
        ``"type": "user_oauth"`` to ``"type": "oidc_federation"``) will not be
        picked up automatically. Callers that need to react to such changes
        can call ``reload()`` to force a fresh read on the next ``__call__``.
        N)rt   rw   ry   r7   r7   r8   Úreload‹  s   	
zCredentialsFile.reloadÚdatac                 C  s&  | j dusJ ‚| j j}|jdddd� tj|d| j j› d�dd�\}}z0z t |d¡ t |t	j
|d	d
� d¡¡ t |¡ W t |¡ nt |¡ w t || j ¡ W n tyk   zt |¡ W ‚  tyj   Y ‚ w w zt |tj¡}zt |¡ W t |¡ W dS t |¡ w  ty’   Y dS w )z;Atomic write to the credentials file (NOT the config file).NTiÀ  )ÚparentsÚexist_okr³   r“   z.tmp)ÚdirÚprefixÚsuffixi€  é   )Úindentr�   )ru   ÚparentÚmkdirÚtempfileÚmkstempr«   rG   ÚfchmodÚwriterœ   ÚdumpsÚencodeÚfsyncr¼   ÚreplaceÚBaseExceptionÚunlinkrš   ÚopenÚO_RDONLY)r\   r¾   rÆ   ÚfdÚtmpÚdir_fdr7   r7   r8   Ú_atomic_write_credentials—  s8    þþý	ÿz)CredentialsFile._atomic_write_credentialsc                 C  s   |   ¡ }td|d ƒS )zEReturn the cached ``authentication`` sub-object from the config file.r>   r”   )r~   r   rˆ   r7   r7   r8   rŠ   ½  s   zCredentialsFile._auth_blockFr_   r`   ra   r   c             
   C  sb   |   ¡ }| d¡}|tkr| j||d�S |tkr| j||d�S td|›d| j› dt›dt›d�	ƒ‚)NrN   r_   úUnknown authentication.type ú at ú. Expected ú or r“   )rŠ   rF   rU   Ú_call_oidc_federationrV   Ú_call_user_oauthr$   rp   )r\   r`   r?   rW   r7   r7   r8   rd   Â  s   
ÿÿÿzCredentialsFile.__call__r?   c             
   C  s  ddl m}m} |  ¡ }| d¡}|std| j› d�ƒ‚| d¡}|s2t| d¡| jƒ}t||d�S | d	¡}	|	sH|d
| j	›dt
›d| j› �ƒ‚t| d¡| jƒ}|sc|durct ¡ |k rct||d�S t|	|dœ}
z|  ¡ j| j› t› �|
dttƒ dœd�}W n tjy” } z|d|› �ƒ|‚d}~ww |jdkr ||dd� | ¡ }| d¡}|s¯|dƒ‚| dd¡}zt|ƒ}W n ttfyÒ } z	|d|›d�ƒ|‚d}~ww tt ¡ ƒ| }| d	¡pá|	}t|d< t|d< ||d< ||d< ||d	< |  |¡ t||d�S )zÞInteractive-login profile. With a ``client_id`` in the auth block,
        we run the refresh_token grant on expiry; without one, we treat the
        credentials file as externally rotated and just read it fresh.
        r
   )ÚWorkloadIdentityErrorÚ_raise_token_endpoint_errorÚaccess_tokenr¨   z is missing 'access_token'.Ú	client_idrc   rb   Úrefresh_tokenzcredentials file for profile z (authentication.type z/ with client_id) must include 'refresh_token': N)Ú
grant_typerâ   rá   zapplication/json)zContent-Typezanthropic-betaz
User-Agent)rœ   r‹   z3user_oauth refresh failed to reach token endpoint: éÈ   zuser_oauth refresh failed)Úmessage_prefixz2user_oauth refresh response missing 'access_token'Ú
expires_ini  z5user_oauth refresh response has invalid 'expires_in' z(; expected an integer number of seconds.ÚversionrN   )Ú	_workloadrÞ   rß   r¶   rF   r$   ru   r9   r   ro   rV   Útimer   r»   Úpostrv   r   r   r   r¹   Ú	HTTPErrorÚstatus_coderœ   r2   r3   r4   ÚCREDENTIALS_FILE_VERSIONr±   r×   )r\   r?   r`   rÞ   rß   r´   rà   rá   rc   râ   ÚbodyÚrespr5   ÚpayloadÚ
new_accessÚraw_expires_inræ   Únew_expires_atÚnew_refreshr7   r7   r8   rÝ   Ó  s€   



ÿþÿýù
ý€ÿ


ÿý€ÿ
z CredentialsFile._call_user_oauthúOptional[Dict[str, Any]]c              
   C  s\   | j dusJ ‚| j  ¡ sdS z|  ¡ W S  ty- } zt|jtƒr(W Y d}~dS ‚ d}~ww )uÑ   ``_read_credentials`` variant that returns ``None`` on absence
        instead of raising â€” used by the federation disk-cache path where a
        missing credentials file just means "exchange now".
        N)ru   Úexistsr¶   r$   rŸ   Ú	__cause__r™   )r\   r5   r7   r7   r8   Ú_read_credentials_if_exists+  s   

€ýz+CredentialsFile._read_credentials_if_existsc             
   C  s  | j d u r|  |¡| _ | jd u r|   ¡ S |  ¡ }|sQ|d urQ| d¡}| d¡}z|rD|d urDt ¡ t|ƒt k rDtt	|ƒt
|ƒd�W S W n ttfyP   Y nw |   ¡ }z|  i |p\i ¥tt|j|jdœ¥¡ W |S  tyƒ } zt d|¡ W Y d }~|S d }~ww )Nrà   rc   rb   )rç   rN   rà   rc   z?federation token disk-cache write-back failed (best-effort): %s)rw   Ú_build_workload_delegateru   rø   rF   ré   Úfloatr   r   rC   r2   r3   r4   r×   rí   r±   rY   rc   rš   r%   Údebug)r\   r?   r`   Úcachedrà   rc   rY   r5   r7   r7   r8   rÜ   :  sH   

	

ÿ€þÿûÿþ€þz%CredentialsFile._call_oidc_federationr&   c              	   C  s
  ddl m}m} | d¡}| jd usJ ‚| j d¡}|r|s)|dt›d| j› �ƒ‚| d¡}|d ur[| d¡}|d	krCtd
|›d�ƒ‚| d¡}|sZtd| j›d| j› d|›d�ƒ‚nd }|rct	|ƒnt	ƒ }	||	||| d¡| j d¡| d¡|  
¡ d�}
|
 | j¡ |
S )Nr
   ©rÞ   r&   rO   rL   z%config file with authentication.type zS must include 'authentication.federation_rule_id' and top-level 'organization_id': rR   r-   rS   zidentity_token source z- is not supported; only 'file' is implementedrT   z@identity_token source 'file' requires a non-empty path; profile rÙ   z has identity_token=r“   rP   rM   rQ   ©Úidentity_token_providerrO   rL   rP   rM   rQ   rk   )rè   rÞ   r&   rF   rt   rU   rp   r$   ro   r+   r»   r‡   rv   )r\   r?   rÞ   r&   rO   rL   Úidentity_token_cfgr-   Úidentity_token_pathÚproviderÚdelegater7   r7   r8   rù   h  sP   
þÿ
	

ÿÿÿÿú
ù	z(CredentialsFile._build_workload_delegaterE   )rl   rm   rk   rn   r/   r@   ©r/   rC   ©r/   r{   )r/   rm   )rK   rC   r/   r@   )r=   r>   r/   rC   )r/   r‰   ©r/   r>   )r/   r·   ©r/   r@   )r¾   r>   r/   r@   re   )r?   r>   r`   ra   r/   r   )r/   rõ   ©r?   r>   r/   r&   )rf   rg   rh   ri   r]   Úpropertyrl   r|   r�   r‡   r…   rŒ   r~   r¶   r»   r¼   r½   r×   rŠ   rd   rÝ   rø   rÜ   rù   r7   r7   r7   r8   r)   ‰   s6    +þü




3
:



&
X.r)   c                   @  s4   e Zd ZdZdddd„Zedd
d„ƒZddd„ZdS )r+   zïAn :class:`IdentityTokenProvider` that reads a JWT from a file on every call.

    Kubernetes projected service-account tokens (and similar) are rotated in place,
    so the file MUST be re-read on every invocation rather than cached.
    NrT   ú$Union[str, 'os.PathLike[str]', None]r/   r@   c                 C  s*   t |ƒ}|d u rtdt› d�ƒ‚|| _d S )Nz;No identity token file path given. Pass `path=` or set the z environment variable.)r"   r$   r   Ú_path)r\   rT   Úresolvedr7   r7   r8   r]   ¥  s   
ÿ
zIdentityTokenFile.__init__r{   c                 C  rx   rE   )r  ry   r7   r7   r8   rT   ®  rz   zIdentityTokenFile.pathrC   c              
   C  sê   z| j jdd� ¡ }W n\ ty! } z
td| j › d�ƒ|‚d }~w ty9 } ztd| j › d|› d�ƒ|‚d }~w tyN } z
td| j › d	�ƒ|‚d }~w ttfyg } ztd| j › d
|› �ƒ|‚d }~ww |sstd| j › d�ƒ‚|S )Nr�   rŽ   z!Identity token file not found at r“   zIdentity token file at z" is not readable by this process: z;. Check the file mode and the effective uid of the process.zIdentity token path zF is a directory, not a file. Point at the projected token file itself.r‘   z‹ is empty. If this is a Kubernetes projected service-account token, check the volume mount and the serviceAccountToken projection audience.)	r  r˜   Ústripr™   r$   ÚPermissionErrorÚIsADirectoryErrorrš   r›   )r\   Úcontentr5   r7   r7   r8   rd   ²  s8   €ÿý€ÿý€€ÿÿzIdentityTokenFile.__call__rE   )rT   r
  r/   r@   r  r  )rf   rg   rh   ri   r]   r	  rT   rd   r7   r7   r7   r8   r+   ž  s    	r+   c                      s^   e Zd ZdZe d¡Zdddœddd„Zeddd„ƒZ	eddd„ƒZ
ed‡ fdd„ƒZ‡  ZS )r*   uÆ  An :class:`AccessTokenProvider` driven by an in-memory config dict
    (same shape as ``configs/<profile>.json``) rather than files on disk.

    Intended for callers that want to construct an :class:`anthropic.Anthropic`
    client with a fully programmatic credentials setup â€” equivalent to the Go
    SDK's ``option.WithConfig`` / TypeScript SDK's ``ClientOptions.config``.

    Both ``authentication.type`` discriminator values are supported:

    ``"oidc_federation"``
        ``authentication.credentials_path`` is **optional**. If set, exchanged
        tokens are cached to / read from that file (same atomic 0600 write as
        :class:`CredentialsFile`). If omitted, every call performs a fresh
        jwt-bearer exchange with no on-disk cache.

    ``"user_oauth"``
        ``authentication.credentials_path`` is **required** â€” it is where the
        access/refresh tokens live. Behaviour is identical to a file-backed
        :class:`CredentialsFile` profile of the same shape.

    The implementation subclasses :class:`CredentialsFile` so the dispatch,
    refresh-grant, disk-cache and atomic-write logic are shared verbatim;
    only config loading and identity-token resolution are overridden.
    z<in-memory config>N)rÿ   rk   r=   r>   rÿ   úOptional[IdentityTokenProvider]rk   rn   r/   r@   c                C  sø   |  d¡}t|tƒstdt› dt› d�ƒ‚td|ƒ}|  d¡}|ttfvr3td|›dt›d	t›d
�ƒ‚|  d¡}|tkrF|sFtdt›d�ƒ‚d| _| j| _	d | _
|| _d | _d | _|| _|| _|rjt t|ƒ¡ ¡ nd | _|  |¡| _t| jdd� d S )Nr”   zaconfig dict is missing the 'authentication' object. Expected shape: {"authentication": {"type": "r•   r–   r>   rN   rØ   rÚ   rÛ   r“   r—   zauthentication.type zŽ requires 'authentication.credentials_path' (where the access/refresh tokens live). For profile-based resolution, use CredentialsFile instead.z<in-memory>zconfig: base_urlrƒ   )rF   rŸ   r    r$   rU   rV   r   ro   Ú_IN_MEMORY_PATHrp   rq   rr   rs   rw   Ú!_identity_token_provider_overridert   r¡   r¢   rC   r£   ru   r…   rv   r   )r\   r=   rÿ   rk   r¥   r?   rW   r—   r7   r7   r8   r]   è  sF   

ÿþÿ

ÿÿÿ

ÿzInMemoryConfig.__init__c                 C  s   | j d usJ ‚| j S rE   )rt   ry   r7   r7   r8   r~     s   zInMemoryConfig._load_configc                 C  s
   d | _ d S rE   )rw   ry   r7   r7   r8   r½     s   
zInMemoryConfig.reloadr?   r&   c              	     s¢   | j d u rtƒ  |¡S ddlm}m} | d¡}| jd usJ ‚| j d¡}|r)|s1|dt›d�ƒ‚|| j ||| d¡| j d¡| d	¡|  	¡ d
�}| 
| j¡ |S )Nr
   rý   rO   rL   z%config dict with authentication.type zQ must include 'authentication.federation_rule_id' and top-level 'organization_id'rP   rM   rQ   rþ   )r  Úsuperrù   rè   rÞ   r&   rF   rt   rU   r»   r‡   rv   )r\   r?   rÞ   r&   rO   rL   r  ©Ú	__class__r7   r8   rù      s*   


ÿ
ù	z'InMemoryConfig._build_workload_delegate)r=   r>   rÿ   r  rk   rn   r/   r@   r  r  r  )rf   rg   rh   ri   r¡   r¢   r  r]   r	   r~   r½   rù   Ú__classcell__r7   r7   r  r8   r*   Ì  s    
û-r*   )r,   r   r-   r.   r/   r0   )r=   r>   r?   r>   r/   r@   )BÚ
__future__r   rG   rœ   r¬   ré   Úloggingr¡   rÈ   Útypingr   r   r   r   r   r   Útyping_extensionsr	   r¹   Ú_typesr   r   Ú
_constantsr   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r    r!   r"   Ú_exceptionsr$   Ú	getLoggerrf   r%   Ú__annotations__rè   r&   Ú__all__r9   r±   ÚCONFIG_FILE_VERSIONrí   rU   rV   rX   r'   r(   r)   r+   r*   r7   r7   r7   r8   Ú<module>   sD     `

    .