Girish Jeswani
add document auth
625853d
Raw
History Blame Contribute Delete
10.6 kB
from fastapi import APIRouter, Request, HTTPException, Depends
from app.core.session_manager import get_session_manager
from app.api.utils import get_or_create_session_for_request_async
from app.core.auth import get_current_active_user
from app.models.user import User
from pydantic import BaseModel
from typing import Optional
import logging
logger = logging.getLogger(__name__)
router = APIRouter()
session_manager = get_session_manager()
class ResetSessionRequest(BaseModel):
chat_session_id: Optional[str] = None
force_new: bool = False
@router.get("/context")
async def get_context(
request: Request,
chat_session_id: Optional[str] = None,
current_user: User = Depends(get_current_active_user)
):
"""
Get context for current session - ENHANCED with document access fix
Now properly handles different chat sessions and ensures document access
"""
try:
# Determine which session to get context for with consistent session ID format
if chat_session_id:
# Getting context for a specific chat session - use consistent format
session_id = f"chat_{chat_session_id}"
logger.info(f"Getting context for specific chat session: {session_id}")
# Ensure session is loaded in memory
if session_id not in session_manager.sessions:
logger.info(f"Chat session {session_id} not in memory, loading from database")
loaded_session_id = await get_or_create_session_for_request_async(
request,
chat_session_id=chat_session_id,
user_id=str(current_user.id)
)
session_id = loaded_session_id
logger.info(f"Loaded session ID: {session_id}")
else:
# Getting context for current session
session_id = await get_or_create_session_for_request_async(request)
logger.info(f"Getting context for current session: {session_id}")
session = session_manager.get_session(session_id)
rag_stats = session.get_rag_stats()
# Enhanced logging for document access debugging
logger.info(f"Retrieved context for session {session_id}:")
logger.info(f" - Messages: {len(session.messages)}")
logger.info(f" - Documents: {rag_stats.get('total_documents', 0)}")
logger.info(f" - Chunks: {rag_stats.get('total_chunks', 0)}")
logger.info(f" - Uploaded files: {len(session.uploaded_files)}")
# Log document details if available
if rag_stats.get('documents'):
for doc in rag_stats['documents']:
logger.info(f" - Available document: {doc.get('filename', 'unknown')} ({doc.get('chunks', 0)} chunks)")
# Include session debugging info in response
context_response = {
"session_id": session_id,
"chat_session_id": chat_session_id,
"messages": session.messages,
"rag_info": {
"total_documents": rag_stats.get("total_documents", 0),
"total_chunks": rag_stats.get("total_chunks", 0),
"documents": rag_stats.get("documents", [])
},
"context_stats": {
"message_count": len(session.messages),
"user_messages": len([m for m in session.messages if m.get('role') == 'user']),
"uploaded_files": session.uploaded_files,
"total_upload_size": session.total_upload_size,
"created_at": session.created_at.isoformat(),
"last_accessed": session.last_accessed.isoformat()
},
# Add debugging info
"debug_info": {
"session_format": "chat_session" if chat_session_id else "new_session",
"session_in_memory": session_id in session_manager.sessions,
"document_access_working": rag_stats.get("total_documents", 0) > 0
}
}
return context_response
except Exception as e:
logger.error(f"Error getting context for session_id {session_id if 'session_id' in locals() else 'unknown'}: {str(e)}")
logger.error(f"Chat session ID: {chat_session_id}")
import traceback
logger.error(f"Full traceback: {traceback.format_exc()}")
return {
"session_id": session_id if 'session_id' in locals() else None,
"chat_session_id": chat_session_id,
"messages": [],
"rag_info": {"total_documents": 0, "total_chunks": 0, "documents": []},
"context_stats": {
"message_count": 0,
"user_messages": 0,
"uploaded_files": [],
"total_upload_size": 0
},
"error": str(e),
"debug_info": {
"error_occurred": True,
"error_type": type(e).__name__
}
}
@router.post("/reset-session")
async def reset_session(
reset_request: ResetSessionRequest,
request: Request,
current_user: User = Depends(get_current_active_user)
):
"""
Reset session - ENHANCED
Now properly handles different reset scenarios
"""
try:
if reset_request.force_new:
# Force create a completely new session
session_id = session_manager.create_session()
session = session_manager.get_session(session_id)
session.clear_all_data()
logger.info(f"Force created new session: {session_id}")
return {
"status": "reset",
"message": "New session created with fresh context",
"session_id": session_id,
"chat_session_id": None
}
elif reset_request.chat_session_id:
# Reset a specific chat session context
session_id = f"chat_{reset_request.chat_session_id}"
if session_id in session_manager.sessions:
success = session_manager.reset_session_completely(session_id)
message = "Chat session context reset successfully" if success else "Failed to reset chat session context"
else:
# Create fresh context for this chat
session = session_manager.get_session(session_id)
session.clear_all_data()
success = True
message = "Fresh context created for chat session"
logger.info(f"Reset chat session {reset_request.chat_session_id}, memory session: {session_id}")
return {
"status": "reset" if success else "error",
"message": message,
"session_id": session_id,
"chat_session_id": reset_request.chat_session_id
}
else:
# Reset current session
session_id = await get_or_create_session_for_request_async(request)
success = session_manager.reset_session_completely(session_id)
logger.info(f"Reset current session: {session_id}")
return {
"status": "reset" if success else "error",
"message": "Current session reset successfully" if success else "Failed to reset current session",
"session_id": session_id
}
except Exception as e:
logger.error(f"Error resetting session: {e}")
return {"status": "error", "message": f"Failed to reset session: {str(e)}"}
@router.get("/session-stats")
async def get_session_stats(
request: Request,
chat_session_id: Optional[str] = None,
current_user: User = Depends(get_current_active_user)
):
"""
Get session statistics - ENHANCED
Now provides detailed stats for different session types
"""
try:
if chat_session_id:
# Stats for specific chat session
session_id = f"chat_{chat_session_id}"
else:
# Stats for current session
session_id = await get_or_create_session_for_request_async(request)
stats = session_manager.get_session_stats(session_id)
# Add additional context
stats["session_type"] = "chat_session" if chat_session_id else "current_session"
stats["chat_session_id"] = chat_session_id
return stats
except Exception as e:
logger.error(f"Error getting session stats: {str(e)}")
return {"error": str(e)}
@router.get("/active-sessions")
async def get_active_sessions(current_user: User = Depends(get_current_active_user)):
"""
Get all active sessions for debugging
"""
try:
active_count = session_manager.get_active_session_count()
# Get overview of sessions (don't return full content for privacy)
session_overview = {}
for session_id, session in session_manager.sessions.items():
session_overview[session_id] = {
"message_count": len(session.messages),
"uploaded_files": len(session.uploaded_files),
"created_at": session.created_at.isoformat(),
"last_accessed": session.last_accessed.isoformat(),
"is_chat_session": session_id.startswith("chat_")
}
return {
"active_session_count": active_count,
"sessions": session_overview
}
except Exception as e:
logger.error(f"Error getting active sessions: {str(e)}")
return {"error": str(e)}
@router.post("/cleanup-sessions")
async def cleanup_expired_sessions(current_user: User = Depends(get_current_active_user)):
"""
Manually trigger session cleanup
"""
try:
initial_count = session_manager.get_active_session_count()
# Force cleanup
session_manager._cleanup_expired_sessions()
final_count = session_manager.get_active_session_count()
cleaned_count = initial_count - final_count
return {
"status": "success",
"message": f"Cleaned up {cleaned_count} expired sessions",
"sessions_before": initial_count,
"sessions_after": final_count
}
except Exception as e:
logger.error(f"Error during session cleanup: {str(e)}")
return {"status": "error", "message": str(e)}