"""Configuration service for Local Code Assistant.""" import os from pathlib import Path from typing import Any import yaml from dotenv import load_dotenv load_dotenv() class ConfigService: """Service for managing application configuration.""" def __init__(self, config_path: str | None = None): """Initialize configuration service. Args: config_path: Path to configuration file. Defaults to ~/.config/local-code-assistant/config.yaml """ env_path = os.getenv("CONFIG_PATH") path_str = config_path if config_path is not None else (env_path if env_path is not None else "~/.config/local-code-assistant/config.yaml") self.config_path = Path(path_str).expanduser() self.config_dir = self.config_path.parent self._config: dict[str, Any] = {} self._load_config() def _load_config(self): """Load configuration from file.""" if self.config_path.exists(): try: with open(self.config_path) as f: loaded = yaml.safe_load(f) self._config = loaded if loaded else {} except Exception: self._config = {} else: self._config = {} def save_config(self): """Save current configuration to file.""" self.config_dir.mkdir(parents=True, exist_ok=True) with open(self.config_path, 'w') as f: yaml.dump(self._config, f, default_flow_style=False) @property def ollama_base_url(self) -> str: """Get Ollama base URL.""" env_url = os.getenv("OLLAMA_BASE_URL") if env_url: return env_url return self._config.get("ollama", {}).get("base_url", "http://localhost:11434") @ollama_base_url.setter def ollama_base_url(self, value: str): """Set Ollama base URL.""" if "ollama" not in self._config: self._config["ollama"] = {} self._config["ollama"]["base_url"] = value @property def ollama_model(self) -> str: """Get Ollama model.""" env_model = os.getenv("OLLAMA_MODEL") if env_model: return env_model return self._config.get("ollama", {}).get("model", "codellama") @ollama_model.setter def ollama_model(self, value: str): """Set Ollama model.""" if "ollama" not in self._config: self._config["ollama"] = {} self._config["ollama"]["model"] = value @property def ollama_timeout(self) -> int: """Get Ollama timeout.""" env_timeout = os.getenv("OLLAMA_TIMEOUT") if env_timeout: return int(env_timeout) return self._config.get("ollama", {}).get("timeout", 8000) @property def streaming(self) -> bool: """Get streaming setting.""" return self._config.get("ollama", {}).get("streaming", True) @property def default_language(self) -> str: """Get default programming language.""" return self._config.get("defaults", {}).get("language", "python") @property def supported_languages(self) -> list[str]: """Get list of supported programming languages.""" return self._config.get("languages", ["python", "javascript", "typescript", "go", "rust"]) @property def temperature(self) -> float: """Get default temperature for LLM requests.""" return self._config.get("defaults", {}).get("temperature", 0.2) @property def max_tokens(self) -> int: """Get max tokens for LLM responses.""" return self._config.get("defaults", {}).get("max_tokens", 4000) @property def context_max_files(self) -> int: """Get maximum number of files to include in context.""" return self._config.get("context", {}).get("max_files", 10) @property def context_max_file_size(self) -> int: """Get maximum file size for context (in bytes).""" return self._config.get("context", {}).get("max_file_size", 100000) @property def syntax_highlighting(self) -> bool: """Get syntax highlighting setting.""" return self._config.get("output", {}).get("syntax_highlighting", True) @property def clipboard_enabled(self) -> bool: """Get clipboard output setting.""" return self._config.get("output", {}).get("clipboard", True) def get(self, key: str, default: Any = None) -> Any: """Get configuration value by key.""" keys = key.split(".") value: Any = self._config for k in keys: if isinstance(value, dict): value = value.get(k) else: return default return value if value is not None else default def set(self, key: str, value: Any): """Set configuration value by key.""" keys = key.split(".") config: dict[str, Any] = self._config for k in keys[:-1]: if k not in config: config[k] = {} config = config[k] config[keys[-1]] = value def reload(self): """Reload configuration from file.""" self._load_config()