"""Admin view over every user's sessions."""
from typing import Annotated
from fastapi import Depends, HTTPException
from navi.api.deps import get_session_store, require_admin
from navi.auth import User
from navi.config import settings
from navi.core import SessionStore
from ._router import router
@router.get("/sessions")
async def admin_list_sessions(
store: Annotated[SessionStore, Depends(get_session_store)],
user: Annotated[User, Depends(require_admin)],
limit: int = 50,
offset: int = 0,
search: str | None = None,
sort_by: str = "last_active",
sort_order: str = "desc",
):
"""Return all sessions across all users with pagination, search and sorting."""
sessions = await store.search_list(
limit=limit,
offset=offset,
user_id=user.id,
is_admin=True,
search=search or None,
sort_by=sort_by,
sort_order=sort_order,
)
total = await store.count_all(user_id=user.id, is_admin=True, search=search or None)
return {
"total": total,
"limit": limit,
"offset": offset,
"items": [
{
"session_id": s.id,
"profile_id": s.profile_id,
"user_id": s.user_id,
"name": s.name,
"message_count": s.display_count,
"pinned": s.pinned,
"created_at": s.created_at.isoformat(),
"last_active": s.last_active.isoformat(),
}
for s in sessions
],
}
@router.get("/sessions/{session_id}")
async def admin_get_session(
session_id: str,
store: Annotated[SessionStore, Depends(get_session_store)],
user: Annotated[User, Depends(require_admin)],
) -> dict:
"""Return full session details including messages."""
session = await store.get(session_id)
if session is None:
raise HTTPException(status_code=404, detail="Session not found")
return {
"session_id": session.id,
"profile_id": session.profile_id,
"user_id": session.user_id,
"name": session.name,
"messages": [m.model_dump(mode="json", exclude_none=True) for m in session.messages],
"context_token_count": session.context_token_count,
"max_context_tokens": settings.ollama_num_ctx,
"pinned": session.pinned,
"created_at": session.created_at.isoformat(),
"last_active": session.last_active.isoformat(),
}
@router.delete("/sessions/{session_id}", status_code=204)
async def admin_delete_session(
session_id: str,
store: Annotated[SessionStore, Depends(get_session_store)],
user: Annotated[User, Depends(require_admin)],
) -> None:
"""Delete any session (bypass ownership)."""
from navi.session_files import delete_session_dir
deleted = await store.delete(session_id)
if not deleted:
raise HTTPException(status_code=404, detail="Session not found")
await delete_session_dir(session_id)