mirror of
https://github.com/tiennm99/litellm.git
synced 2026-08-10 22:24:51 +00:00
[Fix] Include created_at and updated_at in /project/list response
The /project/list endpoint was not returning created_at and updated_at timestamps because these fields were not defined in LiteLLM_ProjectTable. Added these fields to the model so FastAPI includes them in the response (values come from the database). This allows the UI to display project creation and last-updated times. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Haiku 4.5
parent
88c465b5ef
commit
8bb6457471
@@ -2665,6 +2665,8 @@ class LiteLLM_ProjectTable(LiteLLMPydanticObjectBase):
|
||||
object_permission_id: Optional[str] = None
|
||||
created_by: str
|
||||
updated_by: str
|
||||
created_at: Optional[datetime] = None
|
||||
updated_at: Optional[datetime] = None
|
||||
litellm_budget_table: Optional[LiteLLM_BudgetTable] = None
|
||||
object_permission: Optional[LiteLLM_ObjectPermissionTable] = None
|
||||
|
||||
|
||||
@@ -791,3 +791,78 @@ def test_litellm_entity_type_has_project():
|
||||
|
||||
assert hasattr(Litellm_EntityType, "PROJECT")
|
||||
assert Litellm_EntityType.PROJECT.value == "project"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_list_projects_returns_timestamps():
|
||||
"""
|
||||
Test that /project/list returns created_at and updated_at for each project.
|
||||
"""
|
||||
from datetime import datetime, timezone
|
||||
from unittest.mock import AsyncMock, MagicMock, patch
|
||||
|
||||
from litellm.proxy.management_endpoints.project_endpoints import list_projects
|
||||
from litellm.proxy._types import LiteLLM_ProjectTable
|
||||
|
||||
now = datetime(2024, 1, 15, 12, 0, 0, tzinfo=timezone.utc)
|
||||
|
||||
# Build a fake DB row that includes created_at and updated_at
|
||||
fake_project = MagicMock()
|
||||
fake_project.model_dump.return_value = {
|
||||
"project_id": "proj-1",
|
||||
"project_alias": "test-project",
|
||||
"team_id": "team-1",
|
||||
"created_by": "admin",
|
||||
"updated_by": "admin",
|
||||
"created_at": now,
|
||||
"updated_at": now,
|
||||
"models": [],
|
||||
"spend": 0.0,
|
||||
"blocked": False,
|
||||
"budget_id": None,
|
||||
"description": None,
|
||||
"metadata": None,
|
||||
"model_spend": None,
|
||||
"model_rpm_limit": None,
|
||||
"model_tpm_limit": None,
|
||||
"object_permission_id": None,
|
||||
"litellm_budget_table": None,
|
||||
"object_permission": None,
|
||||
}
|
||||
# Make the fake row behave like a Pydantic model for FastAPI serialization
|
||||
fake_project.project_id = "proj-1"
|
||||
fake_project.created_at = now
|
||||
fake_project.updated_at = now
|
||||
|
||||
mock_prisma = MagicMock()
|
||||
mock_prisma.db.litellm_projecttable.find_many = AsyncMock(
|
||||
return_value=[fake_project]
|
||||
)
|
||||
|
||||
with patch(
|
||||
"litellm.proxy.proxy_server.prisma_client", mock_prisma
|
||||
):
|
||||
response = await list_projects(
|
||||
user_api_key_dict=UserAPIKeyAuth(
|
||||
user_role=LitellmUserRoles.PROXY_ADMIN,
|
||||
api_key="sk-1234",
|
||||
user_id="1234",
|
||||
),
|
||||
)
|
||||
|
||||
assert len(response) == 1
|
||||
project = response[0]
|
||||
assert project.created_at == now
|
||||
assert project.updated_at == now
|
||||
|
||||
|
||||
def test_litellm_project_table_has_timestamp_fields():
|
||||
"""
|
||||
Test that LiteLLM_ProjectTable model includes created_at and updated_at fields,
|
||||
so the /project/list response_model exposes them.
|
||||
"""
|
||||
from litellm.proxy._types import LiteLLM_ProjectTable
|
||||
|
||||
fields = LiteLLM_ProjectTable.model_fields
|
||||
assert "created_at" in fields, "LiteLLM_ProjectTable must have created_at field"
|
||||
assert "updated_at" in fields, "LiteLLM_ProjectTable must have updated_at field"
|
||||
|
||||
Reference in New Issue
Block a user