"""Reference document upload (scrub + ingest into the REFERENCE tier).""" from __future__ import annotations import shutil import tempfile from pathlib import Path from fastapi import APIRouter, Depends, HTTPException, UploadFile, status from backend.api.deps import get_current_tenant from backend.config import settings def _upload_temp_dir() -> Path: from backend.utils.runtime_paths import ensure_data_drive_runtime_dirs ensure_data_drive_runtime_dirs() d = settings.data_dir_path / "tmp" / "uploads" d.mkdir(parents=True, exist_ok=True) return d from backend.core import ingest router = APIRouter(prefix="/api/upload", tags=["upload"]) _ALLOWED = {".pdf", ".docx", ".docm", ".doc"} @router.post("/reference", status_code=status.HTTP_201_CREATED) async def upload_reference( file: UploadFile, tenant_id: str = Depends(get_current_tenant), ) -> dict: """Scrub and ingest a past report as style reference. Never structural.""" suffix = Path(file.filename or "").suffix.lower() if suffix not in _ALLOWED: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail=f"Unsupported file type '{suffix}'. Allowed: {sorted(_ALLOWED)}", ) tmp_dir = Path(tempfile.mkdtemp(prefix="rics_v2_ref_", dir=str(_upload_temp_dir()))) safe_name = Path(file.filename or f"upload{suffix}").name tmp_path = tmp_dir / safe_name try: content = await file.read() if not content: raise HTTPException(status_code=400, detail="Empty upload body") tmp_path.write_bytes(content) chunks = ingest.ingest_reference(tenant_id, tmp_path) finally: shutil.rmtree(tmp_dir, ignore_errors=True) return {"ingested_chunks": chunks, "filename": file.filename, "tier": "reference"} @router.get("/reference/status") def reference_status(tenant_id: str = Depends(get_current_tenant)) -> dict: """Summarise ingested past reports for the demo UI.""" from backend.core.rag_store import TIER_REFERENCE, get_rag_store store = get_rag_store() count = store.count(tenant_id, TIER_REFERENCE) return { "reference_chunk_count": count, "reference_documents": store.list_source_filenames(tenant_id, TIER_REFERENCE), "ready_for_generation": count > 0, }