Luxx/luxx/config.py

118 lines
3.4 KiB
Python

"""Configuration management module"""
import os
import yaml
from pathlib import Path
from typing import Any, Dict, Optional
class Config:
"""Configuration class (singleton pattern)"""
_instance: Optional["Config"] = None
_config: Dict[str, Any] = {}
def __new__(cls):
if cls._instance is None:
cls._instance = super().__new__(cls)
cls._instance._load_config()
return cls._instance
def _load_config(self) -> None:
"""Load configuration from YAML file"""
yaml_paths = [
Path("config.yaml"),
Path(__file__).parent.parent / "config.yaml",
Path.cwd() / "config.yaml",
]
for path in yaml_paths:
if path.exists():
with open(path, "r", encoding="utf-8") as f:
self._config = yaml.safe_load(f) or {}
self._resolve_env_vars()
return
self._config = {}
def _resolve_env_vars(self) -> None:
"""Resolve environment variable references"""
def resolve(value: Any) -> Any:
if isinstance(value, str) and value.startswith("${") and value.endswith("}"):
return os.environ.get(value[2:-1], "")
elif isinstance(value, dict):
return {k: resolve(v) for k, v in value.items()}
elif isinstance(value, list):
return [resolve(item) for item in value]
return value
self._config = resolve(self._config)
def get(self, key: str, default: Any = None) -> Any:
"""Get configuration value, supports dot-separated keys"""
keys = key.split(".")
value = self._config
for k in keys:
if isinstance(value, dict):
value = value.get(k)
else:
return default
if value is None:
return default
return value
# App configuration
@property
def secret_key(self) -> str:
return self.get("app.secret_key", "change-me-in-production")
@property
def debug(self) -> bool:
return self.get("app.debug", True)
@property
def app_host(self) -> str:
return self.get("app.host", "0.0.0.0")
@property
def app_port(self) -> int:
return self.get("app.port", 8000)
# Database configuration
@property
def database_url(self) -> str:
return self.get("database.url", "sqlite:///./chat.db")
# LLM configuration
@property
def llm_api_key(self) -> str:
return self.get("llm.api_key", "") or os.environ.get("DEEPSEEK_API_KEY", "")
@property
def llm_api_url(self) -> str:
return self.get("llm.api_url", "https://api.deepseek.com/v1")
@property
def llm_provider(self) -> str:
return self.get("llm.provider", "deepseek")
# Tools configuration
@property
def tools_enable_cache(self) -> bool:
return self.get("tools.enable_cache", True)
@property
def tools_cache_ttl(self) -> int:
return self.get("tools.cache_ttl", 300)
@property
def tools_max_workers(self) -> int:
return self.get("tools.max_workers", 4)
@property
def tools_max_iterations(self) -> int:
return self.get("tools.max_iterations", 10)
# Global configuration instance
config = Config()