"""Concrete multi-modal interface adapters: visual, haptic, gesture, biometric.""" from __future__ import annotations import asyncio from collections import deque from typing import Any from fusionagi._logger import logger from fusionagi.interfaces.base import ( InterfaceAdapter, InterfaceCapabilities, InterfaceMessage, ModalityType, ) class VisualAdapter(InterfaceAdapter): """Visual modality adapter for images, video, and AR/VR content. In production, connect to a rendering engine or display server. This implementation queues messages for external consumers. """ def __init__(self) -> None: super().__init__("visual") self._outbox: deque[InterfaceMessage] = deque(maxlen=100) self._inbox: asyncio.Queue[InterfaceMessage] = asyncio.Queue() def capabilities(self) -> InterfaceCapabilities: return InterfaceCapabilities( supported_modalities=[ModalityType.VISUAL], supports_streaming=True, supports_interruption=False, supports_multimodal=True, ) async def send(self, message: InterfaceMessage) -> None: self._outbox.append(message) logger.debug("VisualAdapter: queued visual output", extra={"id": message.id}) async def receive(self, timeout_seconds: float | None = None) -> InterfaceMessage | None: try: return await asyncio.wait_for(self._inbox.get(), timeout=timeout_seconds) except (asyncio.TimeoutError, TimeoutError): return None def get_pending_outputs(self) -> list[InterfaceMessage]: """Drain pending visual outputs for external rendering.""" msgs = list(self._outbox) self._outbox.clear() return msgs class HapticAdapter(InterfaceAdapter): """Haptic feedback adapter for tactile interactions. Stores haptic events (vibration patterns, force feedback) for consumption by a hardware controller. """ def __init__(self) -> None: super().__init__("haptic") self._events: deque[InterfaceMessage] = deque(maxlen=50) def capabilities(self) -> InterfaceCapabilities: return InterfaceCapabilities( supported_modalities=[ModalityType.HAPTIC], supports_streaming=False, supports_interruption=True, latency_ms=10.0, ) async def send(self, message: InterfaceMessage) -> None: self._events.append(message) logger.debug("HapticAdapter: queued haptic event", extra={"id": message.id}) async def receive(self, timeout_seconds: float | None = None) -> InterfaceMessage | None: return None # haptic is output-only class GestureAdapter(InterfaceAdapter): """Gesture recognition adapter for motion control input. Processes gesture events from external tracking systems (cameras, IMUs, depth sensors). """ def __init__(self) -> None: super().__init__("gesture") self._inbox: asyncio.Queue[InterfaceMessage] = asyncio.Queue() def capabilities(self) -> InterfaceCapabilities: return InterfaceCapabilities( supported_modalities=[ModalityType.GESTURE], supports_streaming=True, supports_interruption=True, latency_ms=50.0, ) async def send(self, message: InterfaceMessage) -> None: pass # gesture is input-only async def receive(self, timeout_seconds: float | None = None) -> InterfaceMessage | None: try: return await asyncio.wait_for(self._inbox.get(), timeout=timeout_seconds) except (asyncio.TimeoutError, TimeoutError): return None async def inject_gesture(self, gesture: InterfaceMessage) -> None: """Inject a gesture event from an external tracking system.""" await self._inbox.put(gesture) class BiometricAdapter(InterfaceAdapter): """Biometric adapter for physiological signal processing. Handles emotion detection, heart rate, GSR (galvanic skin response), and other biosensors. Input-only modality. """ def __init__(self) -> None: super().__init__("biometric") self._inbox: asyncio.Queue[InterfaceMessage] = asyncio.Queue() self._latest: dict[str, Any] = {} def capabilities(self) -> InterfaceCapabilities: return InterfaceCapabilities( supported_modalities=[ModalityType.BIOMETRIC], supports_streaming=True, supports_interruption=False, latency_ms=100.0, ) async def send(self, message: InterfaceMessage) -> None: pass # biometric is input-only async def receive(self, timeout_seconds: float | None = None) -> InterfaceMessage | None: try: msg = await asyncio.wait_for(self._inbox.get(), timeout=timeout_seconds) if isinstance(msg.content, dict): self._latest.update(msg.content) return msg except (asyncio.TimeoutError, TimeoutError): return None async def inject_reading(self, reading: InterfaceMessage) -> None: """Inject a biometric reading from external sensors.""" await self._inbox.put(reading) def get_latest(self) -> dict[str, Any]: """Get the latest aggregated biometric readings.""" return dict(self._latest) __all__ = [ "VisualAdapter", "HapticAdapter", "GestureAdapter", "BiometricAdapter", ]