"""Модели Pydantic для описания `config/plugins.yaml` и его загрузчика.""" from pathlib import Path from typing import Any, Literal import yaml from pydantic import BaseModel, Field class TranscriberConfig(BaseModel): """Конфигурация активного плагина transcriber.""" enabled: bool = True provider: str = Field(default="null", min_length=1) model: str | None = None language: str = "ru" options: dict[str, Any] = Field(default_factory=dict) class SummarizerConfig(BaseModel): """Конфигурация активного плагина summarizer.""" enabled: bool = True provider: str = Field(default="null", min_length=1) model: str | None = None chunk_minutes: int = 20 options: dict[str, Any] = Field(default_factory=dict) class ChatConfig(BaseModel): """Конфигурация переключателя функции чата.""" enabled: bool = True class PluginsConfig(BaseModel): """Корневая модель конфигурации для `config/plugins.yaml`.""" transcriber: TranscriberConfig = Field(default_factory=TranscriberConfig) summarizer: SummarizerConfig = Field(default_factory=SummarizerConfig) chat: ChatConfig = Field(default_factory=ChatConfig) def load_plugins_config(path: str | Path) -> PluginsConfig: """Загрузить и валидировать `PluginsConfig` из YAML файла.""" raw = yaml.safe_load(Path(path).read_text()) or {} return PluginsConfig.model_validate(raw) # --- Настройки инстанса: БД поверх дефолтов `plugins.yaml`. --- # Ключи `instance_settings` зеркалят секции ниже (`transcriber`, `summarizer`, # `chat`, `ai_level`, `summary_recipients`, `display_timezone`) — см. # `services/instance_settings.py`. AiLevel = Literal["min", "medium", "max"] """Уровень AI-модуля инстанса (модели/требования — ADR-004, `docs/architecture/adr/004-ai-tier-matrix.md`, `services/ai_tiers.TIERS`). Доступность каждого уровня на конкретном инстансе зависит от обнаруженного железа и скачанных моделей — см. `services/ai_levels.py::detect_ai_levels`.""" SummaryRecipientsMode = Literal["all", "owner"] """Режим рассылки саммари по умолчанию: всем участникам либо только владельцу конференции (переопределяется на уровне `conferences.summary_recipients`).""" class InstanceConfig(BaseModel): """Эффективная конфигурация инстанса (значения `instance_settings` поверх дефолтов `plugins.yaml`, см. `services/instance_settings.py::load_effective_config`).""" transcriber: TranscriberConfig summarizer: SummarizerConfig chat: ChatConfig ai_level: AiLevel = "min" summary_recipients: SummaryRecipientsMode = "all" display_timezone: str = "Europe/Moscow" # Разрешить выбор команды на форме регистрации (справочник `teams`) # — см. `services/instance_settings.py`. registration_team_choice: bool = False # Верификация регистрирующихся по домену email: при включении # `POST /auth/register` принимает только # email с доменом `registration_email_domain` — см. # `services/instance_settings.py`. registration_email_domain_enabled: bool = False registration_email_domain: str | None = None # Контактный адрес инстанса — подставляется в `Reply-To` исходящих писем # (сами письма уходят от `no-reply@`, отвечать на них некуда без этого # адреса) — см. `services/instance_settings.py`, `services/email.py`. contact_email_enabled: bool = False contact_email: str | None = None