
    g                        d 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 ddlm	Z	m
Z
mZm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 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/m0Z0m1Z1 dd	l2m3Z3m4Z4 dd
l5m6Z6 ddl7m8Z8m9Z9 ddl:m;Z;  e       Z<de1de de=fdZ>	 d;de;de	e?   de
e?   de	e   fdZ@e<j                  ddg ee6      ge       e9 ee6       edd      fde&dede1de
e?   fd              ZBde0de
e?   de;de1de?de
e?   fd ZCe<j                  d!dg ee6      g"      e9 ee6       edd      fde0dede1de
e?   fd#              ZDd$ee%e	e%   f   d%e=fd&ZEde
e;   de,d%e=fd'ZFe<j                  d(dg ee6      ge)      e9 ee6      fde,dede1fd)              ZGe<j                  d*dg ee6      g"      e9 ee6      fde-dede1fd+              ZHe<j                  d,dg ee6      ge/      e9 ee6      fde.dede1fd-              ZIe<j                  d.dg ee6      g"      e9 ee6       edd      fdedede1de
e?   fd/              ZJe<j                  d0dg ee6      g"      e9 ej                  dd12       ee6      fdede?de1fd3              ZMe<j                  d4dg ee6      g"      e9 ee6      fdedede1fd5              ZNe<j                  d6dg ee6      g"      e9 ee6      fdedede1fd7              ZOe<j                  d8dg ee6      g"      e9 ej                  dd92       ee6      fdede
e?   de1fd:              ZPy)<zb
TEAM MANAGEMENT

All /team management endpoints 

/team/new
/team/info
/team/update
/team/delete
    N)datetime	timedeltatimezone)ListOptionalUnioncast)	APIRouterDependsHeaderHTTPExceptionRequeststatus)	BaseModel)verbose_proxy_logger)BlockTeamRequestCommonProxyErrorsDeleteTeamRequestLiteLLM_AuditLogsLiteLLM_ModelTableLiteLLM_TeamMembershipLiteLLM_TeamTableLiteLLM_TeamTableCachedObjLiteLLM_UserTableLitellmTableNamesLitellmUserRolesMemberNewTeamRequestProxyErrorTypesProxyExceptionTeamAddMemberResponseTeamInfoResponseObjectTeamListResponseObjectTeamMemberAddRequestTeamMemberDeleteRequestTeamMemberUpdateRequestTeamMemberUpdateResponseUpdateTeamRequestUserAPIKeyAuth) allowed_route_check_inside_routeget_team_object)user_api_key_auth)add_new_membermanagement_endpoint_wrapper)PrismaClientuser_api_key_dictteam_objreturnc                 v    |j                   D ]*  }|j                  |j                  | j                  k(  s* y y)NTF)members_with_rolesuser_id)r0   r1   members      f/var/www/openai/venv/lib/python3.12/site-packages/litellm/proxy/management_endpoints/team_endpoints.py_is_user_team_adminr8   A   s8     -->>%&..<M<U<U*U .     prisma_clientteam_idr5   c           	      &  K   t        |t              st        |      }| j                  j                  j	                  ||d|idndd|iiddi       d{   }g }|D ]*  }|j                  t        di |j                                , |S 7 7w)	z)Get all team memberships for a given userNin)r5   r;   r;   litellm_budget_tableT)whereinclude )
isinstancestrdblitellm_teammembership	find_manyappendr   
model_dump)r:   r;   r5   team_membershipsreturned_tmtms         r7   get_all_team_membershipsrL   K   s     
 gs#g,*--DDNN "  T7O<dG_-'. O   13K1DBMMODE  s   ABB8Bz	/team/newzteam management)tagsdependenciesresponse_modelzThe litellm-changed-by header enables tracking of actions performed by authorized users on behalf of other users, providing an audit trail for accountability)descriptiondatahttp_requestlitellm_changed_byc                 ,  K   ddl m}m}m}m} |t        dddi      | j                  #t        t        j                               | _        nE|j                  | j                  dd	
       d{   }|t        ddd| j                   di      |j                  |j                  t        j                  k7  rz| j                  N|j                  B| j                  |j                  kD  r)t        ddd|j                   d|j                   i      | j                  N|j                  B| j                  |j                  kD  r)t        ddd|j                   d|j                   i      | j                   N|j                   B| j                   |j                   kD  r)t        ddd|j                    d|j                   i      | j"                  `t%        |j"                        dkD  rH| j"                  D ]9  }	|	|j"                  vst        ddd|j"                   d|j&                   i       |j&                  cd}
| j(                  D ]  }|j&                  |j&                  k(  sd}
  |
du r0| j(                  j+                  t-        d|j&                               d}| j.                  t1        | j.                  t2              rt5        t7        j8                  | j.                        |j&                  xs ||j&                  xs |      }|j:                  j<                  j?                  i |j7                  d             d{   }|j@                  }tC        d+i | j7                         d|i}| jD                  iddl m#} |dur&tI        dtJ        jL                  jN                         |jP                  d| jD                  i|_(        n| jD                  |jP                  d<   |jR                  J ||jR                        }tU        jV                  tX        jZ                        t]        |      z   }||_/        |ja                  d      }|jc                  |       }|j:                  jd                  j?                  |d!di"       d{   }|j(                  D ]O  }|jg                  |j&                  |j&                  |j                  gd#d$d%|j                  gii&       d{    Q th        jj                  du r|j7                  d      }t7        j8                  |t        '      }tm        jn                   |tq        t        t        j                               tU        jV                  tX        jZ                        |xs |j&                  xs ||jr                  tt        jv                  | j                  d(|d)	      *             	 |ja                         S 7 z7 7 W7 # tx        $ r |j3                         cY S w xY ww),u   
    Allow users to create a new team. Apply user permissions to their team.

    👉 [Detailed Doc on setting team budgets](https://docs.litellm.ai/docs/proxy/team_budgets)


    Parameters:
    - team_alias: Optional[str] - User defined team alias
    - team_id: Optional[str] - The team id of the user. If none passed, we'll generate it.
    - members_with_roles: List[{"role": "admin" or "user", "user_id": "<user-id>"}] - A list of users and their roles in the team. Get user_id when making a new user via `/user/new`.
    - metadata: Optional[dict] - Metadata for team, store information for team. Example metadata = {"extra_info": "some info"}
    - tpm_limit: Optional[int] - The TPM (Tokens Per Minute) limit for this team - all keys with this team_id will have at max this TPM limit
    - rpm_limit: Optional[int] - The RPM (Requests Per Minute) limit for this team - all keys associated with this team_id will have at max this RPM limit
    - max_budget: Optional[float] - The maximum budget allocated to the team - all keys for this team_id will have at max this max_budget
    - budget_duration: Optional[str] - The duration of the budget for the team. Doc [here](https://docs.litellm.ai/docs/proxy/team_budgets)
    - models: Optional[list] - A list of models associated with the team - all keys for this team_id will have at most, these models. If empty, assumes all models are allowed.
    - blocked: bool - Flag indicating if the team is blocked or not - will stop all calls from keys with this team_id.
    - members: Optional[List] - Control team members via `/team/member/add` and `/team/member/delete`. 
    - tags: Optional[List[str]] - Tags for [tracking spend](https://litellm.vercel.app/docs/proxy/enterprise#tracking-spend-for-custom-tags) and/or doing [tag-based routing](https://litellm.vercel.app/docs/proxy/tag_routing).
    - organization_id: Optional[str] - The organization id of the team. Default is None. Create via `/organization/new`.
    - model_aliases: Optional[dict] - Model aliases for the team. [Docs](https://docs.litellm.ai/docs/proxy/team_based_routing#create-team-with-model-alias)

    Returns:
    - team_id: (str) Unique team id - used for tracking spend across multiple keys for same team id.

    _deprecated_params:
    - admins: list - A list of user_id's for the admin role
    - users: list - A list of user_id's for the user role

    Example Request:
    ```
    curl --location 'http://0.0.0.0:4000/team/new'     --header 'Authorization: Bearer sk-1234'     --header 'Content-Type: application/json'     --data '{
      "team_alias": "my-new-team_2",
      "members_with_roles": [{"role": "admin", "user_id": "user-1234"},
        {"role": "user", "user_id": "user-2434"}]
    }'

    ```

     ```
    curl --location 'http://0.0.0.0:4000/team/new'     --header 'Authorization: Bearer sk-1234'     --header 'Content-Type: application/json'     --data '{
                "team_alias": "QA Prod Bot", 
                "max_budget": 0.000000001, 
                "budget_duration": "1d"
            }'
    ```
    r   )create_audit_log_for_updateduration_in_secondslitellm_proxy_admin_namer:   N  errorNo db connectedstatus_codedetailteamfind_uniquer;   
table_name
query_type  z
Team id = z0 already exists. Please use a different team id.z/tpm limit higher than user max. User tpm limit=z. User role=z/rpm limit higher than user max. User rpm limit=z1max budget higher than user max. User max budget=z6Model not in allowed user models. User allowed models=z
. User id=FTadmin)roler5   model_aliases
created_by
updated_byexclude_nonemodel_idpremium_user*Only premium users can add tags to teams. rM   durationsecondsdb_datalitellm_model_table)rQ   r@   )r5   teamsrw   zpush )r5   rQ   update_key_values_custom_querydefaultcreated	id
updated_at
changed_bychanged_by_api_keyra   	object_idactionupdated_valuesbefore_valuerequest_datarA   )=litellm.proxy.proxy_serverrU   rV   rW   r:   r   r;   rC   uuiduuid4get_data	user_roler   PROXY_ADMIN	tpm_limit	rpm_limit
max_budgetmodelslenr5   r4   rG   r   rg   rB   dictr   jsondumpsrD   litellm_modeltablecreater}   r   rM   rn   
ValueErrorr   not_premium_uservaluemetadatabudget_durationr   nowr   utcr   budget_reset_atrH   jsonify_team_objectlitellm_teamtableupdate_datalitellmstore_audit_logsasynciocreate_taskr   api_keyr   TEAM_TABLE_NAME	Exception)rQ   rR   r0   rS   rU   rV   rW   r:   _existing_team_idmcreating_user_in_listr6   	_model_idr   
model_dictcomplete_team_datarn   
duration_sreset_atcomplete_team_data_dictteam_rowuser_updated_valuess                          r7   new_teamr   d   sW    J  W>O4PQQ||4::<( #0"8"8LLV #9 #
 
 (z$,,7gh  	##+&&*:*F*FF NN&!++7!2!<!<<NO`OjOjNkkw  yJ  yT  yT  xU  V  NN&!++7!2!<!<<NO`OjOjNkkw  yJ  yT  yT  xU  V  OO'!,,8"3">">>PQbQmQmPnnz  |M  |W  |W  {X  Y  ;;"s+<+C+C'Dq'H[[-444'$'#']^o^v^v]w  xB  CT  C\  C\  B]  &^   !   , %--F~~!2!:!::(,% . !E)##**G->-F-FG
 I%*T5G5G*N/**T%7%78(00L4L(00L4L

 )++>>EE:!&&D&9:
 

 MM	 + 
))+ yy;t#<=N=_=_=e=e<fg  &&.+1499*='26))''/ ))5(2D2T2TU
<<-	*0MM-5*0;;;N+??' @  )6(8(8(J(J(Q(Q$&- )R ) #H #55''LL!\\X5E5E4FGh../, ( 
 	
 	
 6 4',11t1D**_cB'.4::<('||HLL91  0(00 0/'8'@'@0@@"ll$#2!%	
$""$$}
`
F#	
H  }}s~   A.X0W*1FXA X/C!XW-EXW0AX5W36C#XW5 )X-X0X3X5XXXXrl   rW   c                 D  K   |}| j                   t        | j                   t              rt        t	        j
                  | j                         |j                  xs ||j                  xs |      }|A|j                  j                  j                  i |j	                  d             d{   }nX|j                  j                  j                  d|ii |j	                  d      i |j	                  d      d       d{   }|j                  }|S 7 k7 w)	z4
    Upsert model table and return the model id
    Nrf   Trj   rQ   r}   )updater   r?   rQ   )rg   rB   r   r   r   r   r5   rD   r   r   upsertr}   )rQ   rl   r:   r0   rW   r   r   r   s           r7   _update_model_tabler   Z  s)     I%*T5G5G*N/**T%7%78(00L4L(00L4L

 ,//BBIIC*//T/BC  J   J  -//BBIIX&L!3!8!8d!8!KLL!3!8!8d!8!KL  J   J MM	s%   B.D 0D1AD 	D
D D z/team/update)rM   rN   c                    K   ddl m} ddlm}m}m}m}m}	m}
 |t        dddi      | j                  t        d	dd
i      t        j                  d|        |j                  j                  j                  d| j                  i       d{   }|t        d	dd| j                   i      | j!                  d      }| j"                  H || j"                        }t%        j&                  t(        j*                        t-        |      z   }||d<   d|v r_|d   Zddlm} |dur&t1        dt2        j4                  j6                         |j9                  d      }d|v r|d   	||d   d<   nd|i|d<   d|v r:|j9                  d       t;        | |j<                  |||       d{   }|||d<   |j?                  |      }|j                  j                  jA                  d| j                  i|ddi       d{   }||j                  t        d	ddjC                  |      i       ||j                  tE        d%i |jG                         |
|	       d{    tH        jJ                  du r|j!                  d      }t!        jL                  |tN               }t!        jL                  |tN               }tQ        jR                   |tU        tO        tW        jX                               t%        j&                  t(        j*                        |xs |jZ                  xs ||j\                  t^        j`                  | j                  d!||"	      #             |j                  |d$S 7 7 7 s7 w)&a	  
    Use `/team/member_add` AND `/team/member/delete` to add/remove new team members  

    You can now update team budget / rate limits via /team/update

    Parameters:
    - team_id: str - The team id of the user. Required param.
    - team_alias: Optional[str] - User defined team alias
    - metadata: Optional[dict] - Metadata for team, store information for team. Example metadata = {"team": "core-infra", "app": "app2", "email": "ishaan@berri.ai" }
    - tpm_limit: Optional[int] - The TPM (Tokens Per Minute) limit for this team - all keys with this team_id will have at max this TPM limit
    - rpm_limit: Optional[int] - The RPM (Requests Per Minute) limit for this team - all keys associated with this team_id will have at max this RPM limit
    - max_budget: Optional[float] - The maximum budget allocated to the team - all keys for this team_id will have at max this max_budget
    - budget_duration: Optional[str] - The duration of the budget for the team. Doc [here](https://docs.litellm.ai/docs/proxy/team_budgets)
    - models: Optional[list] - A list of models associated with the team - all keys for this team_id will have at most, these models. If empty, assumes all models are allowed.
    - blocked: bool - Flag indicating if the team is blocked or not - will stop all calls from keys with this team_id.
    - tags: Optional[List[str]] - Tags for [tracking spend](https://litellm.vercel.app/docs/proxy/enterprise#tracking-spend-for-custom-tags) and/or doing [tag-based routing](https://litellm.vercel.app/docs/proxy/tag_routing).
    - organization_id: Optional[str] - The organization id of the team. Default is None. Create via `/organization/new`.
    - model_aliases: Optional[dict] - Model aliases for the team. [Docs](https://docs.litellm.ai/docs/proxy/team_based_routing#create-team-with-model-alias)

    Example - update team TPM Limit

    ```
    curl --location 'http://0.0.0.0:4000/team/update'     --header 'Authorization: Bearer sk-1234'     --header 'Content-Type: application/json'     --data-raw '{
        "team_id": "8d916b1c-510d-4894-a334-1c16a93344f5",
        "tpm_limit": 100
    }'
    ```

    Example - Update Team `max_budget` budget
    ```
    curl --location 'http://0.0.0.0:4000/team/update'     --header 'Authorization: Bearer sk-1234'     --header 'Content-Type: application/json'     --data-raw '{
        "team_id": "8d916b1c-510d-4894-a334-1c16a93344f5",
        "max_budget": 10
    }'
    ```
    r   )_cache_team_object)rU   rV   rW   r:   proxy_logging_objuser_api_key_cacheNrX   rY   rZ   r[   rc   No team id passed inz/team/update - %sr;   r?   Team not found, passed team_id=Trj   rp   rr   r   rM   rm   ro   r   rg   )rQ   rl   r:   r0   rW   rl   rt   rv   )r?   rQ   r@   zTeam doesn't exist. Got={})r;   
team_tabler   r   ry   updatedr|   r   )r;   rQ   rA   )1litellm.proxy.auth.auth_checksr   r   rU   rV   rW   r:   r   r   r   r;   r   debugrD   r   r_   r   r   r   r   r   r   r   rn   r   r   r   r   popr   rl   r   r   formatr   rH   r   r   r   rC   r   r   r   r   r   r5   r   r   r   )rQ   rR   r0   rS   r   rU   rV   rW   r:   r   r   existing_team_row
updated_kvr   r   rn   _tagsr   r   _before_value_after_values                        r7   update_teamr   ~  s    n B  W>O4PQQ||W>T4UVV2D9+..@@LL$,,' M    >t||nMN
 	

 -J '($2F2FG
<<-	*0MM )1
$% 
6 2 >;t#<=N=_=_=e=e<fg  v&#
:(>(J-2Jz"6*&,e_Jz"*$'-&//'/%=
 
	  %.Jz"22:2FJ0077dll+*D1 8 
 	
  8++39@@JK
 	

   -F0C0C0EF-+	   4')..D.A

=#> JJz3?'.4::<('||HLL91  0(00 0/'8'@'@0@@"ll$#/!.	
$  ''::{J
	
sL   BM>M2DM>.M5/AM>M8A M>&M;'DM>5M>8M>;M>r6   rn   c                 D   t        | t              r:| j                  dk(  r+|dur&t        dt        j
                  j                         y t        | t              rF| D ]@  }|j                  dk(  s|dust        d| dt        j
                  j                   d       y y )Nrd   Tz,Assigning team admins is a premium feature. z0Assigning team admins is a premium feature. Got=z. )rB   r   re   r   r   r   r   r   )r6   rn   r   s      r7   _check_team_member_admin_addr   &  s     &&!fkkW&<t#>?P?a?a?g?g>hi  $ 
FD	!Avv t+$J1#RPaPrPrPxPxOyy{|   
"r9   c                    | t        dddi      |j                  t        dddi      |j                  t        dddi      	 t        |j                  |       y # t        $ r}t        ddt        |      i      d }~ww xY w)	NrX   rY   rZ   r[   rc   r   zNo member/members passed in)r6   rn   )r   r;   r6   r   r   rC   )r:   rQ   rn   es       r7   team_call_validation_checksr   8  s    
 W>O4PQQ||W>T4UVV{{W.K$L
 	
G$;;%	
  GWc!f4EFFGs   	A! !	B*BB/team/member_addc                 	  K   ddl m}m}m}m}m} 	 t        || |       t        t        |      }t        | j                  ||d|dd       d{   }	|	t        dd	d
t        | dd       i      t        di |	j                         }
t        |d      r]|j                   t"        j$                  j&                  k7  r6t)        ||
      s)t        dd	dj+                  d|
j                        i      g }g }t-        | j.                  t0              r`	 t3        | j.                  | j4                  |||| j                         d{   \  }}|j;                  |       ||j;                  |       nt-        | j.                  t<              rg }| j.                  D ]X  }	 t3        || j4                  |||| j                         d{   \  }}|j;                  |       |H|j;                  |       Z t?        j@                  |  d{    t-        | j.                  t0              r| j.                  }|jB                  K|jD                  ?|D ]:  }|jD                  |jD                  |jD                  k(  s*|jB                  |_!        < |
jF                  j;                  |       nt-        | j.                  t<              r| j.                  }|D ][  }|jB                  |jD                  |D ]:  }|jD                  |jD                  |jD                  k(  s*|jB                  |_!        < ] |
jF                  jI                  |       |
jF                  D cg c]  }|j                          }}|jJ                  jL                  jO                  d| j                  idtQ        jR                  |      i       d{   }|t        dd	d| j                   di      tU        di |j                         ||dS # t        $ r}|d}~ww xY w7 7 # t6        $ rB}t        dd	dj+                  | j.                  | j                  t9        |            i      d}~ww xY w7 # t6        $ rB}t        dd	dj+                  | j.                  | j                  t9        |            i      d}~ww xY w7 c c}w 7 w)a  
    [BETA]

    Add new members (either via user_email or user_id) to a team

    If user doesn't exist, new user row will also be added to User Table

    Only proxy_admin or admin of team, allowed to access this endpoint.
    ```

    curl -X POST 'http://0.0.0.0:4000/team/member_add'     -H 'Authorization: Bearer sk-1234'     -H 'Content-Type: application/json'     -d '{"team_id": "45e3e396-ee08-4a61-a88e-16b3ce7e0849", "member": {"role": "user", "user_id": "krrish247652@berri.ai"}}'

    ```
    r   )rW   rn   r:   r   r   )r:   rQ   rn   NFT)r;   r:   r   parent_otel_spanr   check_cache_onlycheck_db_only  rY   zTeam not found for team_id=r;   r[   r   r0   r1     JCall not allowed. User not proxy admin OR team admin. route={}, team_id={}r   )
new_membermax_budget_in_teamr:   r0   rW   r;   rX   z6Unable to add user - {}, to team - {}, for reason - {}r4   r   zTeam with id z
 not found)updated_usersupdated_team_membershipsrA   )+r   rW   rn   r:   r   r   r   r   r	   r/   r+   r;   getattrr   rH   hasattrr   r   r   r   r8   r   rB   r6   r   r-   r   r   rC   rG   r   r   gatherr5   
user_emailr4   extendrD   r   r   r   r   r!   )rQ   rR   r0   rW   rn   r:   r   r   r   r   r   r   r   updated_user
updated_tmtasksr   r   r   new_membersnm_db_team_membersupdated_teams                          r7   team_member_addr   Q  s    : #'%	
 }5M-#-+   6wtYPT7U6VW
 	
 +L->-I-I-KL
 	!;/''+;+G+G+M+MM#/:L
 ell&&..
 	
 .0M=? $++v&	-;;;#'#:#:+"3)A. ($L*$ 	\*!$++J7	DKK	&A1? '+'>'>"/&7-E LL2 ,(j"   .%(//
;+ . nne$$$ $++v&[[
 %**?*?*K%OO/:+@+@@)-J& & 	--44Z@	DKK	&kkBzz!bmm&?)D2t"--7W%)\\
 *  	--44[A 1C0U0UV0U10UV&));;BB$,,'"DJJ/?$@A C  L Wdll^:.V$W
 	
 ! 

!
!
##!9 S  
X(  	U\\T\\3q6 	",  # #!Y!`!` KKs1v"  	%> Ws   SO> /SPCS2P PP AS(Q(Q%Q(S#(SR6AS S:A&S!S.S S>SR9/AS<R>=AS>	PP		PSP 	Q" =QQ""S%Q((	R31=R..R33S9S/team/member_deletec                   K   ddl m} |t        dddi      | j                  t        ddd	i      | j                  | j
                  t        ddd
i      |j                  j                  j                  d| j                  i       d{   }|(t        dddj                  | j                        i      t        di |j                         }|j                  t        j                  j                  k7  r6t!        ||      s)t        dddj                  d|j                        i      g }|j"                  D ]w  }| j                  &|j                  | j                  |j                  k(  r5| j
                  &|j
                  | j
                  |j
                  k(  rg|j%                  |       y ||_        |D cg c]  }|j                          }}|j                  j                  j'                  d| j                  idt)        j*                  |      i       d{   }	i }
| j                  | j                  |
d<   n| j
                  | j
                  |
d<   |j                  j,                  j/                  |
       d{   }|t1        |t2              rt5        |      dkD  r|D ]  }g }| j                  |j6                  v s|j6                  }|j9                  | j                         |j                  j,                  j'                  d|j                  idd|ii       d{     |S 7 c c}w 7 7 7 w)a  
    [BETA]

    delete members (either via user_email or user_id) from a team

    If user doesn't exist, an exception will be raised
    ```
    curl -X POST 'http://0.0.0.0:8000/team/member_delete' 
    -H 'Authorization: Bearer sk-1234' 
    -H 'Content-Type: application/json' 
    -d '{
        "team_id": "45e3e396-ee08-4a61-a88e-16b3ce7e0849",
        "user_id": "krrish247652@berri.ai"
    }'
    ```
    r   r:   NrX   rY   rZ   r[   rc   r   2Either user_id or user_email needs to be passed inr;   r   Team id={} does not exist in dbr   r   r   r   r4   r   r5   r   rw   setrA   )r   r:   r   r;   r5   r   rD   r   r_   r   r   rH   r   r   r   r   r8   r4   rG   r   r   r   litellm_usertablerF   rB   listr   rw   remove)rQ   rR   r0   r:   _existing_team_rowr   new_team_membersr   _db_new_team_members_key_valexisting_user_rowsexisting_user	team_lists                 r7   team_member_deleter     s_    < 9W>O4PQQ||W>T4UVV|| 7QR
 	

  -//AAMM$,,'  N    !>EEdllST
 	
 *L,>,I,I,KL
 	##'7'C'C'I'II#/:K
 ell)+<+D+D
 	
 &(11LL$		%		)OO'(1<</" 2 ,<(@P'Q@P1@P'Q0077t||
 #DJJ/C$DE	 8  	A G||!\\			$ $,//AAKK  L    %%t,5G1H11L/MI||}222)//	  .#&&88??!=#8#8 "E9#56	 @    0 c\ (R	s_   BMMD7M	M AM-M.A&MMAMA!M:M;	MMMMz/team/member_updatec                 N  K   ddl m} |t        dddi      | j                  t        ddd	i      | j                  | j
                  t        ddd
i      |j                  j                  j                  d| j                  i       d{   }|(t        dddj                  | j                        i      t        di |j                         }|j                  t        j                  j                  k7  r6t!        ||      s)t        dddj                  d|j                        i      t#        || j                  |       d{   }d}| j                  | j                  }nT| j
                  H|d   j$                  D ]6  }|j
                  |j
                  | j
                  k(  s*|j                  } n |t        dddj                  |       i      d}	|d   D ]  }
|
j                  |k(  s|
j&                  }	 n |	|j                  j(                  j+                  | j,                  |j                  xs d|j                  xs dd       d{   }|j                  j.                  j+                  | j                  ||j&                  d       d{    n=|j                  j(                  j1                  d|	id| j,                  i       d{    t3        | j                  || j
                  | j,                        S 7 7 7 7 w7 ;w)z0
    [BETA]

    Update team member budgets
    r   r   NrX   rY   rZ   r[   rc   r   r   r;   r   r   r   r   r   r   )rR   r;   r0   	team_infoz,User id doesn't exist in team table. Data={}rI    )r   rh   ri   r   )r;   r5   	budget_idr  r   r   )r;   r5   r   r   rA   )r   r:   r   r;   r5   r   rD   r   r_   r   r   rH   r   r   r   r   r8   r  r4   r  litellm_budgettabler   r   rE   r   r'   )rQ   rR   r0   r:   r   r   returned_team_inforeceived_user_idr6   identified_budget_idrK   
new_budgets               r7   team_member_updater	    sX    " 9W>O4PQQ||W>T4UVV|| 7QR
 	

  -//AAMM$,,'  N    !>EEdllST
 	
 *L,>,I,I,KL
 	##'7'C'C'I'II#/:K
 ell)+<+D+D
 	
 8A!+8 2 '+||<<		$(5HHF  ,1B1Bdoo1U#)>>  I
 GNNtT
 	
 +/ !34::))#%<<  5 #(++??FF"55/77=2/77=2 G 
 

 55<<<<+'11 = 
 	
 	
 2299 45 7 78 : 
 	
 	

 $ ??22	 c82@
	
	
sq   BL%LB?L%LA	L%L%6AL%?A$L%#L$AL%)L!*=L%'L#(2L%L%L%!L%#L%z/team/deletec                 r  K   ddl m}m}m} |t	        dddi      | j
                  t	        ddd	i      | j
                  D ]2  }|j                  |d
d       d{   }|"t	        ddd| i       t        j                  du r| j
                  D ]  }|j                  |d
d       d{   }|"|j                  d      }	t        j                   |t        t        t        j                               t!        j"                  t$        j&                        |xs |j(                  xs ||j*                  t,        j.                  |dd|		                    |j1                  | j
                  d       d{    |j1                  | j
                  d
       d{   }
|
S 7 O7 7 07 w)a  
    delete team and associated team keys

    Parameters:
    - team_ids: List[str] - Required. List of team IDs to delete. Example: ["team-1234", "team-5678"]

    ```
    curl --location 'http://0.0.0.0:4000/team/delete'     --header 'Authorization: Bearer sk-1234'     --header 'Content-Type: application/json'     --data-raw '{
        "team_ids": ["8d916b1c-510d-4894-a334-1c16a93344f5"]
    }'
    ```
    r   )rU   rW   r:   NrX   rY   rZ   r[   rc   r   r^   r_   r`   r   r   Trj   deletedz{}r|   r   key)team_id_listra   )r   rU   rW   r:   r   team_idsr   r   r   r   r   r   r   rC   r   r   r   r   r   r   r5   r   r   r   delete_data)rQ   rR   r0   rS   rU   rW   r:   r;   r   	_team_rowdeleted_teamss              r7   delete_teamr    s    8  W>O4PQQ}}W>T4UVV ==&//= 0 
 
 #B7)!LM  ! 4'}}G:G:P:PF} ;Q ; 5H  48I+!2tzz|,#+<<#=#5 $4,44$43+<+D+D#4#D#D")('+%." %> 
#
#5
#
QQQ'33]]v 4  M c
5< RsP   AF7F. F7'AF72F13CF7F3$F7'F5(F71F73F75F7z
/team/infoz!Team ID in the request parameters)rz   rP   c                   K   ddl m} 	 |t        t        j                  ddi      |t        t        j
                  ddi      |j                  t        j                  j                  k(  s'|j                  t        j                  j                  k(  rnP|j                  ||j                  k7  r5t        t        j                  d	j                  |j                  |            |j                  |d
d       d{   }|!t        t        j                  dd| di      |j                  |ddt!        j"                                d{   }|g }|d}|D ]  }|t%        |dd      z  } d|i}|D ]%  }	 |j'                         }|j-                  dd       ' t/        ||gd       d{   }	t1        |t*              rt3        di |}
n4t1        |t4              rt3        di |j'                         }
n
t3               }
t7        ||
||	      }|S 7 7 # t(        $ r |j+                         }Y w xY w7 # t(        $ r}t9        j:                  dj                  |t=        j>                                      t1        |t              rYtA        t%        |ddtC        |       d      tD        jF                  t%        |dd      t%        |dt        jH                              t1        |t@              r|tA        dtC        |      z   tD        jF                  t%        |dd      t        jH                        d}~ww xY ww) a#  
    get info on team + related keys

    Parameters:
    - team_id: str - Required. The unique identifier of the team to get info on.

    ```
    curl --location 'http://localhost:4000/team/info?team_id=your_team_id_here'     --header 'Authorization: Bearer your_api_key_here'
    ```
    r   r   NrY   zDatabase not connected. Connect a database to your proxy - https://docs.litellm.ai/docs/simple_proxy#managing-auth---virtual-keysr[   messagez(Malformed request. No team id passed in.zPkey not allowed to access this team's info. Key team_id={}, Requested team_id={}r^   r_   r`   z Team not found, passed team id: .r  find_all)r;   ra   rb   expiresspendtokenr5   )r;   r  keysrI   z\litellm.proxy.management_endpoints.team_endpoints.py::team_info - Exception occurred - {}
{}r]   zAuthentication Error()paramNoner\   )r  typer  codezAuthentication Error, rA   )%r   r:   r   r   HTTP_500_INTERNAL_SERVER_ERRORHTTP_422_UNPROCESSABLE_ENTITYr   r   r   r   PROXY_ADMIN_VIEW_ONLYr;   HTTP_403_FORBIDDENr   r   HTTP_404_NOT_FOUNDr   r   r   rH   r   r   r   rL   rB   r   r   r"   r   rY   	traceback
format_excr    rC   r   
auth_errorHTTP_400_BAD_REQUEST)rR   r;   r0   r:   r  r  r  kr  rJ   
_team_inforesponse_objectr   s                r7   r  r  b  s\    , 9l
 "AA  a  ?"@@!#MN  ''+;+G+G+M+MM **55;;< &&.(000"55ipp%--w   ((F} )   	
 "55!%EgYa#PQ  #++!LLN	 , 
 
 <DEGQ//  %(I C!nn& GGGT"  5G9d
 
 i&*7Y7J	9-*DY-A-A-CDJ*,J0 (	
 o
*  !hhj!
&  
""krr9'')	

 a' 8/DSVHA-NO$//a&1Qv/J/JK	  >*G,s1v5 ++!Wf-,,	
 	

s   MC4I  >H?AI  H,I  >H&I  4H>5A$I  MI  I  H;8I  :H;;I   	M	C4L==MMz/team/blockc                    K   ddl m} |t        d      |j                  j                  j                  d| j                  iddi       d{   }|t        d	d
d| j                   i      |S 7 $w)a  
    Blocks all calls from keys with this team id.

    Parameters:
    - team_id: str - Required. The unique identifier of the team to block.

    Example:
    ```
    curl --location 'http://0.0.0.0:4000/team/block'     --header 'Authorization: Bearer sk-1234'     --header 'Content-Type: application/json'     --data '{
        "team_id": "team-1234"
    }'
    ```

    Returns:
    - The updated team record with blocked=True



    r   r   NNo DB Connected.r;   blockedTr   r   rY   r   r[   r   r:   r   rD   r   r   r;   r   rQ   rR   r0   r:   records        r7   
block_teamr3    s     > 9*++ ##55<<$,,'y$.? =  F ~>t||nMN
 	

 M   AA5A3%A5z/team/unblockc                    K   ddl m} |t        d      |j                  j                  j                  d| j                  iddi       d{   }|t        d	d
d| j                   i      |S 7 $w)ay  
    Blocks all calls from keys with this team id.

    Parameters:
    - team_id: str - Required. The unique identifier of the team to unblock.

    Example:
    ```
    curl --location 'http://0.0.0.0:4000/team/unblock'     --header 'Authorization: Bearer sk-1234'     --header 'Content-Type: application/json'     --data '{
        "team_id": "team-1234"
    }'
    ```
    r   r   Nr.  r;   r/  Fr   r   rY   r   r[   r0  r1  s        r7   unblock_teamr6    s     2 9*++ ##55<<$,,'y%.@ =  F ~>t||nMN
 	

 Mr4  z
/team/listz1Only return teams which this 'user_id' belongs toc           
      v  K   ddl m} t        ||      s(t        dddj	                  |j
                        i      |'t        d	dt        j                  j                  i      |j                  j                  j                          d{   }g }|rK|D ]E  }|j                  s|j                  D ]'  }d
|v s|d
   |d
   |k(  s|j                  |       ) G n|}|D cg c]  }|j                   }}t        |||       d{   }	g }
|D ]  }g }|	D ]-  }|j                  |j                  k(  s|j                  |       / |j                  j                   j                  d|j                  i       d{   }	 |
j                  t#        di |j%                         ||d        |
j/                  d        |
S 7 ?c c}w 7 7 S# t&        $ rT}dj	                  |j                  |j%                         t)        |            }t+        j,                  |       Y d}~d}~ww xY ww)z
    ```
    curl --location --request GET 'http://0.0.0.0:4000/team/list'         --header 'Authorization: Bearer sk-1234'
    ```

    Parameters:
    - user_id: str - Optional. If passed will only return teams that the user_id is a member of.
    r   r   )r0   requested_user_idi  rY   zCOnly admin users can query all teams/other teams. Your user role={}r[   Nrc   r5   r  r;   r   )rI   r  zWInvalid team object for team_id: {}. team_object={}.
            Error: {}
            c                 $    t        | dd      xs dS )N
team_aliasr  )r   )xs    r7   <lambda>zlist_team.<locals>.<lambda>  s    71lB+G+M2+Mr9   )r  rA   )r   r:   r*   r   r   r   r   db_not_connected_errorr   rD   r   rF   r4   rG   r;   rL   litellm_verificationtokenr#   rH   r   rC   r   	exceptionsort)rR   r5   r0   r:   responsefiltered_responser^   r6   	_team_idsrJ   returned_responses_team_membershipsrK   r  r   team_exceptions                   r7   	list_teamrG  E  sP    ( 9++w ^ee%//
 	
 .EEKKL
 	

 #%%77AACCHD&&"55F!V+"9-9"9-8)006 6  %*;<*;$*;I<0y' K 8:!:<BzzT\\)!((, 
 #%%??IIdll+ J 
 
	%%& oo'%6 "8  NOi D" =
  	doo/Q 
 !**>:	s   BH9GH9)H9=H9H9H9(G;H9G+H9;AH9GH9	-G6H9H9H9	H6"A	H1+H91H66H9)N)Q__doc__r   r   r&  r   r   r   r   typingr   r   r   r	   fastapir
   r   r   r   r   r   pydanticr   r   litellm._loggingr   litellm.proxy._typesr   r   r   r   r   r   r   r   r   r   r   r   r   r   r    r!   r"   r#   r$   r%   r&   r'   r(   r)   r   r*   r+   $litellm.proxy.auth.user_api_key_authr,   &litellm.proxy.management_helpers.utilsr-   r.   litellm.proxy.utilsr/   routerboolr8   rC   rL   postr   r   r   r   r   r   r   r	  r  getQueryr  r3  r6  rG  rA   r9   r7   <module>rV     s  	     2 2 . .  N N   1      4 C -	%1B	 OS*.s)>Fsm	
 !2 
	+,-$	    )00A(B(. t)	l
ll &l !	l l^!
!sm!  ! &	!
 "! c]!H +,GDU<V;W    )00A(B(. t)	a;
a;a; &a; !	a; a;H&$v,&'$GL)G
G G2 
	+,-(	    )00A(Bq
qq &q qh 
	+,-  
  )00A(Bw
!ww &w wt 
	+,-+	    )00A(Bn
!nn &n nb +,GDU<V;W    )00A(B(. t)	W
WW &W !	W Wt )*'BS:T9U    !7=="E )00A(B@
@
@

 &@
 @
F *+7CT;U:V    )00A(B*
** &* *Z ,-WEV=W<X    )00A(B$
$$ &$ $N )*'BS:T9U    +W]]"U )00A(BXXc]X
 &X Xr9   