""" Event models — Real-time events published via WebSocket and event bus. These events drive the dashboard, notifications, and MCP updates. """ from datetime import datetime from enum import Enum from typing import Any, Optional from pydantic import BaseModel, Field class EventType(str, Enum): """Types of events the gateway can emit.""" # Call lifecycle CALL_INITIATED = "call.initiated" CALL_RINGING = "call.ringing" CALL_CONNECTED = "call.connected" CALL_ENDED = "call.ended" CALL_FAILED = "call.failed" # Hold Slayer IVR_STEP = "holdslayer.ivr_step" IVR_DTMF_SENT = "holdslayer.dtmf_sent" HOLD_DETECTED = "holdslayer.hold_detected" HUMAN_DETECTED = "holdslayer.human_detected" TRANSFER_STARTED = "holdslayer.transfer_started" TRANSFER_COMPLETE = "holdslayer.transfer_complete" # Audio AUDIO_CLASSIFIED = "audio.classified" TRANSCRIPT_CHUNK = "audio.transcript_chunk" # Device DEVICE_REGISTERED = "device.registered" DEVICE_ONLINE = "device.online" DEVICE_OFFLINE = "device.offline" # System GATEWAY_STARTED = "system.gateway_started" GATEWAY_STOPPING = "system.gateway_stopping" ERROR = "system.error" # SIP Trunk SIP_TRUNK_REGISTERED = "sip.trunk.registered" SIP_TRUNK_REGISTRATION_FAILED = "sip.trunk.registration_failed" SIP_TRUNK_UNREGISTERED = "sip.trunk.unregistered" class GatewayEvent(BaseModel): """A real-time event from the gateway.""" type: EventType call_id: Optional[str] = None timestamp: datetime = Field(default_factory=datetime.now) data: dict[str, Any] = Field(default_factory=dict) message: Optional[str] = None # Human-readable description def to_ws_message(self) -> dict: """Serialize for WebSocket transmission.""" return { "type": self.type.value, "call_id": self.call_id, "timestamp": self.timestamp.isoformat(), "data": self.data, "message": self.message, }