mirror of
https://github.com/All-Hands-AI/OpenHands.git
synced 2026-04-29 03:00:45 -04:00
refactor: move settings and secrets stores to app_server (#14165)
Co-authored-by: openhands <openhands@all-hands.dev>
This commit is contained in:
@@ -1,49 +0,0 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
from dataclasses import dataclass
|
||||
|
||||
from openhands.core.config.openhands_config import OpenHandsConfig
|
||||
from openhands.storage import get_file_store
|
||||
from openhands.storage.data_models.secrets import Secrets
|
||||
from openhands.storage.files import FileStore
|
||||
from openhands.storage.secrets.secrets_store import SecretsStore
|
||||
from openhands.utils.async_utils import call_sync_from_async
|
||||
|
||||
|
||||
@dataclass
|
||||
class FileSecretsStore(SecretsStore):
|
||||
file_store: FileStore
|
||||
path: str = 'secrets.json'
|
||||
|
||||
async def load(self) -> Secrets | None:
|
||||
try:
|
||||
json_str = await call_sync_from_async(self.file_store.read, self.path)
|
||||
kwargs = json.loads(json_str)
|
||||
provider_tokens = {
|
||||
k: v
|
||||
for k, v in (kwargs.get('provider_tokens') or {}).items()
|
||||
if v.get('token')
|
||||
}
|
||||
kwargs['provider_tokens'] = provider_tokens
|
||||
secrets = Secrets(**kwargs)
|
||||
return secrets
|
||||
except FileNotFoundError:
|
||||
return None
|
||||
|
||||
async def store(self, secrets: Secrets) -> None:
|
||||
json_str = secrets.model_dump_json(context={'expose_secrets': True})
|
||||
await call_sync_from_async(self.file_store.write, self.path, json_str)
|
||||
|
||||
@classmethod
|
||||
async def get_instance(
|
||||
cls, config: OpenHandsConfig, user_id: str | None
|
||||
) -> FileSecretsStore:
|
||||
file_store = get_file_store(
|
||||
file_store_type=config.file_store,
|
||||
file_store_path=config.file_store_path,
|
||||
file_store_web_hook_url=config.file_store_web_hook_url,
|
||||
file_store_web_hook_headers=config.file_store_web_hook_headers,
|
||||
file_store_web_hook_batch=config.file_store_web_hook_batch,
|
||||
)
|
||||
return FileSecretsStore(file_store)
|
||||
@@ -1,36 +0,0 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from abc import ABC, abstractmethod
|
||||
|
||||
from openhands.core.config.openhands_config import OpenHandsConfig
|
||||
from openhands.storage.data_models.secrets import Secrets
|
||||
|
||||
|
||||
class SecretsStore(ABC):
|
||||
"""Abstract base class for storing user secrets.
|
||||
|
||||
This is an extension point in OpenHands that allows applications to customize how
|
||||
user secrets are stored. Applications can substitute their own implementation by:
|
||||
1. Creating a class that inherits from SecretsStore
|
||||
2. Implementing all required methods
|
||||
3. Setting server_config.secret_store_class to the fully qualified name of the class
|
||||
|
||||
The class is instantiated via get_impl() in openhands.server.shared.py.
|
||||
|
||||
The implementation may or may not support multiple users depending on the environment.
|
||||
"""
|
||||
|
||||
@abstractmethod
|
||||
async def load(self) -> Secrets | None:
|
||||
"""Load secrets."""
|
||||
|
||||
@abstractmethod
|
||||
async def store(self, secrets: Secrets) -> None:
|
||||
"""Store secrets."""
|
||||
|
||||
@classmethod
|
||||
@abstractmethod
|
||||
async def get_instance(
|
||||
cls, config: OpenHandsConfig, user_id: str | None
|
||||
) -> SecretsStore:
|
||||
"""Get a store for the user represented by the token given."""
|
||||
@@ -1,50 +0,0 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
from dataclasses import dataclass
|
||||
|
||||
from openhands.core.config.openhands_config import OpenHandsConfig
|
||||
from openhands.storage import get_file_store
|
||||
from openhands.storage.data_models.settings import Settings
|
||||
from openhands.storage.files import FileStore
|
||||
from openhands.storage.settings.settings_store import SettingsStore
|
||||
from openhands.utils.async_utils import call_sync_from_async
|
||||
|
||||
|
||||
@dataclass
|
||||
class FileSettingsStore(SettingsStore):
|
||||
file_store: FileStore
|
||||
path: str = 'settings.json'
|
||||
|
||||
async def load(self) -> Settings | None:
|
||||
try:
|
||||
json_str = await call_sync_from_async(self.file_store.read, self.path)
|
||||
kwargs = json.loads(json_str)
|
||||
settings = Settings(**kwargs)
|
||||
|
||||
# Turn on V1 in OpenHands
|
||||
# We can simplify / remove this as part of V0 removal
|
||||
settings.v1_enabled = True
|
||||
|
||||
return settings
|
||||
except FileNotFoundError:
|
||||
return None
|
||||
|
||||
async def store(self, settings: Settings) -> None:
|
||||
json_str = settings.model_dump_json(
|
||||
context={'expose_secrets': True, 'persist_settings': True}
|
||||
)
|
||||
await call_sync_from_async(self.file_store.write, self.path, json_str)
|
||||
|
||||
@classmethod
|
||||
async def get_instance(
|
||||
cls, config: OpenHandsConfig, user_id: str | None
|
||||
) -> FileSettingsStore:
|
||||
file_store = get_file_store(
|
||||
file_store_type=config.file_store,
|
||||
file_store_path=config.file_store_path,
|
||||
file_store_web_hook_url=config.file_store_web_hook_url,
|
||||
file_store_web_hook_headers=config.file_store_web_hook_headers,
|
||||
file_store_web_hook_batch=config.file_store_web_hook_batch,
|
||||
)
|
||||
return FileSettingsStore(file_store)
|
||||
@@ -1,36 +0,0 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from abc import ABC, abstractmethod
|
||||
|
||||
from openhands.core.config.openhands_config import OpenHandsConfig
|
||||
from openhands.storage.data_models.settings import Settings
|
||||
|
||||
|
||||
class SettingsStore(ABC):
|
||||
"""Abstract base class for storing user settings.
|
||||
|
||||
This is an extension point in OpenHands that allows applications to customize how
|
||||
user settings are stored. Applications can substitute their own implementation by:
|
||||
1. Creating a class that inherits from SettingsStore
|
||||
2. Implementing all required methods
|
||||
3. Setting server_config.settings_store_class to the fully qualified name of the class
|
||||
|
||||
The class is instantiated via get_impl() in openhands.server.shared.py.
|
||||
|
||||
The implementation may or may not support multiple users depending on the environment.
|
||||
"""
|
||||
|
||||
@abstractmethod
|
||||
async def load(self) -> Settings | None:
|
||||
"""Load session init data."""
|
||||
|
||||
@abstractmethod
|
||||
async def store(self, settings: Settings) -> None:
|
||||
"""Store session init data."""
|
||||
|
||||
@classmethod
|
||||
@abstractmethod
|
||||
async def get_instance(
|
||||
cls, config: OpenHandsConfig, user_id: str | None
|
||||
) -> SettingsStore:
|
||||
"""Get a store for the user represented by the token given."""
|
||||
Reference in New Issue
Block a user