Compare commits

...

1 Commits

Author SHA1 Message Date
rohitvinodmalhotra@gmail.com
5673c2cc66 create plugin pattern 2025-06-06 14:49:59 -04:00
7 changed files with 57 additions and 4 deletions

View File

@@ -358,7 +358,7 @@ async def main_with_loop(loop: asyncio.AbstractEventLoop) -> None:
# Load settings from Settings Store
# TODO: Make this generic?
settings_store = await FileSettingsStore.get_instance(config=config, user_id=None)
settings_store = await FileSettingsStore.get_instance(config=config)
settings = await settings_store.load()
# Track if we've shown the banner during setup

View File

@@ -0,0 +1,15 @@
from openhands.core.config.openhands_config import OpenHandsConfig
from openhands.core.plugins.plugin_schema import PluginSchema
from openhands.storage.settings.settings_store import SettingsStore
from openhands.storage.settings.file_settings_store import FileSettingsStore
class OpenHandsPlugin(PluginSchema):
"""Base class for OpenHands plugins."""
def __init__(self, config: OpenHandsConfig):
self.config = config
async def get_settings_store(self) -> type[SettingsStore]:
"""Get the settings store implementation."""
return await FileSettingsStore.get_instance(self.config)

View File

@@ -0,0 +1,25 @@
from openhands.core.plugins.openhands_plugin import OpenHandsPlugin
from openhands.core.plugins.plugin_schema import MissingPluginException, PluginSchema
from openhands.storage.settings.settings_store import SettingsStore
class PluginRegistry:
_instance = None
_plugins: list[type[PluginSchema]] = []
@classmethod
def get_instance(cls):
if cls._instance is None:
cls._instance = cls()
return cls._instance
def register_plugin(self, plugin: type[PluginSchema]):
self._plugins.append(plugin)
async def get_settings_store(self) -> type[SettingsStore]:
# Return the last registered implementation or default
for plugin in reversed(self._plugins):
store = await plugin.get_settings_store()
return store
raise MissingPluginException('Did not find plugin for settings store')

View File

@@ -0,0 +1,13 @@
from abc import abstractmethod
from openhands.storage.settings.settings_store import SettingsStore
class MissingPluginException(Exception):
"""Raised when no plugin was found for the plugin registry."""
class PluginSchema:
@abstractmethod
async def get_settings_store(self) -> type[SettingsStore]:
"""Get the settings store implementation."""
...

View File

@@ -31,7 +31,7 @@ class FileSettingsStore(SettingsStore):
@classmethod
async def get_instance(
cls, config: OpenHandsConfig, user_id: str | None
cls, config: OpenHandsConfig
) -> FileSettingsStore:
file_store = file_store = get_file_store(
config.file_store,

View File

@@ -31,6 +31,6 @@ class SettingsStore(ABC):
@classmethod
@abstractmethod
async def get_instance(
cls, config: OpenHandsConfig, user_id: str | None
cls, config: OpenHandsConfig
) -> SettingsStore:
"""Get a store for the user represented by the token given."""

View File

@@ -82,7 +82,7 @@ async def test_get_instance():
mock_store = MagicMock(spec=FileStore)
mock_get_store.return_value = mock_store
store = await FileSettingsStore.get_instance(config, None)
store = await FileSettingsStore.get_instance(config)
assert isinstance(store, FileSettingsStore)
assert store.file_store == mock_store