from __future__ import annotations from datetime import datetime, timezone from enum import StrEnum from uuid import uuid4 from pydantic import BaseModel, Field class ProposalStatus(StrEnum): DRAFT = "draft" APPROVED = "approved" REJECTED = "rejected" class NumericStateTrigger(BaseModel): entity_id: str = Field(pattern=r"^sensor\.[a-z0-9_]+$") above: float | None = None below: float | None = None class ServiceAction(BaseModel): service: str = Field(pattern=r"^(light|switch|climate|fan|cover)\.[a-z0-9_]+$") entity_id: str = Field(pattern=r"^(light|switch|climate|fan|cover)\.[a-z0-9_]+$") data: dict[str, str | int | float | bool] = Field(default_factory=dict) class AutomationProposal(BaseModel): proposal_id: str = Field(default_factory=lambda: uuid4().hex) alias: str = Field(min_length=1, max_length=120) description: str = Field(min_length=1, max_length=500) trigger: NumericStateTrigger action: ServiceAction status: ProposalStatus = ProposalStatus.DRAFT created_at: datetime = Field(default_factory=lambda: datetime.now(timezone.utc)) updated_at: datetime = Field(default_factory=lambda: datetime.now(timezone.utc)) revision: int = 1 class ProposalDecision(BaseModel): expected_revision: int = Field(ge=1)