""" Configuration for Claude Vision Auto """ import os import yaml from pathlib import Path from typing import Dict, Any def get_config_dir() -> Path: """Get configuration directory""" config_dir = Path.home() / ".config" / "claude-vision-auto" config_dir.mkdir(parents=True, exist_ok=True) return config_dir def get_cache_dir() -> Path: """Get cache directory for screenshots""" cache_dir = Path.home() / ".cache" / "claude-vision-auto" cache_dir.mkdir(parents=True, exist_ok=True) return cache_dir def load_config() -> Dict[str, Any]: """ Load configuration from YAML files with priority: 1. User config (~/.config/claude-vision-auto/config.yaml) 2. Default config (package default_config.yaml) 3. Environment variables (highest priority) """ # Load default config default_config_path = Path(__file__).parent / "default_config.yaml" with open(default_config_path, 'r') as f: config = yaml.safe_load(f) # Load user config if exists user_config_path = get_config_dir() / "config.yaml" if user_config_path.exists(): with open(user_config_path, 'r') as f: user_config = yaml.safe_load(f) # Deep merge user config if user_config: config = deep_merge(config, user_config) # Override with environment variables if os.getenv("OLLAMA_URL"): config['ollama']['url'] = os.getenv("OLLAMA_URL") if os.getenv("VISION_MODEL"): config['ollama']['model'] = os.getenv("VISION_MODEL") if os.getenv("IDLE_THRESHOLD"): config['timing']['idle_threshold'] = float(os.getenv("IDLE_THRESHOLD")) if os.getenv("RESPONSE_DELAY"): config['timing']['response_delay'] = float(os.getenv("RESPONSE_DELAY")) if os.getenv("DEBUG"): config['debug'] = os.getenv("DEBUG", "false").lower() in ("true", "1", "yes") return config def deep_merge(base: Dict, override: Dict) -> Dict: """Deep merge two dictionaries""" result = base.copy() for key, value in override.items(): if key in result and isinstance(result[key], dict) and isinstance(value, dict): result[key] = deep_merge(result[key], value) else: result[key] = value return result def create_user_config(): """Create user config file with defaults""" config_dir = get_config_dir() user_config_path = config_dir / "config.yaml" if not user_config_path.exists(): # Copy default config to user config default_config_path = Path(__file__).parent / "default_config.yaml" with open(default_config_path, 'r') as f: default_content = f.read() with open(user_config_path, 'w') as f: f.write(default_content) return user_config_path return None def create_user_config_cli(): """CLI command to create user configuration file""" import sys config_path = create_user_config() if config_path: print(f"✅ Created user configuration file:") print(f" {config_path}") print() print("Edit this file to customize:") print(f" - Vision model (minicpm-v, llama3.2-vision, llava)") print(f" - Vision prompt for better responses") print(f" - Timing settings (idle threshold, response delay)") print(f" - Approval keywords") print() print(f"Edit with: nano {config_path}") else: config_dir = get_config_dir() config_path = config_dir / "config.yaml" print(f"ℹ️ Configuration file already exists:") print(f" {config_path}") print() print(f"Edit with: nano {config_path}") sys.exit(0) # Load configuration _config = load_config() # Export commonly used values OLLAMA_URL = _config['ollama']['url'] VISION_MODEL = _config['ollama']['model'] VISION_TIMEOUT = _config['ollama']['timeout'] IDLE_THRESHOLD = _config['timing']['idle_threshold'] RESPONSE_DELAY = _config['timing']['response_delay'] SCREENSHOT_TIMEOUT = _config['timing']['screenshot_timeout'] VISION_PROMPT = _config['vision_prompt'] RESPONSE_MAPPING = _config['response_mapping'] APPROVAL_KEYWORDS = _config['approval_keywords'] OUTPUT_BUFFER_SIZE = _config['buffer']['size'] SCREENSHOT_TOOLS = _config['screenshot']['tools'] SCREENSHOT_CACHE_CLEANUP = _config['screenshot']['cache_cleanup_seconds'] DEBUG = _config['debug'] def get_config() -> Dict[str, Any]: """Get full configuration dict""" return _config.copy() def reload_config(): """Reload configuration from files""" global _config, OLLAMA_URL, VISION_MODEL, VISION_TIMEOUT global IDLE_THRESHOLD, RESPONSE_DELAY, SCREENSHOT_TIMEOUT global VISION_PROMPT, RESPONSE_MAPPING, APPROVAL_KEYWORDS global OUTPUT_BUFFER_SIZE, SCREENSHOT_TOOLS, SCREENSHOT_CACHE_CLEANUP, DEBUG _config = load_config() OLLAMA_URL = _config['ollama']['url'] VISION_MODEL = _config['ollama']['model'] VISION_TIMEOUT = _config['ollama']['timeout'] IDLE_THRESHOLD = _config['timing']['idle_threshold'] RESPONSE_DELAY = _config['timing']['response_delay'] SCREENSHOT_TIMEOUT = _config['timing']['screenshot_timeout'] VISION_PROMPT = _config['vision_prompt'] RESPONSE_MAPPING = _config['response_mapping'] APPROVAL_KEYWORDS = _config['approval_keywords'] OUTPUT_BUFFER_SIZE = _config['buffer']['size'] SCREENSHOT_TOOLS = _config['screenshot']['tools'] SCREENSHOT_CACHE_CLEANUP = _config['screenshot']['cache_cleanup_seconds'] DEBUG = _config['debug']