from abc import abstractmethod from itertools import islice from typing import Iterable from deprecated import deprecated # type: ignore from openhands.events.event import Event, EventSource from openhands.events.event_filter import EventFilter class EventStoreABC: """ A stored list of events backing a conversation """ sid: str user_id: str | None @abstractmethod def search_events( self, start_id: int = 0, end_id: int | None = None, reverse: bool = False, filter: EventFilter | None = None, limit: int | None = None, ) -> Iterable[Event]: """ Retrieve events from the event stream, optionally excluding events using a filter Args: start_id: The ID of the first event to retrieve. Defaults to 0. end_id: The ID of the last event to retrieve. Defaults to the last event in the stream. reverse: Whether to retrieve events in reverse order. Defaults to False. filter: An optional event filter Yields: Events from the stream that match the criteria. """ @deprecated('Use search_events instead') def get_events( self, start_id: int = 0, end_id: int | None = None, reverse: bool = False, filter_out_type: tuple[type[Event], ...] | None = None, filter_hidden: bool = False, ) -> Iterable[Event]: yield from self.search_events( start_id, end_id, reverse, EventFilter(exclude_types=filter_out_type, exclude_hidden=filter_hidden), ) @abstractmethod def get_event(self, id: int) -> Event: """Retrieve a single event from the event stream. Raise a FileNotFoundError if there was no such event""" @abstractmethod def get_latest_event(self) -> Event: """Get the latest event from the event stream""" @abstractmethod def get_latest_event_id(self) -> int: """Get the id of the latest event from the event stream""" @deprecated('use search_events instead') def filtered_events_by_source(self, source: EventSource) -> Iterable[Event]: yield from self.search_events(filter=EventFilter(source=source)) @deprecated('use search_events instead') def get_matching_events( self, query: str | None = None, event_types: tuple[type[Event], ...] | None = None, source: str | None = None, start_date: str | None = None, end_date: str | None = None, start_id: int = 0, limit: int = 100, reverse: bool = False, ) -> list[Event]: """Get matching events from the event stream based on filters. Args: query: Text to search for in event content event_types: Filter by event type classes (e.g., (FileReadAction, ) ). source: Filter by event source start_date: Filter events after this date (ISO format) end_date: Filter events before this date (ISO format) start_id: Starting ID in the event stream. Defaults to 0 limit: Maximum number of events to return. Must be between 1 and 100. Defaults to 100 reverse: Whether to retrieve events in reverse order. Defaults to False. Returns: list: List of matching events (as dicts) """ if limit < 1 or limit > 100: raise ValueError('Limit must be between 1 and 100') events = self.search_events( start_id=start_id, reverse=reverse, filter=EventFilter( query=query, include_types=event_types, source=source, start_date=start_date, end_date=end_date, ), ) return list(islice(events, limit))