feat(documents): add GET /documents endpoint and improve models

Why:
- Need to list documents to get document IDs for queries
- ProcessRequest should default to all 5 strategies
- paragraph_count should be optional (not always stored)

Changes:
- Added GET /documents endpoint with pagination
- Added DocumentListResponse model
- ProcessRequest now defaults to all 5 strategies
- DocumentResponse.paragraph_count now defaults to 0
This commit is contained in:
2026-07-26 12:06:14 +03:30
parent 496a58c62a
commit cbaa72b420
3 changed files with 37 additions and 8 deletions

View File

@@ -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):

View File

@@ -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."""

View File

@@ -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]]: