from __future__ import annotations from typing import Any, Literal from pydantic import BaseModel, Field TriggerMode = Literal["down", "up"] ActionType = Literal["noop", "key_combo", "chain", "app_launch", "folder", "folder_rotation", "plugin"] class SettingsUpdate(BaseModel): serial_port: str | None = None click_check: bool | None = None active_profile_id: str | None = None active_folder_id: str | None = None class ProfileCreate(BaseModel): name: str = Field(min_length=1, max_length=80) class ProfileUpdate(BaseModel): name: str | None = Field(default=None, min_length=1, max_length=80) active: bool | None = None class FolderCreate(BaseModel): profile_id: str parent_id: str | None = None name: str = Field(min_length=1, max_length=80) class FolderUpdate(BaseModel): name: str | None = Field(default=None, min_length=1, max_length=80) parent_id: str | None = None class ButtonUpdate(BaseModel): label: str | None = None color: str | None = None icon: str | None = None physical_button: int | None = Field(default=None, ge=1, le=10) trigger_mode: TriggerMode | None = None action_type: ActionType | None = None action_config: dict[str, Any] | None = None class ManualAppCreate(BaseModel): name: str = Field(min_length=1, max_length=160) path: str = Field(min_length=1) args: str | None = None class ActionTest(BaseModel): action_type: ActionType action_config: dict[str, Any] = Field(default_factory=dict) class WebSocketCommand(BaseModel): type: str payload: dict[str, Any] = Field(default_factory=dict)