diff --git a/src/documents/models.py b/src/documents/models.py index 4578800..1a8ec83 100644 --- a/src/documents/models.py +++ b/src/documents/models.py @@ -11,33 +11,36 @@ from src.core.models import StrategyName class DocumentResponse(BaseModel): """Returned after upload or GET.""" - id: str filename: str - paragraph_count: int + paragraph_count: int = 0 chunk_counts: dict[str, int] = Field(default_factory=dict) created_at: str class DocumentDetailResponse(DocumentResponse): """Full document detail including tree and text preview.""" - parsed_text_preview: str # first 500 chars document_tree: dict # JSON-serialised DocumentTree class ProcessRequest(BaseModel): """Body for POST /documents/{id}/process.""" - strategies: list[StrategyName] = Field( - description="Which chunking strategies to run", + default=[ + StrategyName.RECURSIVE, + StrategyName.FIXED_SIZE, + StrategyName.SEMANTIC, + StrategyName.CONTEXTUAL_RETRIEVAL, + StrategyName.SEMANTIC_PARENT_CHILD, + ], + description="Which chunking strategies to run (defaults to all 5)", min_length=1, ) class StrategyResult(BaseModel): """Outcome for a single strategy in a processing run.""" - strategy: StrategyName status: str # "completed" | "failed" chunks_produced: int = 0 @@ -46,7 +49,6 @@ class StrategyResult(BaseModel): class ProcessResponse(BaseModel): """Returned after processing a document with selected strategies.""" - document_id: str strategies_completed: list[StrategyResult] strategies_failed: list[StrategyResult] @@ -54,11 +56,18 @@ class ProcessResponse(BaseModel): class DeleteResponse(BaseModel): """Returned after deleting a document.""" - deleted: bool document_id: str +class DocumentListResponse(BaseModel): + """Returned when listing documents.""" + items: list[DocumentResponse] + total: int + offset: int + limit: int + + # ── Strategies list ──────────────────────────────────────────────── class StrategyInfo(BaseModel): diff --git a/src/documents/routes.py b/src/documents/routes.py index 1425c77..d76b5c9 100644 --- a/src/documents/routes.py +++ b/src/documents/routes.py @@ -14,6 +14,7 @@ from src.core.models import PaginatedResponse, StrategyName from src.documents.models import ( DeleteResponse, DocumentResponse, + DocumentListResponse, ProcessRequest, ProcessResponse, StrategiesResponse, @@ -24,6 +25,18 @@ from src.documents import service router = APIRouter() +@router.get("/documents", response_model=DocumentListResponse) +async def list_documents(offset: int = 0, limit: int = 50): + """List all uploaded documents with pagination.""" + result = service.list_documents(offset=offset, limit=limit) + return DocumentListResponse( + items=[DocumentResponse(**doc) for doc in result["items"]], + total=result["total"], + offset=result["offset"], + limit=result["limit"], + ) + + @router.post("/documents", response_model=DocumentResponse, status_code=201) async def upload_document(file: UploadFile = File(...)): """Upload a .docx file. Parses it, stores the document tree in SQLite.""" diff --git a/src/documents/service.py b/src/documents/service.py index 4e98033..2f7fc3b 100644 --- a/src/documents/service.py +++ b/src/documents/service.py @@ -141,6 +141,13 @@ def delete_document(doc_id: str) -> bool: return db.delete_document(doc_id) +# ── List documents ──────────────────────────────────────────────── + +def list_documents(*, offset: int = 0, limit: int = 50) -> dict[str, Any]: + """List documents with pagination.""" + return db.list_documents(offset=offset, limit=limit) + + # ── List strategies ──────────────────────────────────────────────── def list_strategies() -> list[dict[str, str]]: