"""Pydantic schemas for the Unified Search plugin.""" from __future__ import annotations from typing import Any from pydantic import BaseModel, Field # ─── Search ─── class SearchRequest(BaseModel): query: str = Field(..., min_length=1, max_length=500) entity_types: list[str] | None = None limit: int = Field(default=20, ge=1, le=100) offset: int = Field(default=0, ge=0) date_from: str | None = Field( default=None, description="ISO date (YYYY-MM-DD) — filter by created_at/updated_at >= date_from" ) date_to: str | None = Field( default=None, description="ISO date (YYYY-MM-DD) — filter by created_at/updated_at <= date_to" ) tags: list[str] | None = Field( default=None, description="Filter results by tags (comma-separated on entities)" ) sort: str = Field( default="relevance", description="Sort order: relevance, date, name", ) class SearchResult(BaseModel): entity_type: str entity_id: str title: str snippet: str score: float data: dict[str, Any] = Field(default_factory=dict) class SearchResponse(BaseModel): query: str normalized_query: str results: list[SearchResult] facets: dict[str, Any] summary: str suggestions: list[str] class FacetsResponse(BaseModel): """Available facets for search filtering.""" entity_types: list[str] tags: list[str] date_ranges: dict[str, Any] # ─── Similar ─── class SimilarRequest(BaseModel): entity_type: str entity_id: str limit: int = Field(default=5, ge=1, le=50) class SimilarResponse(BaseModel): similar: dict[str, list[SearchResult]] # ─── Suggest ─── class SuggestRequest(BaseModel): q: str = Field(..., min_length=1, max_length=200) limit: int = Field(default=10, ge=1, le=50) class SuggestResponse(BaseModel): suggestions: list[str] # ─── Reindex ─── class ReindexRequest(BaseModel): entity_types: list[str] = Field(default_factory=list) include_chunks: bool = Field(default=True, description="Re-index document chunks for files") # ─── Provider ─── class ProviderResponse(BaseModel): entity_type: str plugin_name: str is_active: bool supports_fts: bool = True supports_vector: bool = True supports_rag: bool = False supports_graph: bool = False