Skip to content

Commit

Permalink
Refactor ConversationStore to follow SettingsStore pattern
Browse files Browse the repository at this point in the history
- Make ConversationStore abstract base class
- Create FileConversationStore implementation
- Move ConversationMetadata to server.data_models
- Reorganize storage package structure
  • Loading branch information
openhands-agent committed Dec 28, 2024
1 parent ebb2d86 commit 2fc946f
Show file tree
Hide file tree
Showing 7 changed files with 58 additions and 21 deletions.
8 changes: 8 additions & 0 deletions openhands/server/data_models/conversation_metadata.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
from dataclasses import dataclass


@dataclass
class ConversationMetadata:
conversation_id: str
github_user_id: str
selected_repository: str | None
9 changes: 4 additions & 5 deletions openhands/server/listen_socket.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,10 @@
from openhands.events.observation.agent import AgentStateChangedObservation
from openhands.events.serialization import event_to_dict
from openhands.events.stream import AsyncEventStreamWrapper
from openhands.server.routes.settings import SettingsStoreImpl
from openhands.server.routes.settings import ConversationStoreImpl, SettingsStoreImpl
from openhands.server.session.manager import ConversationDoesNotExistError
from openhands.server.shared import config, openhands_config, session_manager, sio
from openhands.server.types import AppMode
from openhands.storage.conversation.conversation_store import (
ConversationStore,
)
from openhands.utils.async_utils import call_sync_from_async


Expand All @@ -44,7 +41,9 @@ async def connect(connection_id: str, environ, auth):

logger.info(f'User {user_id} is connecting to conversation {conversation_id}')

conversation_store = await ConversationStore.get_instance(config)
conversation_store = await ConversationStoreImpl.get_instance(
config, github_token
)
metadata = await conversation_store.get_metadata(conversation_id)
if metadata.github_user_id != user_id:
logger.error(
Expand Down
9 changes: 3 additions & 6 deletions openhands/server/routes/new_conversation.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,10 @@
from pydantic import BaseModel

from openhands.core.logger import openhands_logger as logger
from openhands.server.routes.settings import SettingsStoreImpl
from openhands.server.routes.settings import ConversationStoreImpl, SettingsStoreImpl
from openhands.server.session.conversation_init_data import ConversationInitData
from openhands.server.shared import config, session_manager
from openhands.storage.conversation.conversation_store import (
ConversationMetadata,
ConversationStore,
)
from openhands.server.data_models.conversation_metadata import ConversationMetadata
from openhands.utils.async_utils import call_sync_from_async

app = APIRouter(prefix='/api')
Expand Down Expand Up @@ -49,7 +46,7 @@ async def new_conversation(request: Request, data: InitSessionRequest):
session_init_args['selected_repository'] = data.selected_repository
conversation_init_data = ConversationInitData(**session_init_args)

conversation_store = await ConversationStore.get_instance(config)
conversation_store = await ConversationStoreImpl.get_instance(config, github_token)

conversation_id = uuid.uuid4().hex
while await conversation_store.exists(conversation_id):
Expand Down
5 changes: 5 additions & 0 deletions openhands/server/routes/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,17 @@
from openhands.core.logger import openhands_logger as logger
from openhands.server.settings import Settings
from openhands.server.shared import config, openhands_config
from openhands.storage.conversation_store import ConversationStore
from openhands.storage.settings_store import SettingsStore
from openhands.utils.import_utils import get_impl

app = APIRouter(prefix='/api')

SettingsStoreImpl = get_impl(SettingsStore, openhands_config.settings_store_class) # type: ignore
ConversationStoreImpl = get_impl(
ConversationStore,
'openhands.storage.file_conversation_store.FileConversationStore',
) # type: ignore


@app.get('/settings')
Expand Down
29 changes: 29 additions & 0 deletions openhands/storage/conversation_store.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
from __future__ import annotations

from abc import ABC, abstractmethod

from openhands.core.config.app_config import AppConfig
from openhands.server.data_models.conversation_metadata import ConversationMetadata


class ConversationStore(ABC):
"""
Storage for conversation metadata. May or may not support multiple users depending on the environment
"""

@abstractmethod
async def save_metadata(self, metadata: ConversationMetadata):
"""Store conversation metadata"""

@abstractmethod
async def get_metadata(self, conversation_id: str) -> ConversationMetadata:
"""Load conversation metadata"""

@abstractmethod
async def exists(self, conversation_id: str) -> bool:
"""Check if conversation exists"""

@classmethod
@abstractmethod
async def get_instance(cls, config: AppConfig, token: str | None) -> ConversationStore:
"""Get a store for the user represented by the token given"""
Original file line number Diff line number Diff line change
@@ -1,22 +1,19 @@
from __future__ import annotations

import json
from dataclasses import dataclass

from openhands.core.config.app_config import AppConfig
from openhands.storage import get_file_store
from openhands.storage.conversation_store import ConversationStore
from openhands.server.data_models.conversation_metadata import ConversationMetadata
from openhands.storage.files import FileStore
from openhands.storage.locations import get_conversation_metadata_filename
from openhands.utils.async_utils import call_sync_from_async


@dataclass
class ConversationMetadata:
conversation_id: str
github_user_id: str
selected_repository: str | None


@dataclass
class ConversationStore:
class FileConversationStore(ConversationStore):
file_store: FileStore

async def save_metadata(self, metadata: ConversationMetadata):
Expand All @@ -38,6 +35,6 @@ async def exists(self, conversation_id: str) -> bool:
return False

@classmethod
async def get_instance(cls, config: AppConfig):
async def get_instance(cls, config: AppConfig, token: str | None):
file_store = get_file_store(config.file_store, config.file_store_path)
return ConversationStore(file_store)
return FileConversationStore(file_store)
2 changes: 2 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ reportlab = "*"
[tool.coverage.run]
concurrency = ["gevent"]


[tool.poetry.group.runtime.dependencies]
jupyterlab = "*"
notebook = "*"
Expand Down Expand Up @@ -129,6 +130,7 @@ ignore = ["D1"]
[tool.ruff.lint.pydocstyle]
convention = "google"


[tool.poetry.group.evaluation.dependencies]
streamlit = "*"
whatthepatch = "*"
Expand Down

0 comments on commit 2fc946f

Please sign in to comment.