Spaces:
Building
Building
| """ | |
| OFP Client | |
| Handles sending and receiving Open Floor Protocol envelopes via HTTPS | |
| """ | |
| import requests | |
| import logging | |
| import json | |
| from typing import Dict, Optional | |
| from .models import Envelope, DialogEvent | |
| logger = logging.getLogger(__name__) | |
| class OFPClient: | |
| """Client for sending OFP envelopes to conveners and other assistants""" | |
| def __init__(self, speaker_uri: str, service_url: str, manifest: Dict): | |
| self.speaker_uri = speaker_uri | |
| self.service_url = service_url | |
| self.manifest = manifest | |
| logger.info(f"OFP Client initialized for {speaker_uri}") | |
| def send_envelope(self, recipient_url: str, envelope: Envelope, timeout: int = 10) -> bool: | |
| """Send OFP envelope to recipient via HTTPS POST""" | |
| try: | |
| payload = envelope.to_payload() | |
| logger.debug(f"Sending envelope to {recipient_url}: {json.dumps(payload, indent=2)}") | |
| response = requests.post( | |
| recipient_url, | |
| json=payload, | |
| headers={ | |
| 'Content-Type': 'application/json', | |
| 'User-Agent': 'OFP-BadWord-Sentinel/1.0' | |
| }, | |
| timeout=timeout | |
| ) | |
| response.raise_for_status() | |
| logger.info(f"β Envelope sent successfully to {recipient_url}") | |
| return True | |
| except requests.exceptions.Timeout: | |
| logger.error(f"β Timeout sending envelope to {recipient_url}") | |
| return False | |
| except requests.exceptions.RequestException as e: | |
| logger.error(f"β Failed to send envelope to {recipient_url}: {e}") | |
| return False | |
| except Exception as e: | |
| logger.error(f"β Unexpected error sending envelope: {e}") | |
| return False | |
| def send_private_alert( | |
| self, | |
| convener_uri: str, | |
| convener_url: str, | |
| conversation_id: str, | |
| alert_data: Dict | |
| ) -> bool: | |
| """Send private alert to convener about profanity detection""" | |
| try: | |
| # Create alert text as JSON | |
| alert_text = json.dumps(alert_data, indent=2) | |
| # Create dialog event for the alert | |
| alert_event = DialogEvent.create_text_event( | |
| speaker_uri=self.speaker_uri, | |
| text=alert_text | |
| ) | |
| # Create envelope with private utterance event | |
| envelope = Envelope( | |
| schema={"version": "1.0.0"}, | |
| conversation={"id": conversation_id}, | |
| sender={"speakerUri": self.speaker_uri}, | |
| events=[{ | |
| "eventType": "utterance", | |
| "to": { | |
| "speakerUri": convener_uri, | |
| "private": True # CRITICAL: Only convener sees this | |
| }, | |
| "parameters": { | |
| "dialogEvent": alert_event.to_dict() | |
| } | |
| }] | |
| ) | |
| logger.info(f"Sending private alert to convener: {convener_uri}") | |
| return self.send_envelope(convener_url, envelope) | |
| except Exception as e: | |
| logger.error(f"Error creating private alert: {e}") | |
| return False | |
| def send_public_message( | |
| self, | |
| conversation_id: str, | |
| recipient_url: str, | |
| text: str | |
| ) -> bool: | |
| """Send public message to the floor (visible to all participants)""" | |
| try: | |
| dialog_event = DialogEvent.create_text_event( | |
| speaker_uri=self.speaker_uri, | |
| text=text | |
| ) | |
| envelope = Envelope( | |
| schema={"version": "1.0.0"}, | |
| conversation={"id": conversation_id}, | |
| sender={"speakerUri": self.speaker_uri}, | |
| events=[{ | |
| "eventType": "utterance", | |
| "parameters": { | |
| "dialogEvent": dialog_event.to_dict() | |
| } | |
| }] | |
| ) | |
| return self.send_envelope(recipient_url, envelope) | |
| except Exception as e: | |
| logger.error(f"Error sending public message: {e}") | |
| return False | |
| def request_floor( | |
| self, | |
| conversation_id: str, | |
| convener_url: str, | |
| convener_uri: str | |
| ) -> bool: | |
| """Request speaking floor from convener""" | |
| envelope = Envelope( | |
| schema={"version": "1.0.0"}, | |
| conversation={"id": conversation_id}, | |
| sender={"speakerUri": self.speaker_uri}, | |
| events=[{ | |
| "eventType": "floorRequest", | |
| "to": { | |
| "speakerUri": convener_uri | |
| } | |
| }] | |
| ) | |
| return self.send_envelope(convener_url, envelope) | |
| def get_manifest(self) -> Dict: | |
| """Return assistant manifest""" | |
| return self.manifest | |