Spaces:
Build error
Build error
| import os | |
| from typing import Any, ClassVar | |
| from pydantic import BaseModel, Field, SecretStr | |
| from openhands.core import logger | |
| from openhands.core.config.agent_config import AgentConfig | |
| from openhands.core.config.config_utils import ( | |
| OH_DEFAULT_AGENT, | |
| OH_MAX_ITERATIONS, | |
| model_defaults_to_dict, | |
| ) | |
| from openhands.core.config.extended_config import ExtendedConfig | |
| from openhands.core.config.llm_config import LLMConfig | |
| from openhands.core.config.mcp_config import MCPConfig | |
| from openhands.core.config.sandbox_config import SandboxConfig | |
| from openhands.core.config.security_config import SecurityConfig | |
| class OpenHandsConfig(BaseModel): | |
| """Configuration for the app. | |
| Attributes: | |
| llms: Dictionary mapping LLM names to their configurations. | |
| The default configuration is stored under the 'llm' key. | |
| agents: Dictionary mapping agent names to their configurations. | |
| The default configuration is stored under the 'agent' key. | |
| default_agent: Name of the default agent to use. | |
| sandbox: Sandbox configuration settings. | |
| runtime: Runtime environment identifier. | |
| file_store: Type of file store to use. | |
| file_store_path: Path to the file store. | |
| file_store_web_hook_url: Optional url for file store web hook | |
| file_store_web_hook_headers: Optional headers for file_store web hook | |
| save_trajectory_path: Either a folder path to store trajectories with auto-generated filenames, or a designated trajectory file path. | |
| save_screenshots_in_trajectory: Whether to save screenshots in trajectory (in encoded image format). | |
| replay_trajectory_path: Path to load trajectory and replay. If provided, trajectory would be replayed first before user's instruction. | |
| search_api_key: API key for Tavily search engine (https://tavily.com/). | |
| workspace_base (deprecated): Base path for the workspace. Defaults to `./workspace` as absolute path. | |
| workspace_mount_path (deprecated): Path to mount the workspace. Defaults to `workspace_base`. | |
| workspace_mount_path_in_sandbox (deprecated): Path to mount the workspace in sandbox. Defaults to `/workspace`. | |
| workspace_mount_rewrite (deprecated): Path to rewrite the workspace mount path. | |
| cache_dir: Path to cache directory. Defaults to `/tmp/cache`. | |
| run_as_openhands: Whether to run as openhands. | |
| max_iterations: Maximum number of iterations allowed. | |
| max_budget_per_task: Maximum budget per task, agent stops if exceeded. | |
| e2b_api_key: E2B API key. | |
| disable_color: Whether to disable terminal colors. For terminals that don't support color. | |
| debug: Whether to enable debugging mode. | |
| file_uploads_max_file_size_mb: Maximum file upload size in MB. `0` means unlimited. | |
| file_uploads_restrict_file_types: Whether to restrict upload file types. | |
| file_uploads_allowed_extensions: Allowed file extensions. `['.*']` allows all. | |
| cli_multiline_input: Whether to enable multiline input in CLI. When disabled, | |
| input is read line by line. When enabled, input continues until /exit command. | |
| mcp_host: Host for OpenHands' default MCP server | |
| mcp: MCP configuration settings. | |
| """ | |
| llms: dict[str, LLMConfig] = Field(default_factory=dict) | |
| agents: dict[str, AgentConfig] = Field(default_factory=dict) | |
| default_agent: str = Field(default=OH_DEFAULT_AGENT) | |
| sandbox: SandboxConfig = Field(default_factory=SandboxConfig) | |
| security: SecurityConfig = Field(default_factory=SecurityConfig) | |
| extended: ExtendedConfig = Field(default_factory=lambda: ExtendedConfig({})) | |
| runtime: str = Field(default='docker') | |
| file_store: str = Field(default='local') | |
| file_store_path: str = Field(default='~/.openhands/file_store') | |
| file_store_web_hook_url: str | None = Field(default=None) | |
| file_store_web_hook_headers: dict | None = Field(default=None) | |
| save_trajectory_path: str | None = Field(default=None) | |
| save_screenshots_in_trajectory: bool = Field(default=False) | |
| replay_trajectory_path: str | None = Field(default=None) | |
| search_api_key: SecretStr | None = Field( | |
| default=None, | |
| description='API key for Tavily search engine (https://tavily.com/). Required for search functionality.', | |
| ) | |
| # Deprecated parameters - will be removed in a future version | |
| workspace_base: str | None = Field(default=None, deprecated=True) | |
| workspace_mount_path: str | None = Field(default=None, deprecated=True) | |
| workspace_mount_path_in_sandbox: str = Field(default='/workspace', deprecated=True) | |
| workspace_mount_rewrite: str | None = Field(default=None, deprecated=True) | |
| # End of deprecated parameters | |
| cache_dir: str = Field(default='/tmp/cache') | |
| run_as_openhands: bool = Field(default=True) | |
| max_iterations: int = Field(default=OH_MAX_ITERATIONS) | |
| max_budget_per_task: float | None = Field(default=None) | |
| e2b_api_key: SecretStr | None = Field(default=None) | |
| modal_api_token_id: SecretStr | None = Field(default=None) | |
| modal_api_token_secret: SecretStr | None = Field(default=None) | |
| disable_color: bool = Field(default=False) | |
| jwt_secret: SecretStr | None = Field(default=None) | |
| debug: bool = Field(default=False) | |
| file_uploads_max_file_size_mb: int = Field(default=0) | |
| file_uploads_restrict_file_types: bool = Field(default=False) | |
| file_uploads_allowed_extensions: list[str] = Field(default_factory=lambda: ['.*']) | |
| runloop_api_key: SecretStr | None = Field(default=None) | |
| daytona_api_key: SecretStr | None = Field(default=None) | |
| daytona_api_url: str = Field(default='https://app.daytona.io/api') | |
| daytona_target: str = Field(default='eu') | |
| cli_multiline_input: bool = Field(default=False) | |
| conversation_max_age_seconds: int = Field(default=864000) # 10 days in seconds | |
| enable_default_condenser: bool = Field(default=True) | |
| max_concurrent_conversations: int = Field( | |
| default=3 | |
| ) # Maximum number of concurrent agent loops allowed per user | |
| mcp_host: str = Field(default=f'localhost:{os.getenv("port", 3000)}') | |
| mcp: MCPConfig = Field(default_factory=MCPConfig) | |
| defaults_dict: ClassVar[dict] = {} | |
| model_config = {'extra': 'forbid'} | |
| def get_llm_config(self, name: str = 'llm') -> LLMConfig: | |
| """'llm' is the name for default config (for backward compatibility prior to 0.8).""" | |
| if name in self.llms: | |
| return self.llms[name] | |
| if name is not None and name != 'llm': | |
| logger.openhands_logger.warning( | |
| f'llm config group {name} not found, using default config' | |
| ) | |
| if 'llm' not in self.llms: | |
| self.llms['llm'] = LLMConfig() | |
| return self.llms['llm'] | |
| def set_llm_config(self, value: LLMConfig, name: str = 'llm') -> None: | |
| self.llms[name] = value | |
| def get_agent_config(self, name: str = 'agent') -> AgentConfig: | |
| """'agent' is the name for default config (for backward compatibility prior to 0.8).""" | |
| if name in self.agents: | |
| return self.agents[name] | |
| if 'agent' not in self.agents: | |
| self.agents['agent'] = AgentConfig() | |
| return self.agents['agent'] | |
| def set_agent_config(self, value: AgentConfig, name: str = 'agent') -> None: | |
| self.agents[name] = value | |
| def get_agent_to_llm_config_map(self) -> dict[str, LLMConfig]: | |
| """Get a map of agent names to llm configs.""" | |
| return {name: self.get_llm_config_from_agent(name) for name in self.agents} | |
| def get_llm_config_from_agent(self, name: str = 'agent') -> LLMConfig: | |
| agent_config: AgentConfig = self.get_agent_config(name) | |
| llm_config_name = ( | |
| agent_config.llm_config if agent_config.llm_config is not None else 'llm' | |
| ) | |
| return self.get_llm_config(llm_config_name) | |
| def get_agent_configs(self) -> dict[str, AgentConfig]: | |
| return self.agents | |
| def model_post_init(self, __context: Any) -> None: | |
| """Post-initialization hook, called when the instance is created with only default values.""" | |
| super().model_post_init(__context) | |
| if not OpenHandsConfig.defaults_dict: # Only set defaults_dict if it's empty | |
| OpenHandsConfig.defaults_dict = model_defaults_to_dict(self) | |