cc-os/plugins/os-vault/hooks/config.py

67 lines
2.0 KiB
Python

"""Config loading for the memory plugin hooks (deep module).
Replaces the duplicated inline YAML parsers in the four bash hooks with a single
load_config() call returning a frozen Config dataclass. Fail-open: a missing or
malformed config file yields defaults, never an exception.
"""
from __future__ import annotations
import os
from dataclasses import dataclass, field
try:
import yaml
except Exception: # pragma: no cover - yaml is provided via graphify
yaml = None
CONFIG_PATH = os.path.expanduser("~/.claude/plugins/os-vault/config.yaml")
DEFAULT_VAULT_PATH = "~/Documents/SecondBrain"
DEFAULT_GRAPHIFY_OUTPUT_DIR = "~/Documents/SecondBrain/.graphify"
DEFAULT_MODEL = "qwen25-coder-7b-16k"
DEFAULT_STALE_DAYS = 7
DEFAULT_MEMSEARCH_DIR = "~/.memsearch"
@dataclass(frozen=True)
class Config:
vault_path: str
graphify_output_dir: str
model: str
stale_days: int
memsearch_dir: str
env: dict = field(default_factory=dict)
def load_config(path: str = CONFIG_PATH) -> "Config":
cfg = {}
if yaml is not None:
try:
with open(os.path.expanduser(path)) as f:
cfg = yaml.safe_load(f) or {}
except Exception:
cfg = {}
if not isinstance(cfg, dict):
cfg = {}
def expand(value):
return os.path.expanduser(str(value))
try:
stale_days = int(cfg.get("stale_threshold_days", DEFAULT_STALE_DAYS))
except Exception:
stale_days = DEFAULT_STALE_DAYS
env_block = cfg.get("env") or {}
if not isinstance(env_block, dict):
env_block = {}
return Config(
vault_path=expand(cfg.get("vault_path", DEFAULT_VAULT_PATH)),
graphify_output_dir=expand(cfg.get("graphify_output_dir", DEFAULT_GRAPHIFY_OUTPUT_DIR)),
model=str(cfg.get("ollama_model", DEFAULT_MODEL)),
stale_days=stale_days,
memsearch_dir=expand(cfg.get("memsearch_dir", DEFAULT_MEMSEARCH_DIR)),
env={str(k): str(v) for k, v in env_block.items()},
)