From bd3a175452aeb267d85e5a4ff99fe6f118568257 Mon Sep 17 00:00:00 2001 From: cthomas Date: Tue, 18 Feb 2025 16:49:07 -0800 Subject: [PATCH] feat: add list identities route (#1046) same as #1005 --- letta/server/rest_api/routers/v1/__init__.py | 2 ++ .../server/rest_api/routers/v1/identities.py | 35 +++++++++++++++++++ letta/server/server.py | 2 ++ letta/services/identity_manager.py | 29 +++++++++++++++ 4 files changed, 68 insertions(+) create mode 100644 letta/server/rest_api/routers/v1/identities.py diff --git a/letta/server/rest_api/routers/v1/__init__.py b/letta/server/rest_api/routers/v1/__init__.py index 6a683ac8..9f14ff9f 100644 --- a/letta/server/rest_api/routers/v1/__init__.py +++ b/letta/server/rest_api/routers/v1/__init__.py @@ -1,6 +1,7 @@ from letta.server.rest_api.routers.v1.agents import router as agents_router from letta.server.rest_api.routers.v1.blocks import router as blocks_router from letta.server.rest_api.routers.v1.health import router as health_router +from letta.server.rest_api.routers.v1.identities import router as identities_router from letta.server.rest_api.routers.v1.jobs import router as jobs_router from letta.server.rest_api.routers.v1.llms import router as llm_router from letta.server.rest_api.routers.v1.providers import router as providers_router @@ -15,6 +16,7 @@ ROUTERS = [ tools_router, sources_router, agents_router, + identities_router, llm_router, blocks_router, jobs_router, diff --git a/letta/server/rest_api/routers/v1/identities.py b/letta/server/rest_api/routers/v1/identities.py new file mode 100644 index 00000000..5646e7b2 --- /dev/null +++ b/letta/server/rest_api/routers/v1/identities.py @@ -0,0 +1,35 @@ +from typing import TYPE_CHECKING, List, Optional + +from fastapi import APIRouter, Depends, HTTPException, Query + +from letta.schemas.identity import Identity, IdentityType +from letta.server.rest_api.utils import get_letta_server + +if TYPE_CHECKING: + from letta.server.server import SyncServer + +router = APIRouter(prefix="/identities", tags=["identities"]) + + +@router.get("/", tags=["identities"], response_model=List[Identity], operation_id="list_identities") +def list_identities( + name: Optional[str] = Query(None), + project_id: Optional[str] = Query(None), + identity_type: Optional[IdentityType] = Query(None), + before: Optional[str] = Query(None), + after: Optional[str] = Query(None), + limit: Optional[int] = Query(50), + server: "SyncServer" = Depends(get_letta_server), +): + """ + Get a list of all identities in the database + """ + try: + identities = server.identity_manager.list_identities( + name=name, project_id=project_id, identity_type=identity_type, before=before, after=after, limit=limit + ) + except HTTPException: + raise + except Exception as e: + raise HTTPException(status_code=500, detail=f"{e}") + return identities diff --git a/letta/server/server.py b/letta/server/server.py index 38fe4626..7864dcd0 100644 --- a/letta/server/server.py +++ b/letta/server/server.py @@ -71,6 +71,7 @@ from letta.server.rest_api.interface import StreamingServerInterface from letta.server.rest_api.utils import sse_async_generator from letta.services.agent_manager import AgentManager from letta.services.block_manager import BlockManager +from letta.services.identity_manager import IdentityManager from letta.services.job_manager import JobManager from letta.services.message_manager import MessageManager from letta.services.organization_manager import OrganizationManager @@ -195,6 +196,7 @@ class SyncServer(Server): self.agent_manager = AgentManager() self.provider_manager = ProviderManager() self.step_manager = StepManager() + self.identity_manager = IdentityManager() # Managers that interface with parallelism self.per_agent_lock_manager = PerAgentLockManager() diff --git a/letta/services/identity_manager.py b/letta/services/identity_manager.py index 9d996db7..bf237419 100644 --- a/letta/services/identity_manager.py +++ b/letta/services/identity_manager.py @@ -1,5 +1,8 @@ +from typing import Optional + from letta.orm.identity import Identity as IdentityModel from letta.schemas.identity import Identity as PydanticIdentity +from letta.schemas.identity import IdentityType from letta.utils import enforce_types @@ -10,6 +13,32 @@ class IdentityManager: self.session_maker = db_context + @enforce_types + def list_identities( + self, + name: Optional[str] = None, + project_id: Optional[str] = None, + identity_type: Optional[IdentityType] = None, + before: Optional[str] = None, + after: Optional[str] = None, + limit: Optional[int] = 50, + ) -> list[PydanticIdentity]: + with self.session_maker() as session: + filters = {"organization_id": actor.organization_id} + if project_id: + filters["project_id"] = project_id + if identity_type: + filters["identity_type"] = identity_type + identities = IdentityModel.list( + db_session=session, + query_text=name, + before=before, + after=after, + limit=limit, + **filters, + ) + return [identity.to_pydantic() for identity in identities] + @enforce_types def get_identity_from_identifier_key(self, identifier_key: str) -> PydanticIdentity: with self.session_maker() as session: