from pathlib import Path from datetime import date BASE = Path(__file__).resolve().parent.parent SESSION = BASE / 'session' LOG_DIR = SESSION / 'log' CHAR_PATH = SESSION / 'character.md' WORLD_PATH = SESSION / 'world.md' JOURNAL_PATH = SESSION / 'journal.md' AMBIENCE_PATH = SESSION / 'ambience.md' AMBIENCE_OPTIONS_PATH = SESSION / 'ambience_options.md' BOOK_PATH = SESSION / 'book.md' LAST_PROMPT_PATH = SESSION / 'last_prompt.md' CHANGES_PATH = SESSION / 'changes.md' SETTINGS_PATH = SESSION / 'settings.json' AUDIO_DIR = SESSION / 'audio' TODAY = date.today().isoformat() LOG_PATH = LOG_DIR / f'{TODAY}.md' REFRESH_SECS = 2 def ensure_log(): LOG_DIR.mkdir(parents=True, exist_ok=True) if not LOG_PATH.exists(): LOG_PATH.write_text(f"# Session Log — {TODAY}\n\n") _populate_if_empty() def _populate_if_empty(): content = LOG_PATH.read_text().strip() if content and len(content.splitlines()) > 2: return def clear_llm_log(): from engine_lib.paths import LLM_LOG_PATH LLM_LOG_PATH.parent.mkdir(parents=True, exist_ok=True) LLM_LOG_PATH.write_text("") def read_todo(): if not JOURNAL_PATH.exists(): return ["—— No journal yet ——"] lines = JOURNAL_PATH.read_text().splitlines() in_todo = False todo = [] for l in lines: if l.strip().lstrip("#").strip().startswith("TODO"): in_todo = True continue if l.strip().startswith("#") and in_todo: break if in_todo and l.strip(): todo.append(l.strip().lstrip("- ")) return todo or ["—— All done! ——"] def read_log_tail(n=200): if not LOG_PATH.exists(): return [] lines = LOG_PATH.read_text().splitlines() return [l for l in lines if l.strip() and not l.startswith("#")][-n:] def status_summary(): if not CHAR_PATH.exists(): return "no character" lines = CHAR_PATH.read_text().splitlines() name = "?" health = "?" for l in lines: if l.startswith('**Name:**'): name = l.split(':', 1)[1].strip().strip('_').strip('*') if l.startswith('**Current Health:**'): h = l.split(':', 1)[1].strip().strip('_').strip('*') if h: health = h if l.startswith('**Max Health:**'): m = l.split(':', 1)[1].strip().strip('_').strip('*') if m and health == '?': health = m return f"{name} ❤ {health}" def log_count(): return len(read_log_tail()) def load_book_pages(): if not BOOK_PATH.exists() or not BOOK_PATH.read_text().strip(): return ["*The story has not begun.*"] text = BOOK_PATH.read_text().strip() turns = text.split('\n## ') pages = [] for i, t in enumerate(turns): pages.append(t if i == 0 else '## ' + t) return pages or ["*The story has not begun.*"] def parse_ambience_options(): if not AMBIENCE_OPTIONS_PATH.exists(): return {} options = {} lines = AMBIENCE_OPTIONS_PATH.read_text().splitlines() in_table = False for line in lines: s = line.strip() if not s.startswith('|') or not s.endswith('|'): in_table = False continue parts = [p.strip() for p in s.split('|')] parts = [p for p in parts if p] if len(parts) < 2: continue if not in_table: in_table = True continue if all(c in '-:| ' for c in s): continue name = parts[0].lower() files = [f.strip() for f in parts[1].split(',') if f.strip()] paths = [AUDIO_DIR / f for f in files] options[name] = paths return options