feat(proxy): return tpm_limit and rpm_limit from /v2/user/info

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
mrinal 2026-10-01 22:40:16 +00:00
parent 8baee043d5
commit 0f0ffe5cd3
5 changed files with 25 additions and 8 deletions

View file

@ -3534,6 +3534,8 @@ class UserInfoV2Response(LiteLLMPydanticObjectBase):
user_role: str | None = None
spend: float = 0.0
max_budget: float | None = None
tpm_limit: int | None = None
rpm_limit: int | None = None
models: list[str] = []
budget_duration: str | None = None
budget_reset_at: datetime | None = None

View file

@ -1147,6 +1147,8 @@ async def user_info_v2(
user_role=user_data.get("user_role"),
spend=user_data.get("spend", 0.0),
max_budget=user_data.get("max_budget"),
tpm_limit=user_data.get("tpm_limit"),
rpm_limit=user_data.get("rpm_limit"),
models=user_data.get("models") or [],
budget_duration=user_data.get("budget_duration"),
budget_reset_at=user_data.get("budget_reset_at"),

View file

@ -3062,7 +3062,7 @@ async def test_user_update_rejects_silent_create_for_non_proxy_admin(mocker):
@pytest.mark.asyncio
async def test_user_info_v2_proxy_admin_can_query_any_user(mocker):
async def test_user_info_v2_proxy_admin_can_query_any_user(mocker: MockerFixture) -> None:
"""
Test that proxy admin can query any user via /v2/user/info.
"""
@ -3071,9 +3071,9 @@ async def test_user_info_v2_proxy_admin_can_query_any_user(mocker):
from litellm.proxy._types import UserInfoV2Response
from litellm.proxy.management_endpoints.internal_user_endpoints import user_info_v2
mock_prisma_client = mocker.MagicMock()
mock_prisma_client: Final = mocker.MagicMock()
mock_user_row = mocker.MagicMock()
mock_user_row: Final = mocker.MagicMock()
mock_user_row.model_dump.return_value = {
"user_id": "target-user-123",
"user_email": "target@example.com",
@ -3081,6 +3081,8 @@ async def test_user_info_v2_proxy_admin_can_query_any_user(mocker):
"user_role": "internal_user",
"spend": 42.5,
"max_budget": 100.0,
"tpm_limit": 100000,
"rpm_limit": 1000,
"models": ["gpt-4"],
"budget_duration": "30d",
"budget_reset_at": None,
@ -3091,8 +3093,9 @@ async def test_user_info_v2_proxy_admin_can_query_any_user(mocker):
"teams": ["team-1", "team-2"],
}
async def mock_find_unique(*args, **kwargs):
if kwargs.get("where", {}).get("user_id") == "target-user-123":
async def mock_find_unique(*_args: object, **kwargs: object) -> MagicMock | None:
where: Final = kwargs.get("where")
if isinstance(where, Mapping) and where.get("user_id") == "target-user-123":
return mock_user_row
return None
@ -3100,11 +3103,11 @@ async def test_user_info_v2_proxy_admin_can_query_any_user(mocker):
mocker.patch("litellm.proxy.proxy_server.prisma_client", mock_prisma_client)
mock_request = mocker.MagicMock(spec=Request)
mock_request: Final = mocker.MagicMock(spec=Request)
admin_key = UserAPIKeyAuth(user_id="admin-user", user_role=LitellmUserRoles.PROXY_ADMIN)
admin_key: Final = UserAPIKeyAuth(user_id="admin-user", user_role=LitellmUserRoles.PROXY_ADMIN)
response = await user_info_v2(
response: Final = await user_info_v2(
request=mock_request,
user_id="target-user-123",
user_api_key_dict=admin_key,
@ -3117,6 +3120,8 @@ async def test_user_info_v2_proxy_admin_can_query_any_user(mocker):
assert response.user_role == "internal_user"
assert response.spend == 42.5
assert response.max_budget == 100.0
assert response.tpm_limit == 100000
assert response.rpm_limit == 1000
assert response.models == ["gpt-4"]
assert response.teams == ["team-1", "team-2"]
assert response.sso_user_id == "sso-abc"
@ -3447,6 +3452,8 @@ async def test_user_info_v2_response_shape(mocker):
"user_role",
"spend",
"max_budget",
"tpm_limit",
"rpm_limit",
"models",
"budget_duration",
"budget_reset_at",

View file

@ -1093,6 +1093,8 @@ export interface UserInfoV2Response {
user_role: string | null;
spend: number;
max_budget: number | null;
tpm_limit?: number | null;
rpm_limit?: number | null;
models: string[];
budget_duration: string | null;
budget_reset_at: string | null;

View file

@ -47691,6 +47691,8 @@ export interface components {
*/
models: string[];
object_permission?: components["schemas"]["LiteLLM_ObjectPermissionTable"] | null;
/** Rpm Limit */
rpm_limit?: number | null;
/**
* Spend
* @default 0
@ -47703,6 +47705,8 @@ export interface components {
* @default []
*/
teams: string[];
/** Tpm Limit */
tpm_limit?: number | null;
/** Updated At */
updated_at?: string | null;
/** User Alias */