Spaces:
Sleeping
Sleeping
| """Document service: lifecycle operations.""" | |
| import shutil | |
| from uuid import UUID | |
| from pathlib import Path | |
| from typing import Optional | |
| from sqlalchemy.ext.asyncio import AsyncSession | |
| from app.core.paths import documents_dir | |
| from app.database.repositories import documents as doc_repo | |
| async def create_document( | |
| session: AsyncSession, | |
| *, | |
| filename: str, | |
| original_filename: str, | |
| file_size_bytes: Optional[int] = None, | |
| doc_kind: str = "paper", | |
| ) -> dict: | |
| """Create a document record.""" | |
| return await doc_repo.create_document( | |
| session, | |
| filename=filename, | |
| original_filename=original_filename, | |
| file_size_bytes=file_size_bytes, | |
| doc_kind=doc_kind, | |
| ) | |
| async def get_document(session: AsyncSession, document_id: UUID) -> Optional[dict]: | |
| """Get a document by ID.""" | |
| return await doc_repo.get_document(session, document_id) | |
| async def list_documents(session: AsyncSession, limit: int = 50, offset: int = 0) -> list[dict]: | |
| """List all documents.""" | |
| return await doc_repo.list_documents(session, limit=limit, offset=offset) | |
| async def count_documents(session: AsyncSession) -> int: | |
| """Total number of documents in the library (across all pages).""" | |
| return await doc_repo.count_documents(session) | |
| async def delete_document(session: AsyncSession, document_id: UUID) -> Optional[dict]: | |
| """Delete a document row (cascades to chunks, embeddings, assets, turns). | |
| Returns the deleted document's metadata so the caller can clean up | |
| on-disk artefacts (raw PDFs, MinerU output, extracted images). Returns | |
| ``None`` if the document does not exist. | |
| """ | |
| doc = await doc_repo.get_document(session, document_id) | |
| if not doc: | |
| return None | |
| deleted = await doc_repo.delete_document(session, document_id) | |
| return doc if deleted else None | |