LibreOffice Calc extension for Silo PLM integration. Uses shared silo-client package (submodule) for API communication. Changes from monorepo version: - SiloClient class removed from client.py, replaced with CalcSiloSettings adapter + factory function wrapping silo_client.SiloClient - silo_calc_component.py adds silo-client to sys.path - Makefile build-oxt copies silo_client into .oxt for self-contained packaging - All other modules unchanged
95 lines
2.5 KiB
Python
95 lines
2.5 KiB
Python
"""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()
|