""" LibBee /agent endpoint - thin FastAPI router. The pipeline itself lives in ``src/agentcore`` split by stage: models.py Stage 0 Pydantic I/O contracts constants.py regexes, URLs, prompts (no logic) utils.py shared helpers, LLM factory, URL builders classify.py Stage 2-3 rule pre-classifier + LLM intent classifier libcal.py live hours/events via Cloudflare Worker proxy scholarly.py Semantic Scholar / OpenAlex / Crossref / Unpaywall rendering.py HTML fragments (badges, trace, AI-tools footer) intents_library.py Stage 4 library_info handlers intents_search.py Stage 4 search_academic / search_medical machinery intents_general.py Stage 4 general / social handlers orchestrator.py Stage 1+4 injection gate, routing pipeline, D1 logging This file only wires HTTP to the orchestrator. """ import time from fastapi import APIRouter, Request from src.agentcore.models import AgentRequest, AgentResponse from src.agentcore.orchestrator import _agent_query_inner, _log_agent_query from src.agentcore.utils import ( _get_runtime_config, _normalize_whitespace, _safe_metrics_increment, _sanitize_llm_response, ) from src.services.staff_service import STAFF_DIRECTORY router = APIRouter() @router.post("", response_model=AgentResponse) async def agent_query(request: Request, req: AgentRequest): start_time = time.time() question = _normalize_whitespace(req.question) history = req.history model = req.model client_state = req.client_state _safe_metrics_increment("agent_requests") response = await _agent_query_inner(question, history, model, client_state, start_time) response.answer = _sanitize_llm_response(response.answer) _log_agent_query(question, response, start_time) _rcfg = _get_runtime_config() _ann = _rcfg.get("announcement", "").strip() if _ann and response.intent not in ("social_greeting", "social"): _ann_html = ( '
' f'📢 {_ann}
' ) response.answer = response.answer + _ann_html return response @router.get("/test") async def test(): return { "status": "ok", "message": "Agent endpoint is working!", "staff_loaded": len(STAFF_DIRECTORY), } @router.get("/rag-status") async def rag_status(): try: from app import get_rag_service return get_rag_service().get_stats() except Exception as e: return {"error": str(e), "ready": False}