102 lines
3.2 KiB
Python
102 lines
3.2 KiB
Python
"""Configuration loading for Memory System API."""
|
|
from __future__ import annotations
|
|
|
|
import os
|
|
from pathlib import Path
|
|
from typing import Any, Literal
|
|
|
|
import yaml
|
|
from pydantic import BaseModel, Field
|
|
|
|
|
|
class ServerConfig(BaseModel):
|
|
host: str = "127.0.0.1"
|
|
port: int = 1934
|
|
api_key: str = ""
|
|
|
|
|
|
class OpenVikingConfig(BaseModel):
|
|
url: str = "http://127.0.0.1:1933"
|
|
api_key: str = ""
|
|
timeout: int = 30
|
|
verify_ssl: bool = True
|
|
|
|
|
|
class EverOSConfig(BaseModel):
|
|
url: str = "http://127.0.0.1:1995"
|
|
api_key: str = ""
|
|
timeout: int = 180
|
|
verify_ssl: bool = True
|
|
health_path: str = "/health"
|
|
|
|
|
|
class StorageConfig(BaseModel):
|
|
sqlite_path: str = "/home/tom/memory-gateway/memory_system_api.sqlite3"
|
|
|
|
|
|
class LoggingConfig(BaseModel):
|
|
level: str = "INFO"
|
|
format: str = "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
|
|
|
|
|
|
class Config(BaseModel):
|
|
server: ServerConfig = Field(default_factory=ServerConfig)
|
|
openviking: OpenVikingConfig = Field(default_factory=OpenVikingConfig)
|
|
everos: EverOSConfig = Field(default_factory=EverOSConfig)
|
|
storage: StorageConfig = Field(default_factory=StorageConfig)
|
|
logging: LoggingConfig = Field(default_factory=LoggingConfig)
|
|
|
|
|
|
_config: Config | None = None
|
|
|
|
|
|
def load_config(config_path: str | None = None) -> Config:
|
|
path = Path(config_path or os.environ.get("MEMORY_SYSTEM_CONFIG", "config.yaml"))
|
|
if not path.exists():
|
|
return _apply_env_overrides(Config())
|
|
with path.open("r", encoding="utf-8") as handle:
|
|
data = yaml.safe_load(handle) or {}
|
|
config = Config(
|
|
server=ServerConfig(**data.get("server", {})),
|
|
openviking=OpenVikingConfig(**data.get("openviking", {})),
|
|
everos=EverOSConfig(**data.get("everos", {})),
|
|
storage=StorageConfig(**data.get("storage", {})),
|
|
logging=LoggingConfig(**data.get("logging", {})),
|
|
)
|
|
return _apply_env_overrides(config)
|
|
|
|
|
|
def get_config() -> Config:
|
|
global _config
|
|
if _config is None:
|
|
_config = load_config()
|
|
return _config
|
|
|
|
|
|
def set_config(config: Config) -> None:
|
|
global _config
|
|
_config = config
|
|
|
|
|
|
def _apply_env_overrides(config: Config) -> Config:
|
|
updates: dict[str, dict[str, Any]] = {
|
|
"server": _env_updates("MEMORY_SYSTEM_SERVER", {"API_KEY": "api_key", "HOST": "host", "PORT": "port"}),
|
|
"openviking": _env_updates("OPENVIKING", {"URL": "url", "BASE_URL": "url", "API_KEY": "api_key", "TIMEOUT": "timeout"}),
|
|
"everos": _env_updates("EVEROS", {"URL": "url", "BASE_URL": "url", "API_KEY": "api_key", "TIMEOUT": "timeout"}),
|
|
"storage": _env_updates("MEMORY_SYSTEM_STORAGE", {"SQLITE_PATH": "sqlite_path"}),
|
|
}
|
|
for section, values in updates.items():
|
|
if values:
|
|
setattr(config, section, getattr(config, section).model_copy(update=values))
|
|
return config
|
|
|
|
|
|
def _env_updates(prefix: str, mapping: dict[str, str]) -> dict[str, Any]:
|
|
values: dict[str, Any] = {}
|
|
for env_name, field_name in mapping.items():
|
|
raw = os.environ.get(f"{prefix}_{env_name}")
|
|
if raw is None:
|
|
continue
|
|
values[field_name] = int(raw) if field_name in {"port", "timeout"} else raw
|
|
return values
|