Spaces:
Build error
Build error
File size: 4,841 Bytes
51ff9e5 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 |
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,
}
@field_serializer('llm_api_key', 'search_api_key')
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)
@model_validator(mode='before')
@classmethod
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
@field_serializer('secrets_store')
def secrets_store_serializer(self, secrets: UserSecrets, info: SerializationInfo):
"""Custom serializer for secrets store."""
"""Force invalidate secret store"""
return {'provider_tokens': {}}
@staticmethod
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
|