"""Configuration resolution shared by CLI and MCP entrypoints.""" from __future__ import annotations from pathlib import Path from obsidian_wiki.file_assets import clean_config_value GLOBAL_CONFIG = Path.home() / ".obsidian-wiki" / "config" def parse_config_file(path: Path) -> dict[str, str]: values: dict[str, str] = {} if not path.is_file(): return values for raw in path.read_text(encoding="utf-8", errors="ignore").splitlines(): line = raw.strip() if not line or line.startswith("#") or "=" not in line: continue key, value = line.split("=", 1) values[key.strip()] = clean_config_value(value) return values def find_config(start: str | Path | None = None) -> Path | None: """Resolve config using the llm-wiki protocol.""" current = Path(start or Path.cwd()).expanduser().resolve() if current.is_file(): current = current.parent home = Path.home().resolve() while True: candidate = current / ".env" if candidate.is_file() and parse_config_file(candidate).get("OBSIDIAN_VAULT_PATH"): return candidate if current == home or current.parent == current: break current = current.parent if GLOBAL_CONFIG.is_file(): return GLOBAL_CONFIG return None def load_config(start: str | Path | None = None) -> dict[str, str]: path = find_config(start) return parse_config_file(path) if path else {} def resolve_vault_path(cli_vault: str | None = None, *, start: str | Path | None = None) -> str: if cli_vault: return str(Path(clean_config_value(cli_vault)).expanduser()) config = load_config(start) return config.get("OBSIDIAN_VAULT_PATH", "") def config_value(key: str, default: str = "", *, start: str | Path | None = None) -> str: return load_config(start).get(key, default)