import asyncio import logging from abc import ABC, abstractmethod from datetime import datetime from uuid import UUID from openhands.agent_server.models import EventPage, EventSortOrder from openhands.app_server.event_callback.event_callback_models import EventKind from openhands.app_server.services.injector import Injector from openhands.sdk import Event from openhands.sdk.utils.models import DiscriminatedUnionMixin _logger = logging.getLogger(__name__) class SharedEventService(ABC): """Event Service for getting events from shared conversations only.""" @abstractmethod async def get_shared_event( self, conversation_id: UUID, event_id: str ) -> Event | None: """Given a conversation_id and event_id, retrieve an event if the conversation is shared.""" @abstractmethod async def search_shared_events( self, conversation_id: UUID, kind__eq: EventKind | None = None, timestamp__gte: datetime | None = None, timestamp__lt: datetime | None = None, sort_order: EventSortOrder = EventSortOrder.TIMESTAMP, page_id: str | None = None, limit: int = 100, ) -> EventPage: """Search events for a specific shared conversation.""" @abstractmethod async def count_shared_events( self, conversation_id: UUID, kind__eq: EventKind | None = None, timestamp__gte: datetime | None = None, timestamp__lt: datetime | None = None, sort_order: EventSortOrder = EventSortOrder.TIMESTAMP, ) -> int: """Count events for a specific shared conversation.""" async def batch_get_shared_events( self, conversation_id: UUID, event_ids: list[str] ) -> list[Event | None]: """Given a conversation_id and list of event_ids, get events if the conversation is shared.""" return await asyncio.gather( *[ self.get_shared_event(conversation_id, event_id) for event_id in event_ids ] ) class SharedEventServiceInjector( DiscriminatedUnionMixin, Injector[SharedEventService], ABC ): pass