OpenHands / openhands /events /nested_event_store.py
Backup-bdg's picture
Upload 964 files
51ff9e5 verified
from dataclasses import dataclass
from typing import Iterable
from urllib.parse import urlencode
import httpx # type: ignore
from fastapi import status
from openhands.events.event import Event
from openhands.events.event_filter import EventFilter
from openhands.events.event_store_abc import EventStoreABC
from openhands.events.serialization.event import event_from_dict
@dataclass
class NestedEventStore(EventStoreABC):
"""
A stored list of events backing a conversation
"""
base_url: str
sid: str
user_id: str | None
session_api_key: str | None = None
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]:
while True:
search_params = {
'start_id': start_id,
'reverse': reverse,
}
if limit is not None:
search_params['limit'] = min(100, limit)
search_str = urlencode(search_params)
url = f'{self.base_url}/events?{search_str}'
headers = {}
if self.session_api_key:
headers['X-Session-API-Key'] = self.session_api_key
response = httpx.get(url, headers=headers)
if response.status_code == status.HTTP_404_NOT_FOUND:
# Follow pattern of event store not throwing errors on not found
return
result_set = response.json()
for result in result_set['events']:
event = event_from_dict(result)
start_id = max(start_id, event.id + 1)
if end_id == event.id:
if not filter or filter.include(event):
yield event
return
if filter and filter.exclude(event):
continue
yield event
if limit is not None:
limit -= 1
if limit <= 0:
return
if not result_set['has_more']:
return
def get_event(self, id: int) -> Event:
events = list(self.search_events(start_id=id, limit=1))
if not events:
raise FileNotFoundError('no_event')
return events[0]
def get_latest_event(self) -> Event:
events = list(self.search_events(reverse=True, limit=1))
if not events:
raise FileNotFoundError('no_event')
return events[0]
def get_latest_event_id(self) -> int:
event = self.get_latest_event()
return event.id