"""Persistent settings for the Silo Calc extension. Settings are stored in ``~/.config/silo/calc-settings.json``. The file is a flat JSON dict with known keys. """ import json import os from pathlib import Path from typing import Any, Dict _SETTINGS_DIR = ( Path(os.environ.get("XDG_CONFIG_HOME", "~/.config")).expanduser() / "silo" ) _SETTINGS_FILE = _SETTINGS_DIR / "calc-settings.json" # Default values for every known key. _DEFAULTS: Dict[str, Any] = { "api_url": "", "api_token": "", "ssl_verify": True, "ssl_cert_path": "", "auth_username": "", "auth_role": "", "auth_source": "", "projects_dir": "", # fallback: SILO_PROJECTS_DIR env or ~/projects "default_schema": "kindred-rd", "openrouter_api_key": "", # fallback: OPENROUTER_API_KEY env var "openrouter_model": "", # fallback: ai_client.DEFAULT_MODEL "openrouter_instructions": "", # fallback: ai_client.DEFAULT_INSTRUCTIONS } def load() -> Dict[str, Any]: """Load settings, returning defaults for any missing keys.""" cfg = dict(_DEFAULTS) if _SETTINGS_FILE.is_file(): try: with open(_SETTINGS_FILE, "r") as f: stored = json.load(f) cfg.update(stored) except (json.JSONDecodeError, OSError): pass return cfg def save(cfg: Dict[str, Any]) -> None: """Persist the full settings dict to disk.""" _SETTINGS_DIR.mkdir(parents=True, exist_ok=True) with open(_SETTINGS_FILE, "w") as f: json.dump(cfg, f, indent=2) def get(key: str, default: Any = None) -> Any: """Convenience: load a single key.""" cfg = load() return cfg.get(key, default) def put(key: str, value: Any) -> None: """Convenience: update a single key and persist.""" cfg = load() cfg[key] = value save(cfg) def save_auth(username: str, role: str = "", source: str = "", token: str = "") -> None: """Store authentication info.""" cfg = load() cfg["auth_username"] = username cfg["auth_role"] = role cfg["auth_source"] = source if token: cfg["api_token"] = token save(cfg) def clear_auth() -> None: """Remove stored auth credentials.""" cfg = load() cfg["api_token"] = "" cfg["auth_username"] = "" cfg["auth_role"] = "" cfg["auth_source"] = "" save(cfg) def get_projects_dir() -> Path: """Return the resolved projects base directory.""" cfg = load() d = cfg.get("projects_dir", "") if not d: d = os.environ.get("SILO_PROJECTS_DIR", "~/projects") return Path(d).expanduser()