Spaces:
Build error
Build error
| from __future__ import annotations | |
| from pydantic import ( | |
| BaseModel, | |
| Field, | |
| SecretStr, | |
| SerializationInfo, | |
| field_serializer, | |
| model_validator, | |
| ) | |
| from pydantic.json import pydantic_encoder | |
| from openhands.core.config.llm_config import LLMConfig | |
| from openhands.core.config.mcp_config import MCPConfig | |
| from openhands.core.config.utils import load_openhands_config | |
| from openhands.storage.data_models.user_secrets import UserSecrets | |
| class Settings(BaseModel): | |
| """ | |
| Persisted settings for OpenHands sessions | |
| """ | |
| language: str | None = None | |
| agent: str | None = None | |
| max_iterations: int | None = None | |
| security_analyzer: str | None = None | |
| confirmation_mode: bool | None = None | |
| llm_model: str | None = None | |
| llm_api_key: SecretStr | None = None | |
| llm_base_url: str | None = None | |
| remote_runtime_resource_factor: int | None = None | |
| # Planned to be removed from settings | |
| secrets_store: UserSecrets = Field(default_factory=UserSecrets, frozen=True) | |
| enable_default_condenser: bool = True | |
| enable_sound_notifications: bool = False | |
| enable_proactive_conversation_starters: bool = True | |
| user_consents_to_analytics: bool | None = None | |
| sandbox_base_container_image: str | None = None | |
| sandbox_runtime_container_image: str | None = None | |
| mcp_config: MCPConfig | None = None | |
| search_api_key: SecretStr | None = None | |
| email: str | None = None | |
| email_verified: bool | None = None | |
| model_config = { | |
| 'validate_assignment': True, | |
| } | |
| def api_key_serializer(self, api_key: SecretStr | None, info: SerializationInfo): | |
| """Custom serializer for API keys. | |
| To serialize the API key instead of ********, set expose_secrets to True in the serialization context. | |
| """ | |
| if api_key is None: | |
| return None | |
| context = info.context | |
| if context and context.get('expose_secrets', False): | |
| return api_key.get_secret_value() | |
| return pydantic_encoder(api_key) | |
| def convert_provider_tokens(cls, data: dict | object) -> dict | object: | |
| """Convert provider tokens from JSON format to UserSecrets format.""" | |
| if not isinstance(data, dict): | |
| return data | |
| secrets_store = data.get('secrets_store') | |
| if not isinstance(secrets_store, dict): | |
| return data | |
| custom_secrets = secrets_store.get('custom_secrets') | |
| tokens = secrets_store.get('provider_tokens') | |
| secret_store = UserSecrets(provider_tokens={}, custom_secrets={}) | |
| if isinstance(tokens, dict): | |
| converted_store = UserSecrets(provider_tokens=tokens) | |
| secret_store = secret_store.model_copy( | |
| update={'provider_tokens': converted_store.provider_tokens} | |
| ) | |
| else: | |
| secret_store.model_copy(update={'provider_tokens': tokens}) | |
| if isinstance(custom_secrets, dict): | |
| converted_store = UserSecrets(custom_secrets=custom_secrets) | |
| secret_store = secret_store.model_copy( | |
| update={'custom_secrets': converted_store.custom_secrets} | |
| ) | |
| else: | |
| secret_store = secret_store.model_copy( | |
| update={'custom_secrets': custom_secrets} | |
| ) | |
| data['secret_store'] = secret_store | |
| return data | |
| def secrets_store_serializer(self, secrets: UserSecrets, info: SerializationInfo): | |
| """Custom serializer for secrets store.""" | |
| """Force invalidate secret store""" | |
| return {'provider_tokens': {}} | |
| def from_config() -> Settings | None: | |
| app_config = load_openhands_config() | |
| llm_config: LLMConfig = app_config.get_llm_config() | |
| if llm_config.api_key is None: | |
| # If no api key has been set, we take this to mean that there is no reasonable default | |
| return None | |
| security = app_config.security | |
| # Get MCP config if available | |
| mcp_config = None | |
| if hasattr(app_config, 'mcp'): | |
| mcp_config = app_config.mcp | |
| settings = Settings( | |
| language='en', | |
| agent=app_config.default_agent, | |
| max_iterations=app_config.max_iterations, | |
| security_analyzer=security.security_analyzer, | |
| confirmation_mode=security.confirmation_mode, | |
| llm_model=llm_config.model, | |
| llm_api_key=llm_config.api_key, | |
| llm_base_url=llm_config.base_url, | |
| remote_runtime_resource_factor=app_config.sandbox.remote_runtime_resource_factor, | |
| mcp_config=mcp_config, | |
| search_api_key=app_config.search_api_key, | |
| ) | |
| return settings | |