"""Pydantic schemas for the kommunikation plugin API.""" from __future__ import annotations import uuid from datetime import datetime from typing import Any from pydantic import BaseModel, Field # ─── Conversation Schemas ─── class ParticipantResponse(BaseModel): id: str conversation_id: str participant_id: str | None = None participant_type: str display_name: str | None = None role: str joined_at: str | None = None class ConversationCreate(BaseModel): title: str | None = None participant_ids: list[str] = Field(default_factory=list) participant_types: list[str] = Field(default_factory=lambda: ["user"]) initial_message: str | None = None is_direct: bool = False class ConversationUpdate(BaseModel): title: str | None = None is_archived: bool | None = None class ConversationResponse(BaseModel): id: str title: str | None = None is_locked: bool = False locked_by: str | None = None is_direct: bool = False is_archived: bool = False is_pinned: bool = False created_by: str | None = None created_by_type: str = "user" last_msg_at: str | None = None last_msg_preview: str | None = None last_msg_sender_type: str | None = None participants: list[ParticipantResponse] = Field(default_factory=list) unread_count: int = 0 metadata: dict[str, Any] = Field(default_factory=dict) class ConversationListResponse(BaseModel): items: list[ConversationResponse] total: int # ─── Participant Management ─── class ParticipantAdd(BaseModel): participant_id: str participant_type: str = "user" role: str = "member" class ParticipantRoleUpdate(BaseModel): role: str = Field(..., pattern="^(admin|member|reader)$") # ─── Message Schemas ─── class MessageBlockCreate(BaseModel): block_type: str block_data: dict[str, Any] class MessageBlockResponse(BaseModel): id: str block_type: str block_data: dict[str, Any] sort_order: int = 0 class AttachmentCreate(BaseModel): file_id: str | None = None file_source: str = "comm" class AttachmentResponse(BaseModel): id: str file_id: str | None = None file_source: str = "comm" file_name: str file_type: str file_size: int | None = None thumbnail_path: str | None = None class MessageCreate(BaseModel): content: str = "" content_format: str = "text" blocks: list[MessageBlockCreate] = Field(default_factory=list) reply_to_id: str | None = None attachments: list[AttachmentCreate] = Field(default_factory=list) class MessageUpdate(BaseModel): content: str | None = None read: bool | None = None class MessageResponse(BaseModel): id: str conversation_id: str sender_id: str | None = None sender_type: str content: str = "" content_format: str = "text" metadata: dict[str, Any] = Field(default_factory=dict) reply_to_id: str | None = None is_pinned: bool = False created_at: str | None = None edited_at: str | None = None blocks: list[MessageBlockResponse] = Field(default_factory=list) attachments: list[AttachmentResponse] = Field(default_factory=list) reactions: list[dict[str, Any]] = Field(default_factory=list) class MessageListResponse(BaseModel): items: list[MessageResponse] total: int page: int = 1 has_more: bool = False # ─── Reaction Schemas ─── class ReactionCreate(BaseModel): emoji: str class ReactionResponse(BaseModel): id: str message_id: str user_id: str emoji: str # ─── Read State ─── class ReadStateUpdate(BaseModel): last_read_msg_id: str | None = None # ─── Mini-App Schemas ─── class MiniAppResponse(BaseModel): app_id: str name: str icon: str description: str plugin_name: str render_schema: dict[str, Any] = Field(default_factory=dict) class MiniAppStartRequest(BaseModel): app_id: str config: dict[str, Any] = Field(default_factory=dict) # ─── WebSocket Message Schemas ─── class WSMessage(BaseModel): type: str data: dict[str, Any] = Field(default_factory=dict)