File size: 2,598 Bytes
526950e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# scripts/lib/paths.py
"""Path resolution. Single source of truth — other modules import from here."""
from __future__ import annotations
import json
import os
from pathlib import Path


def default_paths_json_path() -> Path:
    """Return the default location of paths.json."""
    if os.name == "nt":
        # Windows: %USERPROFILE%\.config\me-hub\paths.json
        return Path(os.environ["USERPROFILE"]) / ".config" / "me-hub" / "paths.json"
    return Path.home() / ".config" / "me-hub" / "paths.json"


_PATHS_JSON_PATH: Path = default_paths_json_path()


def repo_root() -> Path:
    """Return the repo root by walking up from cwd looking for pyproject.toml."""
    p = Path.cwd().resolve()
    for candidate in [p, *p.parents]:
        if (candidate / "pyproject.toml").is_file():
            return candidate
    raise RuntimeError(f"could not locate repo root from {p}")


def load_paths_json() -> dict:
    """Load and return ~/.config/me-hub/paths.json as a dict."""
    if not _PATHS_JSON_PATH.is_file():
        raise FileNotFoundError(
            f"paths.json not found at {_PATHS_JSON_PATH}. "
            "Run ./bootstrap.{ps1,sh} to configure this machine."
        )
    return json.loads(_PATHS_JSON_PATH.read_text())


def declared_role() -> str:
    """Return the declared role: 'maintainer' or 'faculty'."""
    role = load_paths_json().get("declared_role")
    if role not in ("maintainer", "faculty"):
        raise ValueError(f"declared_role must be 'maintainer' or 'faculty', got {role!r}")
    return role


def box_togo_path() -> Path | None:
    """Return the Box mirror path or None if not configured (faculty mode)."""
    raw = load_paths_json().get("box_togo_path")
    return Path(raw) if raw else None


def tolk_technology_path() -> Path | None:
    """Return the tolk-technology repo path or None if not configured."""
    raw = load_paths_json().get("tolk_technology_path")
    return Path(raw) if raw else None


def ferpa_data_root() -> Path:
    """Return FERPA_DATA_ROOT (always configured)."""
    raw = load_paths_json().get("ferpa_data_root")
    if not raw:
        raise ValueError("ferpa_data_root not configured in paths.json")
    return Path(raw)


def openai_api_key() -> str | None:
    """Read OPENAI_API_KEY from env. Returns None if unset.

    A per-machine key file fallback is supported but requires explicit opt-in
    via the build_derived --accept-key-file-risk flag; this reader does NOT
    read the file by default to avoid surprising the user.
    """
    val = os.environ.get("OPENAI_API_KEY")
    return val if val else None