Files
local-code-assistant/local_code_assistant/services/config.py
7000pctAUTO 6816541535
Some checks failed
CI / test (push) Has been cancelled
CI / build (push) Has been cancelled
Add services, prompts, and utils modules
2026-01-31 15:30:15 +00:00

154 lines
5.0 KiB
Python

"""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()