| """ |
| Knowledge Search API Hardened - Secure RAG and keyword search. |
| Enforces authentication for all knowledge retrieval operations. |
| """ |
|
|
| from fastapi import APIRouter, Depends, HTTPException |
|
|
| from src.server.api_routes.knowledge.schemas import RagQueryRequest |
| from src.server.config.logfire_config import safe_logfire_error |
| from src.server.services.search.rag_service import RAGService |
| from src.server.utils import get_supabase_client |
|
|
| from ...auth.dependencies import requires_permission |
| from ...auth.permissions import TASK_READ_OWN |
|
|
| router = APIRouter() |
|
|
|
|
| @router.post("/knowledge-items/search") |
| async def search_knowledge_items( |
| request: RagQueryRequest, current_user: dict = Depends(requires_permission(TASK_READ_OWN)) |
| ): |
| """Search for relevant knowledge items using vector similarity. Requires TASK_READ_OWN.""" |
| try: |
| service = RAGService(get_supabase_client()) |
| metadata_filter = {"source_id": request.source_ids[0]} if request.source_ids else None |
| return await service.search_documents( |
| query=request.query, match_count=request.limit, filter_metadata=metadata_filter |
| ) |
| except Exception as e: |
| safe_logfire_error(f"Failed to search knowledge items | error={str(e)}") |
| raise HTTPException(status_code=500, detail=str(e)) from e |
|
|
|
|
| @router.post("/rag/query") |
| async def perform_rag_query(request: RagQueryRequest, current_user: dict = Depends(requires_permission(TASK_READ_OWN))): |
| """Perform a full RAG query combining retrieval and generation. Requires TASK_READ_OWN.""" |
| try: |
| service = RAGService(get_supabase_client()) |
| success, result = await service.perform_rag_query( |
| query=request.query, source=request.source_ids[0] if request.source_ids else None, match_count=request.limit |
| ) |
| if success: |
| return {**result, "success": True} |
| raise HTTPException(status_code=500, detail=str(result.get("error"))) |
| except Exception as e: |
| safe_logfire_error(f"Failed to perform RAG query | error={str(e)}") |
| raise HTTPException(status_code=500, detail=str(e)) from e |
|
|
|
|
| @router.post("/rag/code-examples") |
| async def search_code_examples( |
| request: RagQueryRequest, current_user: dict = Depends(requires_permission(TASK_READ_OWN)) |
| ): |
| """Search specifically for code examples within the knowledge base. Requires TASK_READ_OWN.""" |
| try: |
| service = RAGService(get_supabase_client()) |
| success, result = await service.search_code_examples_service( |
| query=request.query, |
| source_id=request.source_ids[0] if request.source_ids else None, |
| match_count=request.limit, |
| ) |
| if success: |
| return result |
| raise HTTPException(status_code=500, detail=str(result.get("error"))) |
| except Exception as e: |
| safe_logfire_error(f"Failed to search code examples | error={str(e)}") |
| raise HTTPException(status_code=500, detail=str(e)) from e |
|
|
|
|
| @router.post("/code-examples") |
| async def search_code_examples_simple( |
| request: RagQueryRequest, current_user: dict = Depends(requires_permission(TASK_READ_OWN)) |
| ): |
| """Backward compatible alias for searching code examples. Requires TASK_READ_OWN.""" |
| service = RAGService(get_supabase_client()) |
| success, result = await service.search_code_examples_service( |
| query=request.query, source_id=request.source_ids[0] if request.source_ids else None, match_count=request.limit |
| ) |
| if success: |
| return result |
| raise HTTPException(status_code=500, detail=str(result.get("error"))) |
|
|