from __future__ import annotations import json import threading import webbrowser from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer from pathlib import Path HOST = "127.0.0.1" PORT = 8765 SETTINGS_PATH = Path(__file__).with_name("local_settings.json") PAGE = """ Gemma Heretic Demo Settings

Gemma Heretic Demo Settings

These defaults apply the next time the local app starts.

""" class SettingsHandler(BaseHTTPRequestHandler): def _send(self, status: int, content_type: str, body: bytes) -> None: self.send_response(status) self.send_header("Content-Type", content_type) self.send_header("Content-Length", str(len(body))) self.end_headers() self.wfile.write(body) def do_GET(self) -> None: if self.path == "/": self._send(200, "text/html; charset=utf-8", PAGE.encode()) return if self.path == "/api/settings": self._send(200, "application/json", SETTINGS_PATH.read_bytes()) return self._send(404, "text/plain", b"Not found") def do_POST(self) -> None: if self.path != "/api/settings": self._send(404, "text/plain", b"Not found") return length = int(self.headers.get("Content-Length", "0")) try: data = json.loads(self.rfile.read(length)) required = { "model_id", "system_prompt", "thinking", "max_new_tokens", "temperature", "top_p", "top_k", "repetition_penalty", "max_input_tokens", "history_messages", } if set(data) != required: raise ValueError("Unexpected settings fields.") SETTINGS_PATH.write_text( json.dumps(data, indent=2, ensure_ascii=False) + "\n", encoding="utf-8", ) except (ValueError, TypeError, json.JSONDecodeError): self._send(400, "application/json", b'{"ok":false}') return self._send(200, "application/json", b'{"ok":true}') def log_message(self, format: str, *args: object) -> None: return if __name__ == "__main__": server = ThreadingHTTPServer((HOST, PORT), SettingsHandler) url = f"http://{HOST}:{PORT}" threading.Timer(0.4, webbrowser.open, args=(url,)).start() print(f"Settings page: {url}") print("Press Ctrl+C to stop.") server.serve_forever()