"""Pydantic schemas for the AI Assistant plugin.""" from __future__ import annotations from datetime import datetime from typing import Any from pydantic import BaseModel, ConfigDict, Field # ─── Providers ─── class AIProviderCreate(BaseModel): name: str = Field(..., min_length=1, max_length=100) provider_type: str = Field(..., min_length=1, max_length=50) api_key: str = Field(default="", max_length=2000) base_url: str = Field(default="", max_length=500) is_active: bool = True is_default: bool = False config: dict[str, Any] = Field(default_factory=dict) class AIProviderUpdate(BaseModel): name: str | None = Field(None, min_length=1, max_length=100) provider_type: str | None = Field(None, min_length=1, max_length=50) api_key: str | None = Field(None, max_length=2000) base_url: str | None = Field(None, max_length=500) is_active: bool | None = None is_default: bool | None = None config: dict[str, Any] | None = None class AIProviderResponse(BaseModel): model_config = ConfigDict(from_attributes=True) id: str name: str provider_type: str api_key: str # masked in routes base_url: str is_active: bool is_default: bool config: dict[str, Any] created_at: datetime | None = None updated_at: datetime | None = None # ─── Models ─── class AIModelCreate(BaseModel): provider_id: str model_id: str = Field(..., min_length=1, max_length=200) display_name: str = Field(..., min_length=1, max_length=200) context_window: int = Field(default=4096, ge=1) supports_tools: bool = False supports_streaming: bool = True is_active: bool = True config: dict[str, Any] = Field(default_factory=dict) class AIModelUpdate(BaseModel): model_id: str | None = Field(None, min_length=1, max_length=200) display_name: str | None = Field(None, min_length=1, max_length=200) context_window: int | None = Field(None, ge=1) supports_tools: bool | None = None supports_streaming: bool | None = None is_active: bool | None = None config: dict[str, Any] | None = None class AIModelResponse(BaseModel): model_config = ConfigDict(from_attributes=True) id: str provider_id: str model_id: str display_name: str context_window: int supports_tools: bool supports_streaming: bool is_active: bool config: dict[str, Any] # ─── Presets ─── class AIPresetCreate(BaseModel): name: str = Field(..., min_length=1, max_length=100) model_id: str = Field(..., min_length=1, max_length=200) provider_id: str | None = None temperature: float = Field(default=0.7, ge=0.0, le=2.0) max_tokens: int = Field(default=2048, ge=1, le=128000) top_p: float = Field(default=1.0, ge=0.0, le=1.0) system_prompt: str = "" config: dict[str, Any] = Field(default_factory=dict) is_active: bool = True class AIPresetUpdate(BaseModel): name: str | None = Field(None, min_length=1, max_length=100) model_id: str | None = Field(None, min_length=1, max_length=200) provider_id: str | None = None temperature: float | None = Field(None, ge=0.0, le=2.0) max_tokens: int | None = Field(None, ge=1, le=128000) top_p: float | None = Field(None, ge=0.0, le=1.0) system_prompt: str | None = None config: dict[str, Any] | None = None is_active: bool | None = None class AIPresetResponse(BaseModel): model_config = ConfigDict(from_attributes=True) id: str name: str model_id: str provider_id: str | None = None temperature: float max_tokens: int top_p: float system_prompt: str config: dict[str, Any] is_active: bool # ─── Agents ─── class AIAgentCreate(BaseModel): name: str = Field(..., min_length=1, max_length=100) description: str = "" system_prompt: str = "" preset_id: str | None = None tool_ids: list[str] = Field(default_factory=list) is_active: bool = True config: dict[str, Any] = Field(default_factory=dict) class AIAgentUpdate(BaseModel): name: str | None = Field(None, min_length=1, max_length=100) description: str | None = None system_prompt: str | None = None preset_id: str | None = None tool_ids: list[str] | None = None is_active: bool | None = None config: dict[str, Any] | None = None class AIAgentResponse(BaseModel): model_config = ConfigDict(from_attributes=True) id: str name: str description: str system_prompt: str preset_id: str | None = None tool_ids: list[str] is_default: bool is_active: bool config: dict[str, Any] created_at: datetime | None = None updated_at: datetime | None = None # ─── Chat Sessions ─── class ChatSessionCreate(BaseModel): title: str = Field(default="Neuer Chat", max_length=255) agent_id: str | None = None is_sidebar: bool = False class ChatSessionUpdate(BaseModel): title: str | None = Field(None, max_length=255) is_pinned: bool | None = None agent_id: str | None = None folder_id: str | None = None class ChatSessionResponse(BaseModel): model_config = ConfigDict(from_attributes=True) id: str user_id: str agent_id: str | None = None title: str is_pinned: bool is_sidebar: bool folder_id: str | None = None created_at: datetime | None = None updated_at: datetime | None = None # ─── Chat Messages ─── class ChatMessageResponse(BaseModel): model_config = ConfigDict(from_attributes=True) id: str session_id: str role: str content: str tool_calls: list[dict[str, Any]] | None = None tool_results: list[dict[str, Any]] | None = None tokens: int model_used: str created_at: datetime | None = None class ChatSendRequest(BaseModel): content: str = Field(..., min_length=1) agent_id: str | None = None # override session agent # ─── Folders ─── class ChatFolderCreate(BaseModel): name: str = Field(..., min_length=1, max_length=255) parent_id: str | None = None class ChatFolderUpdate(BaseModel): name: str | None = Field(None, min_length=1, max_length=255) parent_id: str | None = None class ChatFolderResponse(BaseModel): model_config = ConfigDict(from_attributes=True) id: str name: str parent_id: str | None = None user_id: str created_at: datetime | None = None # ─── Attachments ─── class ChatAttachmentResponse(BaseModel): model_config = ConfigDict(from_attributes=True) id: str message_id: str | None = None session_id: str filename: str mime_type: str size_bytes: int # ─── Tools ─── class AIToolResponse(BaseModel): name: str description: str parameters: dict[str, Any] plugin_name: str required_permission: str | None = None category: str