"""Channel connection setup models.""" from __future__ import annotations from dataclasses import asdict, dataclass, field from datetime import datetime, timezone from typing import Any CONNECTION_STATUSES = {"draft", "pairing", "connected", "running", "degraded", "error", "revoked"} def iso_now() -> str: return datetime.now(timezone.utc).isoformat() @dataclass(slots=True) class ChannelConnection: connection_id: str owner_user_id: str | None channel_id: str kind: str mode: str display_name: str account_id: str status: str auth_type: str credentials_ref: str | None = None connector_ref: str | None = None pairing_session_id: str | None = None runtime_config: dict[str, Any] = field(default_factory=dict) capabilities: list[str] = field(default_factory=list) created_at: str = field(default_factory=iso_now) updated_at: str = field(default_factory=iso_now) last_seen_at: str | None = None last_error: str | None = None def to_dict(self) -> dict[str, Any]: return asdict(self) @classmethod def from_dict(cls, data: dict[str, Any]) -> "ChannelConnection": return cls( connection_id=str(data.get("connection_id") or ""), owner_user_id=_optional_string(data.get("owner_user_id")), channel_id=str(data.get("channel_id") or ""), kind=str(data.get("kind") or ""), mode=str(data.get("mode") or ""), display_name=str(data.get("display_name") or ""), account_id=str(data.get("account_id") or ""), status=str(data.get("status") or "draft"), auth_type=str(data.get("auth_type") or ""), credentials_ref=_optional_string(data.get("credentials_ref")), connector_ref=_optional_string(data.get("connector_ref")), pairing_session_id=_optional_string(data.get("pairing_session_id")), runtime_config=dict(data.get("runtime_config") or {}), capabilities=[str(item) for item in data.get("capabilities") or []], created_at=str(data.get("created_at") or iso_now()), updated_at=str(data.get("updated_at") or iso_now()), last_seen_at=_optional_string(data.get("last_seen_at")), last_error=_optional_string(data.get("last_error")), ) @dataclass(slots=True) class PairingSession: pairing_session_id: str kind: str scope: str token: str status: str expires_at_ms: int created_at_ms: int def to_dict(self) -> dict[str, Any]: return asdict(self) @classmethod def from_dict(cls, data: dict[str, Any]) -> "PairingSession": return cls( pairing_session_id=str(data.get("pairing_session_id") or ""), kind=str(data.get("kind") or ""), scope=str(data.get("scope") or ""), token=str(data.get("token") or ""), status=str(data.get("status") or "pending"), expires_at_ms=int(data.get("expires_at_ms") or 0), created_at_ms=int(data.get("created_at_ms") or 0), ) @dataclass(slots=True) class ChannelRuntimeSpec: channel_id: str kind: str mode: str account_id: str display_name: str config: dict[str, Any] = field(default_factory=dict) secrets_ref: str | None = None external_endpoint: str | None = None @dataclass(slots=True) class ValidationResult: ok: bool status: str account_id: str | None = None display_name: str | None = None error: str | None = None metadata: dict[str, Any] = field(default_factory=dict) def _optional_string(value: Any) -> str | None: if value is None: return None text = str(value).strip() return text or None