iluksic's picture
Created Computer Use Agent
2baba5d
Raw
History Blame Contribute Delete
4.75 kB
"""Centralized configuration management."""
from dataclasses import dataclass, field
from typing import Optional
import os
from dotenv import load_dotenv
@dataclass
class TimingConfig:
"""Timing configuration for various operations."""
screenshot_delay: float = 0.5
action_delay: float = 0.1
navigation_delay: float = 1.0
click_delay: float = 0.05
typing_delay_ms: int = 12
@dataclass
class ScreenConfig:
"""Screen and display configuration."""
width: int = 1024
height: int = 768
display_number: int = 1
@dataclass
class NetworkConfig:
"""Network access configuration."""
block_all: bool = False
allow_list: str = "0.0.0.0/0"
@dataclass
class SandboxConfig:
"""Sandbox lifecycle configuration."""
auto_stop_interval: int = 30 # minutes
auto_archive_interval: Optional[int] = None
auto_delete_interval: Optional[int] = None
@dataclass
class ClaudeConfig:
"""Claude API configuration."""
model: str = "claude-sonnet-4-5"
max_tokens: int = 4096
max_screenshots_in_history: int = 0
max_messages_in_history: int = 20 # Keep only last N messages (user + assistant pairs)
api_timeout: float = 300.0 # 5 minutes
max_retries: int = 3
auto_screenshot_after_action: bool = False # Capture screenshot after each action (needed for Gemini, not Claude)
@dataclass
class GUIConfig:
"""GUI and browser configuration for desktop automation."""
initial_url: str = "https://www.google.com"
search_engine_url: str = "https://www.google.com/"
user_agent: Optional[str] = None
@dataclass
class ExecutionConfig:
"""Code execution configuration."""
default_timeout: int = 60
max_timeout: int = 300
allow_package_install: bool = True
@dataclass
class DaytonaConfig:
"""Complete Daytona configuration."""
# Core configs
timing: TimingConfig = field(default_factory=TimingConfig)
screen: ScreenConfig = field(default_factory=ScreenConfig)
network: NetworkConfig = field(default_factory=NetworkConfig)
sandbox: SandboxConfig = field(default_factory=SandboxConfig)
claude: ClaudeConfig = field(default_factory=ClaudeConfig)
gui: GUIConfig = field(default_factory=GUIConfig)
execution: ExecutionConfig = field(default_factory=ExecutionConfig)
# API Keys
daytona_api_key: Optional[str] = None
anthropic_api_key: Optional[str] = None
@classmethod
def from_env(cls) -> "DaytonaConfig":
"""Create configuration from environment variables.
Returns:
DaytonaConfig instance with values from environment
"""
# Load .env file if it exists
load_dotenv()
config = cls()
# Load API keys
config.daytona_api_key = os.environ.get("DAYTONA_API_KEY")
config.anthropic_api_key = os.environ.get("ANTHROPIC_API_KEY")
# Override with environment variables if present
if screen_width := os.environ.get("DAYTONA_SCREEN_WIDTH"):
config.screen.width = int(screen_width)
if screen_height := os.environ.get("DAYTONA_SCREEN_HEIGHT"):
config.screen.height = int(screen_height)
if model := os.environ.get("CLAUDE_MODEL"):
config.claude.model = model
if initial_url := os.environ.get("DAYTONA_INITIAL_URL"):
config.gui.initial_url = initial_url
if auto_stop := os.environ.get("DAYTONA_AUTO_STOP"):
config.sandbox.auto_stop_interval = int(auto_stop)
return config
def validate(self) -> list[str]:
"""Validate configuration.
Returns:
List of validation errors (empty if valid)
"""
errors = []
# Validate API keys
if not self.daytona_api_key:
errors.append("DAYTONA_API_KEY is required")
if not self.anthropic_api_key:
errors.append("ANTHROPIC_API_KEY is required")
# Validate screen size
if self.screen.width <= 0 or self.screen.height <= 0:
errors.append(f"Invalid screen size: {self.screen.width}x{self.screen.height}")
# Validate timing
if self.timing.screenshot_delay < 0:
errors.append("screenshot_delay must be non-negative")
# Validate timeouts
if self.claude.api_timeout <= 0:
errors.append("API timeout must be positive")
if self.execution.default_timeout <= 0:
errors.append("Execution timeout must be positive")
if self.execution.max_timeout < self.execution.default_timeout:
errors.append("max_timeout must be greater than or equal to default_timeout")
return errors
# Global default configuration instance
DEFAULT_CONFIG = DaytonaConfig()