techprotrade's picture
Deploy ATOM FastAPI command center runtime (part 4)
4b9d59b verified
Raw
History Blame Contribute Delete
2.94 kB
from abc import ABC, abstractmethod
from typing import Any, Dict, Optional
from fastapi import Request
class PlatformAdapter(ABC):
"""
Abstract base class for Communication Platform Adapters.
Handles platform-specific verification, normalization, and sending.
"""
@abstractmethod
async def verify_request(self, request: Request, body_bytes: bytes) -> bool:
"""Verify the authenticity of the incoming webhook request"""
pass
@abstractmethod
def normalize_payload(self, payload: Dict[str, Any]) -> Dict[str, Any]:
"""
Convert platform-specific payload to standard Atom format:
{
"sender_id": str,
"content": str,
"channel_id": str,
"metadata": dict
}
Returns None if message should be ignored (e.g. bot message).
"""
pass
@abstractmethod
async def send_message(self, target_id: str, message: str, **kwargs) -> bool:
"""Send an outbound message to this platform"""
pass
async def send_approval_request(self, target_id: str, action_id: str, details: Dict[str, Any], priority: str) -> bool:
"""
Send an interactive approval request (Approve/Reject buttons).
Default implementation falls back to plain text send_message.
"""
message = f"🚨 *HITL Approval Required* ({priority})\nAction: {details.get('action_type')}\nReason: {details.get('reason')}\nAction ID: {action_id}\n\nPlease reply with 'APPROVE {action_id}' or 'REJECT {action_id}'"
return await self.send_message(target_id, message)
async def send_direct_message(self, target_id: str, message: str, agent_name: Optional[str] = None) -> bool:
"""
Send a proactive message from a specific agent.
Default implementation falls back to plain text send_message.
"""
prefix = f"[{agent_name}] " if agent_name else ""
return await self.send_message(target_id, f"{prefix}{message}")
async def get_media(self, media_id: str) -> Optional[bytes]:
"""Optional: Download media (audio/voice) from the platform."""
return None
class GenericAdapter(PlatformAdapter):
"""Fallback adapter for generic webhooks (no verification by default)"""
async def verify_request(self, request: Request, body_bytes: bytes) -> bool:
return True # MVP: Open generic webhook
def normalize_payload(self, payload: Dict[str, Any]) -> Dict[str, Any]:
return {
"sender_id": payload.get("sender_id", "unknown"),
"content": payload.get("message") or payload.get("content", ""),
"channel_id": payload.get("channel_id"),
"metadata": payload
}
async def send_message(self, target_id: str, message: str, **kwargs) -> bool:
# Generic has no outbound capability usually, or just logs
return True