Ë
    tPêjÒ‹  ã                   ó  — U d Z ddlmZmZ ddl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mZmZ ddlmZmZ erddlmZ dd	lmZ dd
lmZ ddlZddlmZ ddlmZ ddl ­ 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+m,Z, ddlm-Z- ddl.m/Z/ ddl0m1Z1 ddl2m3Z3 ddl4m5Z5m6Z6m7Z7m8Z8  e
dd¬«      Z9ee:d<    ee;e<e=f   «      Z>ee:d<   er G d„ de	e9   «      Z?ede1dd fd!„«       Z@ede/dd"fd#„«       Z@de1e/z  de=fd$„Z@ e«       ZAee:d%<   d&ee<   ddfd'„ZBd(ee<   deCe<d)f   fd*„ZDd+ede6fd,„ZEeAj�                  d-d.g ee"«      gd/¬0«      eAj�                  d1d.g ee"«      ge5¬2«      d3eGfd4„«       «       ZHeAj�                  d5d.g ee"«      gd/¬0«      eAj�                  d6d.g ee"«      ge8¬2«      d3eGfd7„«       «       ZId3eJdeKdz  fd8„ZLd9e;e<e=f   d:edz  d;e;e<e=f   d<d=ddf
d>„ZMeAj�                  d?d.gd/ ee"«      g¬@«      eAj�                  dAd.g ee"«      ge6¬2«       ee"«      fd3eJdBeNde6fdC„«       «       ZOeAj¡                  dDd.g ee"«      ge6¬2«      eAj¡                  dEd.gd/ ee"«      g¬@«       ej¢                  dF¬G«      fdHe<de6fdI„«       «       ZReAj�                  dJd.g ee"«      ge6¬2«      eAj�                  dKd.gd/ ee"«      g¬@«       ee"«      fd3eSdBeNde6fdL„«       «       ZTeAj�                  dMd.g ee"«      ge7¬2«      eAj�                  dNd.gd/ ee"«      g¬@«       ee"«      fd3eUdBeNde7fdO„«       «       ZVeAj¡                  dPd.g ee"«      geWe6   ¬2«      eAj¡                  dQd.gd/ ee"«      g¬@«       ee"«      fdRedBeNdeWe6   fdS„«       «       ZXeAj¡                  dTd.g ee"«      ge3¬2«      eAj¡                  dUd.gd/ ee"«      g¬@«      ddddddVdWd ee"«      f	dXe<dz  dYe<dz  dZe<dz  d[e<dz  d\e<dz  d]eYd^eYd_e<dz  dBeNfd`„«       «       ZZy)azy
CUSTOMER MANAGEMENT

All /customer management endpoints

/customer/new
/customer/info
/customer/update
/customer/delete
é    )ÚMappingÚSequence)ÚdatetimeÚ	timedelta)ÚTYPE_CHECKINGÚFinalÚProtocolÚTypeVarÚoverloadN)Ú	APIRouterÚDependsÚHTTPExceptionÚRequest)Ú	BaseModelÚTypeAdapter)ÚLiteLLM_BudgetTable)ÚLiteLLM_EndUserTable)ÚPrismaClient)Úverbose_proxy_logger)Úduration_in_seconds)Ú*)Úuser_api_key_auth)Úend_user_cache_keyÚ&end_user_restricted_registry_cache_key)Úget_daily_activity)Úvalidate_budget_duration)Ú_set_object_permissionÚ&handle_update_object_permission_common)Úhandle_exception_on_proxy)ÚBudgetRepository)ÚEndUserRepository)ÚSpendAnalyticsPaginatedResponse)ÚBlockUsersResponseÚCustomerResponseÚDeleteCustomersResponseÚUnblockUsersResponseÚ_RowT_coT)Ú	covariantÚ_STR_OBJECT_DICTc            
       óP  — e Zd Z	 	 ddeeef   dz  deeef   dz  dedz  fd„Z	 	 ddeeef   dz  deeef   dz  de	e   fd„Z
	 ddeeef   deeef   dz  defd„Z	 ddeeef   deeef   deeef   dz  dedz  fd	„Zdeeef   deeeeef   f   defd
„Zdeeef   defd„Zy)Ú	_TableOpsNÚwhereÚincludeÚreturnc              ƒ   ó   K  — y ­w©N© ©Úselfr,   r-   s      úz/home/oem/CyberBrain26-unified/.venv/lib/python3.12/site-packages/litellm/proxy/management_endpoints/customer_endpoints.pyÚ
find_firstz_TableOps.find_first=   s   è ø€ ð "ùó   ‚c              ƒ   ó   K  — y ­wr0   r1   r2   s      r4   Ú	find_manyz_TableOps.find_manyC   s   è ø€ ð "%ùr6   Údatac              ƒ   ó   K  — y ­wr0   r1   )r3   r9   r-   s      r4   Úcreatez_TableOps.createI   ó   è ø€ ð ùr6   c              ƒ   ó   K  — y ­wr0   r1   )r3   r,   r9   r-   s       r4   Úupdatez_TableOps.updateO   s   è ø€ ð
 "ùr6   c              ƒ   ó   K  — y ­wr0   r1   )r3   r,   r9   s      r4   Úupsertz_TableOps.upsertV   r<   r6   c              ƒ   ó   K  — y ­wr0   r1   )r3   r,   s     r4   Údelete_manyz_TableOps.delete_many\   s   è ø� ùr6   )NNr0   )Ú__name__Ú
__module__Ú__qualname__r   ÚstrÚobjectÚboolr'   r5   r   r8   r;   r>   r@   ÚintrB   r1   ó    r4   r+   r+   <   s|  „ ð 26Ø15ñ	"à˜3 ˜;Ñ'¨$Ñ.ð	"ð ˜S $˜YÑ'¨$Ñ.ð	"ð ˜‰_ó		"ð 26Ø15ñ	%à˜3 ˜;Ñ'¨$Ñ.ð	%ð ˜S $˜YÑ'¨$Ñ.ð	%ð �hÑó		%ð 26ñ	à˜#˜v˜+Ñ&ð	ð ˜S $˜YÑ'¨$Ñ.ð	ð ó		ð 26ñ		"à˜3 ˜;Ñ'ð	"ð ˜#˜v˜+Ñ&ð	"ð ˜S $˜YÑ'¨$Ñ.ð		"ð
 ˜‰_ó	"ð	à˜3 ˜;Ñ'ð	ð ˜#˜w s¨F {Ñ3Ð3Ñ4ð	ð ó		ð 	M¨7°3¸°;Ñ+?ÐLÀCÔLrJ   r+   Úrepor.   z_TableOps[PrismaEndUserRow]c                  ó   — y r0   r1   ©rK   s    r4   Ú_typed_tablerN   _   s   € ØLOrJ   z_TableOps[PrismaBudgetRow]c                  ó   — y r0   r1   rM   s    r4   rN   rN   a   s   € ØJMrJ   c                 ó   — | j                   S r0   )ÚtablerM   s    r4   rN   rN   c   s   € Ø�:‰:ÐrJ   ÚrouterÚ
cache_keysc              ƒ   óL   K  — ddl m} ddlm}  || |¬«      ƒ d{  –—†  y7 Œ­w)a  
    Every endpoint that mutates an end-user row must call this, or a newly blocked or budgeted
    customer keeps being served unrestricted until the TTL expires: auth reads end users
    cache-first, and the cached restricted-id registry decides whether the row is read at all.
    r   )Úevict_and_broadcast)Úuser_api_key_cache)rS   rV   N)Ú9litellm.proxy.common_utils.auth_cache_invalidation_pubsubrU   Úlitellm.proxy.proxy_serverrV   )rS   rU   rV   s      r4   Ú_evict_end_user_cache_keysrY   j   s!   è ø€ õõ >á
¨ÐHZÔ
[×[Ò[ús   ‚$œ"�$Úuser_ids.c                 ó.   — g d„ | D «       ¢t        «       ‘­S )z]The per-id entries plus the registry, which any restriction change can move ids in or out of.c              3   ó2   K  — | ]  }t        |«      –— Œ y ­wr0   )r   )Ú.0Úuser_ids     r4   ú	<genexpr>z'_end_user_cache_keys.<locals>.<genexpr>z   s   è ø€ ÒB¨gÔ  ×)ÑBùs   ‚)r   )rZ   s    r4   Ú_end_user_cache_keysr`   x   s   € àmÑB¸ÔBÐmÔDjÓDlÑmÐmrJ   Úrecordc                 óH   — t        j                  | j                  «       «      S )zëValidate a raw end-user DB row into the typed customer response.

    object_permission reverse relations and the budget's audit fields are
    dropped here by the response model's field set, so callers need no manual
    cleanup.
    )r$   Úmodel_validateÚ
model_dump)ra   s    r4   Ú_to_customer_responsere   }   s   € ô ×*Ñ*¨6×+<Ñ+<Ó+>Ó?Ð?rJ   z/end_user/blockzCustomer ManagementF)ÚtagsÚdependenciesÚinclude_in_schemaz/customer/block)rf   rg   Úresponse_modelr9   c              ƒ   óÌ  K  — ddl m} 	 g }|�€| j                  D ]J  }t        t	        |«      «      j                  d|i|ddœddidœ¬	«      ƒ d{  –—† }|j                  |«       ŒL t        t        | j                  «      «      ƒ d{  –—†  nt        d
ddi¬«      ‚d|iS 7 ŒQ7 Œ# t        $ r3}t        j                  d|«       t        d
dt        |«      i¬«      ‚d}~ww xY w­w)aª  
    [BETA] Reject calls with this end-user id

    Parameters:
    - user_ids (List[str], required): The unique `user_id`s for the users to block

        (any /chat/completion call with this user={end-user-id} param, will be rejected.)

        ```
        curl -X POST "http://0.0.0.0:8000/user/block"
        -H "Authorization: Bearer sk-1234"
        -d '{
        "user_ids": [<user_id>, ...]
        }'
        ```
    r   ©Úprisma_clientNr^   T)r^   Úblockedrm   )r;   r>   ©r,   r9   éô  ÚerrorzPostgres DB Not connected©Ústatus_codeÚdetailÚblocked_userszAn error occurred - %s)rX   rl   rZ   rN   r!   r@   ÚappendrY   r`   r   Ú	Exceptionr   rp   rF   )r9   rl   ÚrecordsÚidra   Úes         r4   Ú
block_userrz   ‡   s  è ø€ õ: 9ðGØˆØÐ$Ø—m‘mò '�Ü+Ô,=¸mÓ,LÓM×TÑTØ$ b˜/à.0¸TÑ"BØ#,¨dÐ"3ñð  Uó  ÷ �ð —‘˜vÕ&ð'ô -Ô-AÀ$Ç-Á-Ó-PÓQ×QÑQäØØÐ!<Ð=ôð ð
   Ð)Ð)ðøð Rùô ò GÜ×"Ñ"Ð#;¸QÔ?Ü¨°W¼cÀ!»fÐ4EÔFÐFûðGüsM   ‚C$ŠAB% ÁB!Á8B% ÂB#Â	B% Â C$Â!B% Â#B% Â%	C!Â..CÃC!Ã!C$z/end_user/unblockz/customer/unblockc              ƒ   óê  ‡K  — 	 ddl mŠ t        ˆfd„t        j                  D «       «      rt        j                  €t        dddi¬«      ‚t        t        j                  t        «      r1| j                  D ]!  }t        j                  j                  |«       Œ# nt        ddd	i¬«      ‚d
t        j                  iS # t        $ r+ t        dddt        j
                  j                  z   i¬«      ‚w xY w­w)zÚ
    [BETA] Unblock calls with this user id

    Example
    ```
    curl -X POST "http://0.0.0.0:8000/user/unblock"
    -H "Authorization: Bearer sk-1234"
    -d '{
    "user_ids": [<user_id>, ...]
    }'
    ```
    r   )Ú_ENTERPRISE_BlockedUserListé�  rp   z:Blocked user check was never set. This call has no effect.rq   c              3   ó6   •K  — | ]  }t        |‰«      –— Œ y ­wr0   )Ú
isinstance)r]   Úxr|   s     €r4   r_   zunblock_user.<locals>.<genexpr>æ   s   øè ø€ ÒV¸q”
˜1Ð9×:ÑVùs   ƒro   zF`blocked_user_list` must be set as a list. Filepaths can't be updated.rt   )Ú-enterprise.enterprise_hooks.blocked_user_listr|   ÚImportErrorr   ÚCommonProxyErrorsÚ!missing_enterprise_package_dockerÚvalueÚanyÚlitellmÚ	callbacksÚblocked_user_listr   ÚlistrZ   Úremove)r9   rx   r|   s     @r4   Úunblock_userrŒ   ¿   só   øè ø€ ð2
õ	
ô ÓVÄG×DUÑDUÔVÔVÜ×$Ñ$Ð,äØØÐYÐZô
ð 	
ô
 ”'×+Ñ+¬TÔ2Ø—-‘-ò 	1ˆBÜ×%Ñ%×,Ñ,¨RÕ0ñ	1ô ØØÐeÐfô
ð 	
ð
 œW×6Ñ6Ð7Ð7øô7 ò 
ÜØàÐUÜ#×EÑE×KÑKñLðô
ð 	
ð
üs   ƒC3…B< ‹B1C3Â<4C0Ã0C3c                 óˆ  — t         j                  j                  «       }i }|D ]  }|dk(  rŒ	t        | |d«      }|€Œ|||<   Œ |r~t         j	                  |«      }t        |j                  «       |j                  €F|j                  �:t        j                  «       t        t        |j                  ¬«      ¬«      z   |_        |S y)zE
    Return a new budget object if new budget params are passed.
    Ú	budget_idN)Úduration)Úseconds)ÚBudgetNewRequestÚmodel_fieldsÚkeysÚgetattrrc   r   Úbudget_durationÚbudget_reset_atr   Úutcnowr   r   )r9   Úbudget_paramsÚbudget_kv_pairsÚ
field_namer…   Úbudget_requests         r4   Únew_budget_requestrœ   ú   sÆ   € ô ,×8Ñ8×=Ñ=Ó?€MØ€Oð $ò 0ˆ
Ø˜Ò$ØÜ˜˜j¨$Ó/ˆØÑØ*/ˆO˜JÒ'ð0ñ Ü 0× ?Ñ ?ÀÓ PˆÜ  ×!?Ñ!?Ô@Ø×)Ñ)Ð1°n×6TÑ6TÐ6`Ü-5¯_©_Ó->ÄÜ+°^×5SÑ5SÔTôBñ .ˆNÔ*ð ÐØrJ   Únon_default_valuesÚend_user_table_data_typedÚupdate_end_user_table_datarl   r   c              ƒ   óv   K  — d| v r/|�|j                   nd}t        | ||¬«      ƒ d{  –—† }|�||d<   yyy7 Œ­w)aÏ  
    Handle object permission updates for customer endpoints.

    Updates the update_end_user_table_data dict in place with the new object_permission_id.

    Args:
        non_default_values: Dictionary containing the update values including object_permission
        end_user_table_data_typed: Existing end user table data
        update_end_user_table_data: Dictionary to update with new object_permission_id
        prisma_client: Prisma database client
    Úobject_permissionN)Ú	data_jsonÚexisting_object_permission_idrl   Úobject_permission_id)r¤   r   )r�   rž   rŸ   rl   r£   r¤   s         r4   Ú)_handle_customer_object_permission_updater¥     sg   è ø€ ð" Ð0Ñ0à>WÐ>cÐ%×:Ò:Ðimð 	&ô -SØ(Ø*GØ'ô-
÷ '
Ðð
  Ð+ØAUÐ&Ð'=Ò>ð ,ð 1ð'
ús   ‚&9¨7©9z/end_user/new)rf   rh   rg   z/customer/newÚuser_api_key_dictc              ƒ   ó  K  — 	 ddl m}m}m} |€'t	        ddt
        j                  j                  i¬«      ‚	 | j                  �{|€'t	        ddt
        j                  j                  i¬«      ‚| j                  |j                  «       vr6t	        ddd| j                  › d	t        |j                  «       «      › �i¬«      ‚i }t        | «      }|�p	 t        t        |«      «      j                  i |j!                  d
¬«      ¥|j"                  xs ||j"                  xs |dœ¥¬«      ƒ d{  –—† }|j(                  |d<   n| j(                  �| j(                  |d<   t*        j-                  | j/                  d
¬«      «      }	|	j1                  «       D ]  \  }
}|
t2        j4                  vsŒ|||
<   Œ t*        j-                  t7        ||¬«      ƒ d{  –—† «      }d|v r7t9        j:                  d|j=                  d«      «       |j?                  dd«       t        tA        |«      «      j                  |d
d
dœ¬«      ƒ d{  –—† }tC        tE        | j"                  f«      «      ƒ d{  –—†  tG        |«      S 7 �ŒJ# t$        $ r}t	        ddt'        |«      i¬«      ‚d}~ww xY w7 ŒÑ7 Œd7 Œ?# t$        $ rP}t9        jH                  d|«       dt'        |«      v rtK        d| j"                  › d�ddd¬«      ‚tM        |«      ‚d}~ww xY w­w)aF  
    Allow creating a new Customer 


    Parameters:
    - user_id: str - The unique identifier for the user.
    - alias: Optional[str] - A human-friendly alias for the user.
    - blocked: bool - Flag to allow or disallow requests for this end-user. Default is False.
    - max_budget: Optional[float] - The maximum budget allocated to the user. Either 'max_budget' or 'budget_id' should be provided, not both.
    - budget_id: Optional[str] - The identifier for an existing budget allocated to the user. Either 'max_budget' or 'budget_id' should be provided, not both.
    - allowed_model_region: Optional[Union[Literal["eu"], Literal["us"]]] - Require all user requests to use models in this specific region.
    - default_model: Optional[str] - If no equivalent model in the allowed region, default all requests to this model.
    - metadata: Optional[dict] = Metadata for customer, store information for customer. Example metadata = {"data_training_opt_out": True}
    - budget_duration: Optional[str] - Budget is reset at the end of specified duration. If not set, budget is never reset. You can set duration as seconds ("30s"), minutes ("30m"), hours ("30h"), days ("30d").
    - tpm_limit: Optional[int] - [Not Implemented Yet] Specify tpm limit for a given customer (Tokens per minute)
    - rpm_limit: Optional[int] - [Not Implemented Yet] Specify rpm limit for a given customer (Requests per minute)
    - model_max_budget: Optional[dict] - [Not Implemented Yet] Specify max budget for a given model. Example: {"openai/gpt-4o-mini": {"max_budget": 100.0, "budget_duration": "1d"}}
    - max_parallel_requests: Optional[int] - [Not Implemented Yet] Specify max parallel requests for a given customer.
    - soft_budget: Optional[float] - [Not Implemented Yet] Get alerts when customer crosses given budget, doesn't block requests.
    - spend: Optional[float] - Specify initial spend for a given customer.
    - budget_reset_at: Optional[str] - Specify the date and time when the budget should be reset.
    - object_permission: Optional[LiteLLM_ObjectPermissionBase] - Customer-specific object permissions to control access to resources.
        Supported fields:
        * mcp_servers: List[str] - List of allowed MCP server IDs
        * mcp_access_groups: List[str] - List of MCP access group names
        * mcp_tool_permissions: Dict[str, List[str]] - Map of server ID to allowed tool names (e.g., {"server_1": ["tool_a", "tool_b"]})
        * vector_stores: List[str] - List of allowed vector store IDs
        * agents: List[str] - List of allowed agent IDs
        * agent_access_groups: List[str] - List of agent access group names
        Example: {"mcp_servers": ["server_1", "server_2"], "vector_stores": ["vector_store_1"], "agents": ["agent_1"]}
        IF null or {} then no object-level restrictions apply.
    
    
    - Allow specifying allowed regions 
    - Allow specifying default model

    Example curl:
    ```
    curl --location 'http://0.0.0.0:4000/customer/new'         --header 'Authorization: Bearer sk-1234'         --header 'Content-Type: application/json'         --data '{
            "user_id" : "ishaan-jaff-3",
            "allowed_region": "eu",
            "budget_id": "free_tier",
            "default_model": "azure/gpt-3.5-turbo-eu"
        }'

    # With object permissions
    curl -L -X POST 'http://localhost:4000/customer/new'         -H 'Authorization: Bearer sk-1234'         -H 'Content-Type: application/json'         -d '{
            "user_id": "user_1",
            "object_permission": {
              "mcp_servers": ["server_1"],
              "mcp_access_groups": ["public_group"],
              "vector_stores": ["vector_store_1"]
            }
          }'

        # return end-user object
    ```

    NOTE: This used to be called `/end_user/new`, we will still be maintaining compatibility for /end_user/XXX for these endpoints
    r   )Úlitellm_proxy_admin_nameÚ
llm_routerrl   Nro   rp   rq   i¦  zUDefault Model not on proxy. Configure via `/model/new` or config.yaml. Default_model=z, proxy_model_names=T)Úexclude_unset©Ú
created_byÚ
updated_by)r9   rŽ   )Úexclude_none)r¢   rl   r¡   zLobject_permission still in new_end_user_obj after _set_object_permission: %s©Úlitellm_budget_tabler¡   ©r9   r-   z\litellm.proxy.management_endpoints.customer_endpoints.new_end_user(): Exception occured - %sz3Unique constraint failed on the fields: (`user_id`)z(Customer already exists, passed user_id=z. Please pass a new user_id.Úbad_requestr}   r^   ©ÚmessageÚtypeÚcodeÚparam)'rX   r¨   r©   rl   r   rƒ   Údb_not_connected_errorr…   Údefault_modelÚno_llm_routerÚget_model_namesÚsetrœ   rN   r    r;   rd   r^   rv   rF   rŽ   r)   Úvalidate_pythonÚdictÚitemsr‘   r’   r   r   ÚwarningÚgetÚpopr!   rY   r`   re   Ú	exceptionÚProxyExceptionr   )r9   r¦   r¨   r©   rl   Únew_end_user_objÚ_new_budgetÚbudget_recordry   Ú
_user_dataÚkÚvÚend_user_records                r4   Únew_end_userrÌ   2  st  è ø€ ðd
÷ñ ð ÐÜØØÔ.×EÑE×KÑKÐLô
ð 	
ðO+à×ÑÐ)ØÐ!Ü#Ø #Ø#Ô%6×%DÑ%D×%JÑ%JÐKôð ð ×#Ñ#¨:×+EÑ+EÓ+GÑGÜ#Ø #àÐ#xÐy}÷  zLñ  zLð  yMð  Maô  beð  fp÷  f@ñ  f@ó  fBó  bCð  aDð  "Eðôð ð /1Ðô 0°Ó5ˆØÐ"ð	OÜ-9Ô:JÈ=Ó:YÓ-Z×-aÑ-aðØ%×0Ñ0¸tÐ0ÓDðà&7×&?Ñ&?Ò&[ÐC[Ø&7×&?Ñ&?Ò&[ÐC[òð .bó .÷ (�ð -:×,CÑ,CÐ˜[Ò)Ø�^‰^Ð'Ø,0¯N©NÐ˜[Ñ)ä,×<Ñ<¸T¿Y¹YÐTX¸YÓ=YÓZˆ
à×$Ñ$Ó&ò 	(‰DˆAˆqØÔ(×5Ñ5Ò5Ø&'Ð  Ò#ð	(ô
 ,×;Ñ;Ü(Ø*Ø+ô÷ ó
Ðð Ð"2Ñ2Ü ×(Ñ(Ø^Ø ×$Ñ$Ð%8Ó9ôð × Ñ Ð!4°dÔ;ô (4Ô4EÀmÓ4TÓ'U×'\Ñ'\Ø!Ø-1ÈÑMð (]ó (
÷ "
ˆô
 )Ô)=¸t¿|¹|¸oÓ)NÓO×OÐOä$ _Ó5Ð5ð[(úô ò OÜ#°¸WÄcÈ!ÃfÐ<MÔNÐNûðOúðøð "
øð
 	Pùô ò +Ü×&Ñ&ØjÐlmô	
ð AÄCÈÃFÑJÜ ØBÀ4Ç<Á<À.ÐPlÐmØ"ØØô	ð ô (¨Ó*Ð*ûð+üs™   ‚5L¸BJ% ÃAI6 Ä)I3Ä*I6 Ä.A8J% Æ'&J% ÇJÇA.J% È<J!È=&J% É#J#É$J% É2LÉ3I6 É6	JÉ?JÊJÊJ% Ê!J% Ê#J% Ê%	K>Ê.AK9Ë9K>Ë>Lz/customer/infoz/end_user/infoz%End User ID in the request parameters)ÚdescriptionÚend_user_idc              ƒ   óv  K  — 	 ddl m} |€'t        ddt        j                  j
                  i¬«      ‚t        t        |«      «      j                  d| iddd	œ¬
«      ƒ d{  –—† }|€t        d| › d�ddd¬«      ‚t        |«      S 7 Œ$# t        $ r&}t        j                  d|«       t        |«      ‚d}~ww xY w­w)ae  
    Get information about an end-user. An `end_user` is a customer (external user) of the proxy.

    Parameters:
    - end_user_id (str, required): The unique identifier for the end-user

    Example curl:
    ```
    curl -X GET 'http://localhost:4000/customer/info?end_user_id=test-litellm-user-4'         -H 'Authorization: Bearer sk-1234'
    ```
    r   rk   Nro   rp   rq   r^   Tr¯   ©r,   r-   úEnd User Id=ú does not exist in dbÚ	not_foundé”  rÎ   r³   z]litellm.proxy.management_endpoints.customer_endpoints.end_user_info(): Exception occured - %s)rX   rl   r   rƒ   r¸   r…   rN   r!   r5   rÄ   re   rv   r   rÃ   r   )rÎ   rl   Ú	user_infory   s       r4   Úend_user_inforÖ   ì  sà   è ø€ ð6+Ý<àÐ ÜØØÔ!2×!IÑ!I×!OÑ!OÐPôð ô
 ".Ô.?ÀÓ.NÓ!O×!ZÑ!ZØ˜kÐ*Ø-1ÈÑMð "[ó "
÷ 
ˆ	ð
 ÐÜ Ø& { mÐ3HÐIØ ØØ#ô	ð ô % YÓ/Ð/ð
ùô ò +Ü×&Ñ&ØkÐmnô	
ô (¨Ó*Ð*ûð	+üs;   ‚B9„AB Á BÁ!#B ÂB9ÂB Â	B6Â!B1Â1B6Â6B9z/customer/updatez/end_user/updatec              ƒ   óž  K  — ddl m}m} 	 t        j	                  | j                  «       «      }|€t        d«      ‚t        t        t        f   «       }|j                  «       D ]  \  }}|€Œ	|g i dfvsŒ|||<   Œ t        t        |«      «      j                  d| j                  iddi¬«      ƒ d{  –—† }|€t        d	| j                  › d
�ddd¬«      ‚t         j#                  |j%                  «       «      }	|	j&                  }
t        t        t        f   «       }t        t        t        f   «       }|j                  «       D ]@  \  }}|dk(  r|||<   Œ|t(        j*                  v r|||<   Œ)|t         j*                  v sŒ<|||<   ŒB t-        ||	||¬«      ƒ d{  –—†  |r�|
€bt        t/        |«      «      j1                  i |¥|j                  xs ||j                  xs |dœ¥ddi¬«      ƒ d{  –—† }|j2                  |d<   n9t        t/        |«      «      j5                  d|
j2                  i|¬«      ƒ d{  –—† }t7        j8                  d| «       d|v r7t7        j:                  d|j=                  d«      «       |j?                  dd«       | j                  �ÛtA        | j                  «      dkD  rÃ| j                  |d<   t7        j8                  d«       t        t        |«      «      j5                  d| j                  i|dddœ¬«      ƒ d{  –—† }|€tC        d| j                  › �«      ‚t7        j8                  d|«       tE        tG        | j                  f«      «      ƒ d{  –—†  tI        |«      S tC        d| j                  › �«      ‚7 �ŒÚ7 �Œ÷7 �Œ¤7 �Œ^7 ŒŠ7 Œ5# t        $ r&}t7        jJ                  d|«       tM        |«      ‚d}~ww xY w­w)aî  
    Example curl 

    Parameters:
    - user_id: str
    - alias: Optional[str] = None  # human-friendly alias
    - blocked: bool = False  # allow/disallow requests for this end-user
    - max_budget: Optional[float] = None
    - budget_id: Optional[str] = None  # give either a budget_id or max_budget
    - allowed_model_region: Optional[AllowedModelRegion] = (
        None  # require all user requests to use models in this specific region
    )
    - default_model: Optional[str] = (
        None  # if no equivalent model in allowed region - default all requests to this model
    )
    - object_permission: Optional[LiteLLM_ObjectPermissionBase] - Customer-specific object permissions to control access to resources.
        Supported fields:
        * mcp_servers: List[str] - List of allowed MCP server IDs
        * mcp_access_groups: List[str] - List of MCP access group names
        * mcp_tool_permissions: Dict[str, List[str]] - Map of server ID to allowed tool names
        * vector_stores: List[str] - List of allowed vector store IDs
        * agents: List[str] - List of allowed agent IDs
        * agent_access_groups: List[str] - List of agent access group names
        Example: {"mcp_servers": ["server_1"], "vector_stores": ["vector_store_1"]}
        IF null or {} then no object-level restrictions apply.

    Example curl:
    ```
    curl --location 'http://0.0.0.0:4000/customer/update'     --header 'Authorization: Bearer sk-1234'     --header 'Content-Type: application/json'     --data '{
        "user_id": "test-litellm-user-4",
        "budget_id": "paid_tier"
    }'

    # Updating object permissions
    curl -L -X POST 'http://localhost:4000/customer/update'     --header 'Authorization: Bearer sk-1234'     --header 'Content-Type: application/json'     --data '{
        "user_id": "user_1",
        "object_permission": {
          "mcp_servers": ["server_3"],
          "vector_stores": ["vector_store_2", "vector_store_3"]
        }
      }'

    See below for all params
    ```
    r   )r¨   rl   NúNot connected to DB!r^   r°   TrÐ   rÑ   rÒ   rÓ   rÔ   r³   rŽ   )r�   rž   rŸ   rl   r«   Ú	end_usersr±   rn   z$/customer/update: Received data = %sr¡   z9object_permission still in update_end_user_table_data: %sz,In update customer, user_id condition block.r¯   )r,   r9   r-   zEFailed updating customer data. User ID does not exist passed user_id=ú:received response from updating prisma client. response=%sú&user_id is required, passed user_id = zDlitellm.proxy.proxy_server.update_end_user(): Exception occured - %s)'rX   r¨   rl   r)   r½   Újsonrv   r¾   rF   rG   r¿   rN   r!   r5   r^   rÄ   r   rc   rd   r°   r   r’   r¥   r    r;   rŽ   r>   r   ÚdebugrÀ   rÁ   rÂ   ÚlenÚ
ValueErrorrY   r`   re   rÃ   r   )r9   r¦   r¨   rl   r¢   r�   rÉ   rÊ   Úend_user_table_datarž   Úend_user_budget_tableÚbudget_table_datarŸ   Úbudget_table_data_recordÚresponsery   s                   r4   Úupdate_end_userrå   &  s  è ø€ ÷H Sðn+Ü+×;Ñ;¸D¿I¹I»KÓHˆ	àÐ ÜÐ2Ó3Ð3ô %)¬¬f¨Ñ$5Ó$7ÐØ—O‘OÓ%ò 	*‰DˆAˆqØ‰} ØØØð+ò "ð
 )*Ð" 1Ò%ð	*ô ,8Ô8IÈ-Ó8XÓ+Y×+dÑ+dØ˜dŸl™lÐ+Ð6LÈdÐ5Sð ,eó ,
÷ &
Ðð Ð&Ü Ø& t§|¡| nÐ4IÐJØ ØØô	ð ô ,@×+NÑ+NÐOb×OmÑOmÓOoÓ+pÐ!ð (A×'UÑ'UÐô $(¬¬V¨Ñ#4Ó#6ÐÜ,0´´f°Ñ,=Ó,?Ð"Ø&×,Ñ,Ó.ò 	2‰DˆAˆqà�KÒØ01Ð*¨1Ò-ØÔ)×6Ñ6Ñ6Ø'(Ð! !Ò$àÔ*×7Ñ7Ò7Ø01Ð*¨1Ò-ð	2ô 8Ø1Ø&?Ø'AØ'ô	
÷ 	
ð 	
ñ Ø$Ð,ä1=Ô>NÈ}Ó>]Ó1^×1eÑ1eðØ+ðà&7×&?Ñ&?Ò&[ÐC[Ø&7×&?Ñ&?Ò&[ÐC[òð
 )¨$Ð/ð 2fó 2÷ ,Ð(ð ;S×:\Ñ:\Ð*¨;Ò7ô 2>Ô>NÈ}Ó>]Ó1^×1eÑ1eØ&Ð(=×(GÑ(GÐHØ*ð 2fó 2÷ ,Ð(ô 	×"Ñ"Ð#IÈ4ÔPð Ð"<Ñ<Ü ×(Ñ(ØKØ*×.Ñ.Ð/BÓCôð '×*Ñ*Ð+>ÀÔEà�<‰<Ð#¬¨D¯L©LÓ(9¸AÒ(=Ø48·L±LÐ& yÑ1Ü ×&Ñ&Ð'UÔVÜ$0Ô1BÀ=Ó1QÓ$R×$YÑ$YØ  $§,¡,Ð/Ø/Ø15ÈDÑQð %Zó %÷ ˆHð
 ÐÜ Ð#hÐim×iuÑiuÐhvÐ!wÓxÐxÜ ×&Ñ&Ð'cÐemÔnä,Ô-AÀ4Ç<Á<À/Ó-RÓS×SÐSä(¨Ó2Ð2äÐEÀdÇlÁlÀ^ÐTÓUÐUðo&
ùð>	
ùð,ùð,ùð(øð Tùô ò +Ü×&Ñ&Ð'mÐopÔqÜ'¨Ó*Ð*ûð+üs¬   ‚	OŒAN Á,N Á4=N Â1NÂ2CN Å>N ÆNÆAN Ç-NÇ.AN È6NÈ7CN ÌNÌAN Í#NÍ$N Í2OÍ3N ÎN ÎN ÎN ÎN ÎN Î	O
Î$!OÏO
Ï
Oz/customer/deletez/end_user/deletec              ƒ   ó  K  — ddl m} 	 |€t        d«      ‚t        j                  d| «       | j
                  ��mt        | j
                  t        «      �rRt        | j
                  «      dkD  �r9t        t        |«      «      j                  dd| j
                  ii¬«      ƒ d{  –—† }|D �ch c]  }|j                  ’Œ }}| j
                  D �cg c]	  }||vsŒ|‘Œ }}|r-t        d	j                  d
j                  |«      «      ddd¬«      ‚t        t        |«      «      j!                  dd| j
                  ii¬«      ƒ d{  –—† }t        j                  d|«       t#        t%        | j
                  «      «      ƒ d{  –—†  t'        |dt)        | j
                  «      z   ¬«      S t+        d| j
                  › �«      ‚7 �Œc c}w c c}w 7 Œˆ7 ŒN# t        $ r&}	t        j,                  d|	«       t/        |	«      ‚d}	~	ww xY w­w)a«  
    Delete multiple end-users.

    Parameters:
    - user_ids (List[str], required): The unique `user_id`s for the users to delete

    Example curl:
    ```
    curl --location 'http://0.0.0.0:4000/customer/delete'         --header 'Authorization: Bearer sk-1234'         --header 'Content-Type: application/json'         --data '{
            "user_ids" :["ishaan-jaff-5"]
    }'

    See below for all params 
    ```
    r   rk   NrØ   z$/customer/delete: Received data = %sr^   Úin©r,   z$End User Id(s)={} do not exist in dbz, rÓ   rÔ   rZ   r³   rÚ   z)Successfully deleted customers with ids: )Údeleted_customersr´   rÛ   zDlitellm.proxy.proxy_server.delete_end_user(): Exception occured - %s)rX   rl   rv   r   rÝ   rZ   r   rŠ   rÞ   rN   r!   r8   r^   rÄ   ÚformatÚjoinrB   rY   r`   r%   rF   rß   rp   r   )
r9   r¦   rl   Úexisting_usersÚuserÚexisting_user_idsr^   Úmissing_user_idsrä   ry   s
             r4   Údelete_end_userrð   Ý  sê  è ø€ õD 9ð'+ØÐ ÜÐ2Ó3Ð3ä×"Ñ"Ð#IÈ4ÔPØ�=‰=Ñ$¬°D·M±MÄ4Õ)HÌSÐQU×Q^ÑQ^ÓM_ÐbcÓMcä*6Ô7HÈÓ7WÓ*X×*bÑ*bØ  4¨¯©Ð"7Ð8ð +có +÷ %ˆNð BPÖ'P¸¨¯«Ð'PÐÐ'PØ>B¿m¹mÖ&p°7ÈwÐ^oÒOo¢wÐ&pÐÐ&páÜ$ØB×IÑIÈ$Ï)É)ÐTdÓJeÓfØ$ØØ$ô	ð ô %1Ô1BÀ=Ó1QÓ$R×$^Ñ$^Ø  4¨¯©Ð"7Ð8ð %_ó %÷ ˆHô !×&Ñ&Ð'cÐemÔnä,Ô-AÀ$Ç-Á-Ó-PÓQ×QÐQä*Ø"*ØCÄcÈ$Ï-É-ÓFXÑXôð ô
 ÐEÀdÇmÁmÀ_ÐUÓVÐVð7%ûò (QùÚ&pðøð
 Rùô ò +Ü×"Ñ"Ð#iÐklÔmÜ'¨Ó*Ð*ûð+üs~   ‚HŠBG Â#F?Â$G Â,GÂ?G Ã	GÃGÃA&G ÅGÅ;G Å?GÆ &G Æ&HÆ'G ÇG ÇG Ç	G?Ç!G:Ç:G?Ç?Hz/customer/listz/end_user/listÚhttp_requestc              ƒ   ó  K  — 	 ddl m} |j                  t        j                  k7  r9|j                  t        j
                  k7  rt        ddd|j                  › �i¬«      ‚|€'t        ddt        j                  j                  i¬«      ‚t        t        |«      «      j                  d	d	d
œ¬«      ƒ d{  –—† }|D �cg c]  }t        |«      ‘Œ c}S 7 Œc c}w # t        $ r&}t        j                   d|«       t#        |«      ‚d}~ww xY w­w)zÎ
    [Admin-only] List all available customers

    Example curl:
    ```
    curl --location --request GET 'http://0.0.0.0:4000/customer/list'         --header 'Authorization: Bearer sk-1234'
    ```

    r   rk   é‘  rp   ú$Admin-only endpoint. Your user role=rq   Nr}   Tr¯   )r-   z]litellm.proxy.management_endpoints.customer_endpoints.list_end_user(): Exception occured - %s)rX   rl   Ú	user_roleÚLitellmUserRolesÚPROXY_ADMINÚPROXY_ADMIN_VIEW_ONLYr   rƒ   r¸   r…   rN   r!   r8   re   rv   r   rÃ   r   )rñ   r¦   rl   rä   Úitemry   s         r4   Úlist_end_userrú   +  s  è ø€ ð4+Ý<ð ×'Ñ'Ô+;×+GÑ+GÒGØ!×+Ñ+Ô/?×/UÑ/UÒUäØØÐ#GÐHY×HcÑHcÐGdÐ!eÐfôð ð
 Ð ÜØØÔ!2×!IÑ!I×!OÑ!OÐPôð ô
 !-Ô->¸}Ó-MÓ N× XÑ XØ-1ÈÑMð !Yó !
÷ 
ˆð 9AÖA°Ô% dÕ+ÒAÐAð	
úò Bøäò +Ü×&Ñ&ØkÐmnô	
ô (¨Ó*Ð*ûð	+üsM   ‚D
„B/C Â3CÂ4C Â<CÃC ÃD
ÃC ÃC Ã	DÃ!!DÄDÄD
z/customer/daily/activityz/end_user/daily/activityé   é
   Úend_user_idsÚ
start_dateÚend_dateÚmodelÚapi_keyÚpageÚ	page_sizeÚexclude_end_user_idsc	              ƒ   ó´  K  — |j                   t        j                  k7  r9|j                   t        j                  k7  rt	        ddd|j                   › �i¬«      ‚ddlm}	 |	€'t	        ddt        j                  j                  i¬«      ‚| r| j                  d	«      nd}
d}|r|r|j                  d	«      nd}t        t        t        f   «       }|
rd
t        |
«      i|d<   t        t!        |	«      «      j#                  |¬«      ƒ d{  –—† }t%        |	dd|
|D �ci c]  }|j&                  d|j(                  i“Œ c}|||||||¬«      ƒ d{  –—† S 7 ŒHc c}w 7 Œ­w)zX
    Get daily activity for specific organizations or all accessible organizations.
    ró   rp   rô   rq   r   rk   Nro   ú,rç   r^   rè   Úlitellm_dailyenduserspendrÎ   Úalias)rl   Ú
table_nameÚentity_id_fieldÚ	entity_idÚentity_metadata_fieldÚexclude_entity_idsrþ   rÿ   r   r  r  r  )rõ   rö   r÷   rø   r   rX   rl   rƒ   r¸   r…   Úsplitr¾   rF   rG   rŠ   rN   r!   r8   r   r^   r  )rý   rþ   rÿ   r   r  r  r  r  r¦   rl   Úend_user_ids_listÚexclude_end_user_ids_listÚwhere_conditionÚend_user_aliasesry   s                  r4   Úget_customer_daily_activityr  d  sv  è ø€ ð6 	×#Ñ#Ô'7×'CÑ'CÒCØ×'Ñ'Ô+;×+QÑ+QÒQäØØÐCÐDU×D_ÑD_ÐC`ÐaÐbô
ð 	
õ
 9àÐÜØØÔ.×EÑE×KÑKÐLô
ð 	
ñ ;G˜|×1Ñ1°#Ô6ÈDÐØ26ÐÙÙG[Ð$8×$>Ñ$>¸sÔ$CÐaeÐ!ô "¤#¤v +Ñ.Ó0€OÙØ&*¬DÐ1BÓ,CÐ%Dˆ˜	Ñ"Ü$0Ô1BÀ=Ó1QÓ$R×$\Ñ$\ÐcrÐ$\Ó$s×sÐô $Ø#Ø.Ø%Ø#ØFVÖWÀ˜qŸy™y¨7°A·G±GÐ*<Ñ<ÒWØ4ØØØØØØô÷ ð ð túò Xðús0   ‚DEÄEÄEÄ EÄ8EÅ
EÅEÅE)[Ú__doc__Úcollections.abcr   r   r   r   Útypingr   r   r	   r
   r   Úfastapir   r   r   r   Úpydanticr   r   Úprisma.modelsr   ÚPrismaBudgetRowr   ÚPrismaEndUserRowÚlitellm.proxy.utilsr   r‡   Úlitellm._loggingr   Ú*litellm.litellm_core_utils.duration_parserr   Úlitellm.proxy._typesÚ$litellm.proxy.auth.user_api_key_authr   Ú-litellm.proxy.common_utils.user_api_key_cacher   r   Ú8litellm.proxy.management_endpoints.common_daily_activityr   Ú/litellm.proxy.management_endpoints.common_utilsr   Ú8litellm.proxy.management_helpers.object_permission_utilsr   r   r   Ú&litellm.repositories.budget_repositoryr    Ú'litellm.repositories.table_repositoriesr!   Ú>litellm.types.proxy.management_endpoints.common_daily_activityr"   Ú;litellm.types.proxy.management_endpoints.customer_endpointsr#   r$   r%   r&   r'   Ú__annotations__r¾   rF   rG   r)   r+   rN   rR   rY   Útupler`   re   ÚpostÚ
BlockUsersrz   rŒ   ÚNewCustomerRequestr‘   rœ   r¥   ÚUserAPIKeyAuthrÌ   rÁ   ÚQueryrÖ   ÚUpdateCustomerRequestrå   ÚDeleteCustomerRequestrð   rŠ   rú   rI   r  r1   rJ   r4   ú<module>r2     sŽ  ðò	÷ .ß (ß DÕ Dã ß >Ó >ß +áÝDÝFå0ã Ý 1Ý JÜ "Ý B÷õ XÝ T÷õ :Ý CÝ Eõ÷ó ñ ˜*°Ô5€ˆ%Ó 5Ù% d¨3°¨;Ñ&7Ó8Ð �%Ó 8áô M�H˜XÑ&ô  MðF 
Ø OÐ(Ð OÐ-JÒ Oó 
Ø OØ	Ø MÐ'Ð MÐ,HÒ Mó 
Ø MðÐ(Ð+;Ñ;ð Àó ñ “€ˆÓ ð\°¸#±ð \À4ó \ðn 8¨C¡=ð n°U¸3À¸8±_ó nð
@ )ð @Ð0@ó @ð ‡�ØØ
Ð	 ÙÐ+Ó,Ð-Øð	 ó ð ‡�ØØ
Ð	 ÙÐ+Ó,Ð-Ø%ð	 ó ð)G˜:ò )Góóð)GðX ‡�ØØ
Ð	 ÙÐ+Ó,Ð-Øð	 ó ð ‡�ØØ
Ð	 ÙÐ+Ó,Ð-Ø'ð	 ó ð,8˜Zò ,8óóð,8ð^Ð/ð Ð4DÀtÑ4Kó ð4VØ˜S &˜[Ñ)ðVà3°dÑ:ðVð !% S¨& [Ñ 1ðVð "ð	Vð
 
óVð< ‡�ØØ
Ð	 ØÙÐ+Ó,Ð-ð	 ó ð ‡�ØØ
Ð	 ÙÐ+Ó,Ð-Ø#ð	 ó ñ )0Ð0AÓ(Bñk+Ø
ðk+à%ðk+ð òk+óóðk+ð\ ‡�ØØ
Ð	 ÙÐ+Ó,Ð-Ø#ð	 ó ð ‡�ØØ
Ð	 ØÙÐ+Ó,Ð-ð	 ó ð %�w—}‘}Ð1XÔYñ++Øð++àò++óóð++ð\ ‡�ØØ
Ð	 ÙÐ+Ó,Ð-Ø#ð	 ó ð ‡�ØØ
Ð	 ØÙÐ+Ó,Ð-ð	 ó ñ )0Ð0AÓ(Bñh+Ø
ðh+à%ðh+ð òh+óóðh+ðV ‡�ØØ
Ð	 ÙÐ+Ó,Ð-Ø*ð	 ó ð ‡�ØØ
Ð	 ØÙÐ+Ó,Ð-ð	 ó ñ )0Ð0AÓ(Bñ?+Ø
ð?+à%ð?+ð ò?+óóð?+ðD ‡�ØØ
Ð	 ÙÐ+Ó,Ð-ØÐ(Ñ)ð	 ó ð ‡�ØØ
Ð	 ØÙÐ+Ó,Ð-ð	 ó ñ )0Ð0AÓ(Bñ*+Øð*+à%ð*+ð 
Ð
Ñò*+óóð*+ðZ ‡�ØØ
Ð	 ÙÐ+Ó,Ð-Ø2ð	 ó ð ‡�ØØ
Ð	 ØÙÐ+Ó,Ð-ð	 ó ð  $Ø!ØØØØØØ'+Ù(/Ð0AÓ(Bñ9Ø˜‘*ð9à�d‘
ð9ð �D‰jð9ð �‰:ð	9ð
 �4‰Zð9ð ð9ð ð9ð  ™*ð9ð &ò9óóñ9rJ   