"""Persisted, live-editable bot persona (the brain's system prompt). The dashboard lets the user view and edit the bot's system prompt at runtime. The brain reads the current persona on every turn, so an edit takes effect on the next reply with no restart. The text is persisted to disk so it survives a restart; when no override file exists the caller's default (``ClaudeBrain.PERSONA``) is used. Path: ``$WSAI_PROMPT_PATH`` or ``~/.config/wsai/persona.txt`` (disk, never a RAM-backed tmpfs). """ from __future__ import annotations import os import threading from pathlib import Path _LOCK = threading.Lock() def _path() -> Path: override = os.environ.get("WSAI_PROMPT_PATH") return Path(override) if override else (Path.home() / ".config" / "wsai" / "persona.txt") def get_persona(default: str) -> str: """Return the saved persona override, or ``default`` if none is set.""" try: with _LOCK: text = _path().read_text(encoding="utf-8") except OSError: return default return text if text.strip() else default def set_persona(text: str) -> None: """Persist a new persona. Blank text clears the override (reverts to default).""" p = _path() with _LOCK: p.parent.mkdir(parents=True, exist_ok=True) if text and text.strip(): p.write_text(text, encoding="utf-8") else: p.unlink(missing_ok=True) def is_overridden() -> bool: """True when a non-empty override file is in effect.""" try: with _LOCK: return bool(_path().read_text(encoding="utf-8").strip()) except OSError: return False