Spaces:
Sleeping
Sleeping
File size: 4,432 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 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 | """First-time machine setup: persist role + external paths + FERPA_DATA_ROOT.
Writes two files:
- paths.json (user-config dir, machine-scoped; OUTSIDE the repo)
- .me-hub/local-state.json (in-repo, gitignored)
The role declaration is explicit, never inferred from path existence.
"""
from __future__ import annotations
import json
import os
import socket
from pathlib import Path
from typing import Optional
from lib.local_state import SCHEMA_VERSION as LOCAL_STATE_SCHEMA_VERSION
from lib.paths import default_paths_json_path, repo_root as _repo_root_real
_PATHS_JSON_SCHEMA_VERSION = 1
class MissingMaintainerPathError(RuntimeError):
pass
class FerpaInsideRepoError(RuntimeError):
pass
def _paths_json_path() -> Path:
return default_paths_json_path()
def _local_state_path() -> Path:
return _repo_root_real() / ".me-hub" / "local-state.json"
def _repo_root() -> Path:
return _repo_root_real()
def configure(
*,
declared_role: str,
box_togo_path: Optional[Path],
tolk_technology_path: Optional[Path],
ferpa_data_root: Path,
machine: str,
) -> None:
"""Persist the configuration for this machine."""
if declared_role not in ("maintainer", "faculty"):
raise ValueError(
f"declared_role must be 'maintainer' or 'faculty', got {declared_role!r}"
)
if declared_role == "maintainer":
if box_togo_path is None or not box_togo_path.exists():
raise MissingMaintainerPathError("maintainer mode requires box_togo_path")
if tolk_technology_path is None or not tolk_technology_path.exists():
raise MissingMaintainerPathError(
"maintainer mode requires tolk_technology_path"
)
repo = _repo_root()
try:
ferpa_data_root.resolve().relative_to(repo.resolve())
except ValueError:
pass
else:
raise FerpaInsideRepoError(
f"FERPA_DATA_ROOT must be OUTSIDE the working tree "
f"(got {ferpa_data_root}, which is inside {repo})"
)
ferpa_data_root.mkdir(parents=True, exist_ok=True)
pj = _paths_json_path()
pj.parent.mkdir(parents=True, exist_ok=True)
pj.write_text(
json.dumps(
{
"schema_version": _PATHS_JSON_SCHEMA_VERSION,
"declared_role": declared_role,
"box_togo_path": str(box_togo_path) if box_togo_path else None,
"tolk_technology_path": str(tolk_technology_path) if tolk_technology_path else None,
"ferpa_data_root": str(ferpa_data_root),
},
indent=2,
sort_keys=True,
),
encoding="utf-8",
)
ls = _local_state_path()
ls.parent.mkdir(parents=True, exist_ok=True)
ls.write_text(
json.dumps(
{
"schema_version": LOCAL_STATE_SCHEMA_VERSION,
"machine": machine,
"declared_role": declared_role,
"last_local_refresh_utc": None,
"last_seen_state_commit": None,
},
indent=2,
sort_keys=True,
),
encoding="utf-8",
)
# Inform the maintainer about OPENAI_API_KEY (required for build-derived)
if os.environ.get("OPENAI_API_KEY"):
print("OK: OPENAI_API_KEY found in environment (will be used by build-derived).")
else:
print("")
print("INFO: OPENAI_API_KEY not set. The build-derived pipeline requires it.")
print(" - bash/zsh: export OPENAI_API_KEY=sk-...")
print(" - powershell: $env:OPENAI_API_KEY = 'sk-...'")
print(" - or set it in your shell profile so it persists across sessions.")
# Inform the maintainer about ANTHROPIC_API_KEY (required for student-chat app)
if os.environ.get("ANTHROPIC_API_KEY"):
print("OK: ANTHROPIC_API_KEY found in environment (will be used by the chat app).")
else:
print("")
print("INFO: ANTHROPIC_API_KEY not set. The student-chat application requires it.")
print(" - bash/zsh: export ANTHROPIC_API_KEY=sk-ant-...")
print(" - powershell: $env:ANTHROPIC_API_KEY = 'sk-ant-...'")
print(" - or set it in your shell profile so it persists across sessions.")
def detect_machine() -> str:
"""Return socket.gethostname(). Called by bootstrap.{ps1,sh} to populate `machine`."""
return socket.gethostname()
|