Add Regular dataclass + lore file loader
This commit is contained in:
@@ -0,0 +1,51 @@
|
|||||||
|
from dataclasses import dataclass
|
||||||
|
from pathlib import Path
|
||||||
|
import re
|
||||||
|
|
||||||
|
HOME = Path.home()
|
||||||
|
VAULT = HOME / "code" / "dotfiles"
|
||||||
|
SILAS_DIR = VAULT / "silas"
|
||||||
|
REGULARS_DIR = VAULT / "regulars"
|
||||||
|
ARCHIVED_DIR = REGULARS_DIR / "archived"
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Regular:
|
||||||
|
name: str
|
||||||
|
voice: str
|
||||||
|
age: int
|
||||||
|
arc_state: str
|
||||||
|
lore_body: str
|
||||||
|
file_path: Path
|
||||||
|
|
||||||
|
|
||||||
|
def load_regular(path: Path) -> Regular:
|
||||||
|
text = path.read_text()
|
||||||
|
m = re.match(r"^---\n(.*?)\n---\n(.*)$", text, re.DOTALL)
|
||||||
|
if not m:
|
||||||
|
raise ValueError(f"No frontmatter in {path}")
|
||||||
|
fm_raw, body = m.group(1), m.group(2).strip()
|
||||||
|
fm = {}
|
||||||
|
for line in fm_raw.splitlines():
|
||||||
|
if ":" in line:
|
||||||
|
k, v = line.split(":", 1)
|
||||||
|
fm[k.strip()] = v.strip()
|
||||||
|
return Regular(
|
||||||
|
name=fm["name"],
|
||||||
|
voice=fm["voice"],
|
||||||
|
age=int(fm["age"]),
|
||||||
|
arc_state=fm.get("arc_state", ""),
|
||||||
|
lore_body=body,
|
||||||
|
file_path=path,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def load_all_active_regulars() -> list[Regular]:
|
||||||
|
out = []
|
||||||
|
if SILAS_DIR.exists():
|
||||||
|
for f in SILAS_DIR.glob("*.md"):
|
||||||
|
out.append(load_regular(f))
|
||||||
|
if REGULARS_DIR.exists():
|
||||||
|
for f in REGULARS_DIR.glob("*.md"):
|
||||||
|
out.append(load_regular(f))
|
||||||
|
return out
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
from backend.services.regulars_v2 import Regular, load_regular, REGULARS_DIR, SILAS_DIR
|
||||||
|
|
||||||
|
|
||||||
|
def test_load_regular_parses_frontmatter_and_body(tmp_path):
|
||||||
|
lore_file = tmp_path / "silas.md"
|
||||||
|
lore_file.write_text("""---
|
||||||
|
name: Silas
|
||||||
|
voice: Dennis
|
||||||
|
age: 54
|
||||||
|
arc_state: Cult is splintering after the eclipse failure
|
||||||
|
---
|
||||||
|
|
||||||
|
# Silas
|
||||||
|
|
||||||
|
Silas runs a small desert cult outside Truth or Consequences...
|
||||||
|
|
||||||
|
## Arc Log
|
||||||
|
|
||||||
|
- 2026-03-01: First call, introduced the cult
|
||||||
|
- 2026-03-20: Prophesied the eclipse
|
||||||
|
""")
|
||||||
|
reg = load_regular(lore_file)
|
||||||
|
assert reg.name == "Silas"
|
||||||
|
assert reg.voice == "Dennis"
|
||||||
|
assert reg.age == 54
|
||||||
|
assert "splintering" in reg.arc_state
|
||||||
|
assert "Silas runs a small desert cult" in reg.lore_body
|
||||||
Reference in New Issue
Block a user