from __future__ import annotations from .shared import * from .helpers import _resolve_tenant_id from .. import rag_ask_contract from ...services.ai_pmo.ai_pmo_kernel import AIPMOKernelService @router.post("/ask") async def rag_ask( request: RAGAskRequest, current_user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db), tenant_id: int = Depends(get_tenant_id), ): service = AIPMOKernelService( db, tenant_id=rag_ask_contract.resolve_effective_tenant_id(current_user, tenant_id), ) ingress_result = await service.process_ingress( **rag_ask_contract.build_kernel_ingress_kwargs( request=request, current_user=current_user, ) ) if not bool(ingress_result.get("handled")): raise HTTPException( status_code=400, detail=str(ingress_result.get("reason") or "ai_pmo_kernel_not_handled"), ) return success_response( rag_ask_contract.build_rag_response_payload(ingress_result=ingress_result), ) @router.get("/manifest") async def rag_manifest( project_id: int | None = Query(default=None), current_user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db), tenant_id: int = Depends(get_tenant_id), ): service = AdaptiveRAGService(db, tenant_id=_resolve_tenant_id(current_user, tenant_id)) data = await service.get_project_manifest(project_id=project_id) return success_response(data) @router.get("/features/catalog") async def rag_feature_catalog( query: str | None = Query(default=None), limit: int = Query(default=20, ge=1, le=200), current_user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db), tenant_id: int = Depends(get_tenant_id), ): service = AdaptiveRAGService(db, tenant_id=_resolve_tenant_id(current_user, tenant_id)) data = await service.get_feature_catalog(query=query, limit=limit) return success_response(data) @router.post("/entity-resolution") async def rag_entity_resolution( request: EntityResolutionRequest, current_user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db), tenant_id: int = Depends(get_tenant_id), ): service = AdaptiveRAGService(db, tenant_id=_resolve_tenant_id(current_user, tenant_id)) data = await service.entity_resolution( question=request.question, project_id=request.project_id, limit=request.limit, ) return success_response(data) @router.post("/multi-step-search") async def rag_multi_step_search( request: MultiStepSearchRequest, current_user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db), tenant_id: int = Depends(get_tenant_id), ): service = AdaptiveRAGService(db, tenant_id=_resolve_tenant_id(current_user, tenant_id)) data = await service.multi_step_search( question=request.question, project_id=request.project_id, source_chat_id=request.source_chat_id, session_state=None, ) return success_response(data) @router.post("/symbols/sync") async def rag_symbols_sync( request: SymbolSyncRequest, current_user: User = Depends(require_roles("ADMIN", "BOSS")), db: AsyncSession = Depends(get_db), tenant_id: int = Depends(get_tenant_id), ): service = SymbolIndexService(db, tenant_id=_resolve_tenant_id(current_user, tenant_id)) data = await service.sync_codebase_symbols( base_dir=request.base_dir, max_files=request.max_files, force_reindex=request.force_reindex, ) return success_response(data) @router.post("/symbols/search") async def rag_symbols_search( request: SymbolSearchRequest, current_user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db), tenant_id: int = Depends(get_tenant_id), ): service = SymbolIndexService(db, tenant_id=_resolve_tenant_id(current_user, tenant_id)) data = await service.search_symbols( query=request.query, language=request.language, symbol_type=request.symbol_type, limit=request.limit, ) return success_response(data) @router.get("/symbols/overview") async def rag_symbols_overview( current_user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db), tenant_id: int = Depends(get_tenant_id), ): service = SymbolIndexService(db, tenant_id=_resolve_tenant_id(current_user, tenant_id)) data = await service.get_overview(top_n_files=10, auto_sync_if_empty=False) return success_response(data) @router.get("/symbols/{symbol_id}") async def rag_symbol_detail( symbol_id: int, current_user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db), tenant_id: int = Depends(get_tenant_id), ): service = SymbolIndexService(db, tenant_id=_resolve_tenant_id(current_user, tenant_id)) try: data = await service.get_symbol_detail(symbol_id=symbol_id) except ValueError as exc: raise HTTPException(status_code=404, detail=str(exc)) from exc return success_response(data)