"""Minimal live wizard portal: persona-aware chat over WebSocket.""" import os, json from pathlib import Path from flask import Flask, render_template_string from flask_sock import Sock import yaml app = Flask(__name__) sock = Sock(app) ROOT = Path(os.getenv("PORTAL_ROOT", Path(__file__).resolve().parent)) PERSONA_PATH = ROOT / "persona.yaml" with open(PERSONA_PATH, "r", encoding="utf-8") as f: persona = yaml.safe_load(f) or {} PAGE = """ Timmy Time — Live Wizard Portal
""" @app.get("/") def index(): return render_template_string(PAGE) @app.get("/health") def health(): return {"status":"ok","persona":persona.get("wizard",{}).get("name","Unknown")} @sock.route("/ws") def ws(ws): wizard = persona.get("wizard", {}) catchphrases = wizard.get("catchphrases", []) while True: msg = ws.receive() if msg is None: break try: data = json.loads(msg) except Exception: continue if data.get("type") == "text": text = data.get("text", "").strip() prefix = catchphrases[0] if catchphrases else "The mists reveal:" reply = f"{prefix} {text}" ws.send(json.dumps({"text": reply})) if __name__ == "__main__": app.run(host="0.0.0.0", port=8787)