From 6816541535d95af62a2105250e180948d9b3bc75 Mon Sep 17 00:00:00 2001 From: 7000pctAUTO Date: Sat, 31 Jan 2026 15:30:15 +0000 Subject: [PATCH] Add services, prompts, and utils modules --- local_code_assistant/services/config.py | 154 ++++++++++++++++++++++++ 1 file changed, 154 insertions(+) create mode 100644 local_code_assistant/services/config.py diff --git a/local_code_assistant/services/config.py b/local_code_assistant/services/config.py new file mode 100644 index 0000000..fa95e57 --- /dev/null +++ b/local_code_assistant/services/config.py @@ -0,0 +1,154 @@ +"""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() \ No newline at end of file