From 87ffa7ec60ba272d9fd4e817b8aaf5a3f69e9270 Mon Sep 17 00:00:00 2001 From: timmy Date: Wed, 8 Jul 2026 19:27:17 +0000 Subject: [PATCH] seed repo scaffold --- services/router/server.py | 69 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 services/router/server.py diff --git a/services/router/server.py b/services/router/server.py new file mode 100644 index 0000000..b19eadf --- /dev/null +++ b/services/router/server.py @@ -0,0 +1,69 @@ +"""Router: mic/WebSocket -> brain -> TTS -> avatar -> RTMP streaming glue.""" +import os, json, queue, threading, time +from pathlib import Path +from flask import Flask, request, jsonify +from flask_sock import Sock +import requests + +app = Flask(__name__) +sock = Sock(app) + +BRAIN = os.getenv("BRAIN_URL", "http://brain:11434") +TTS = os.getenv("TTS_URL", "http://tts:5002") +PERSONA = os.getenv("PERSONA", "/app/persona.yaml") + +response_q = queue.Queue() + +def build_prompt(user_text): + return user_text + +def brain_reply(prompt): + try: + r = requests.post(f"{BRAIN}/api/generate", json={"model":"llama3.2:1b","prompt":prompt,"stream":False}, timeout=20) + return r.json().get("response","") + except Exception as e: + return f"*static from the aether* {e}" + +def tts_synth(text): + try: + r = requests.post(f"{TTS}/synthesize", json={"text": text}, timeout=20) + return r.content + except Exception: + return b"" + +def run_job(text): + prompt = build_prompt(text) + reply = brain_reply(prompt) + audio = tts_synth(reply) + response_q.put({"text": reply, "audio": audio}) + +@app.post("/say") +def say(): + data = request.get_json(force=True) + text = data.get("text", "") + if not text: + return jsonify({"error": "text required"}), 400 + threading.Thread(target=run_job, args=(text,), daemon=True).start() + return jsonify({"queued": True}) + +@app.get("/health") +def health(): + return {"status": "ok", "queued": response_q.qsize()} + +@sock.route("/ws") +def ws(ws): + while True: + msg = ws.receive() + if msg is None: + break + try: + data = json.loads(msg) + except Exception: + continue + if data.get("type") == "text": + run_job(data.get("text","")) + result = response_q.get() + ws.send(json.dumps(result)) + +if __name__ == "__main__": + app.run(host="0.0.0.0", port=8787) \ No newline at end of file