Files
watch_sceen_ai/wsai/prompt_store.py
EJClaw df07224feb feat(dashboard): live-editable bot prompt via popup (view/edit/save)
Adds a persisted, runtime-editable system prompt. The brain reads the persona
on every turn (prompt_store.get_persona), so a dashboard edit applies to the
next reply with no restart; blank clears the override back to the built-in
PERSONA. New endpoints GET/POST /api/prompt, and a reusable modal popup
(뒤로가기 + 수정/저장) that later white/blacklist features will share.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-08-22 11:20:57 +09:00

55 lines
1.6 KiB
Python

"""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