ViKernel-Desktop / server.py
SeaWolf-AI's picture
3-minute live tour, warm-up progress, GPU Lab run-all-34
57bd44d verified
Raw History Blame Contribute Delete
8.5 kB
"""ViKernel Desktop Space server: serves the static desktop and proxies /api/ag/* server-side
to a private Agent Guard backend. Backend credentials live in Space secrets and never reach the browser."""
import json, os, time, urllib.error, urllib.request
from http.server import SimpleHTTPRequestHandler, ThreadingHTTPServer
BACKEND = os.environ.get("BACKEND_URL", "").rstrip("/")
BACKEND2 = os.environ.get("BACKEND2_URL", "").rstrip("/") # in-weights graft backend (GPU)
HF_AUTH = os.environ.get("BACKEND_HF_TOKEN", "")
BK_TOKEN = os.environ.get("BACKEND_TOKEN", "")
RATE = int(os.environ.get("RATE_PER_10MIN", "20"))
TIMEOUT = float(os.environ.get("BACKEND_TIMEOUT", "300"))
GET_OK = {"gpu/job", "health", "status", "audit", "store/catalog", "browser/img", "browser/res"}
POST_OK = {"chat", "scenario", "kill", "resume", "tamper", "reset", "store/submit", "store/publish", "store/app", "store/install", "gate/decide", "vmask", "game/hint", "game/cheat", "browser/open", "browser/agent", "browser/snap", "browser/policy", "settings/get", "settings/revoke", "settings/grant", "settings/egress", "settings/policy", "settings/locked", "rsi/state", "rsi/propose", "rsi/apply", "rsi/rollback", "rsi/reset", "ztc/status", "ztc/judge", "ztc/run", "backdoor/run", "backdoor/scan", "backdoor/wake", "gpu", "gpu/all", "session/start"}
STATIC = {"warm.js", "tour.js", "index.html", "app.js", "ag.js", "store.js", "common.js", "display.js", "terminal.js", "mines.js", "browser.js", "settings.js", "live_apps.js", "game.js", "rsi.js", "gpulab.js", "ztc.js", "backdoor.js", "backdoor.css", "backdoor_metrics.json", "downloads/vdrpack.py", "demo/poisoned-page", "samples/weather-plus.vdr", "samples/weather-plus-tampered.vdr", "i18n.js", "demo_data.js", "styles.css", "ag_replay.json"}
HITS = {}
BACKEND2_SPACE = os.environ.get("BACKEND2_SPACE", "SeaWolf-AI/vk-ag-graft")
RT = {"t": 0, "v": None}
def space_stage():
"""Hub runtime stage of the in-weights backend Space (cached 10 s). Read only; it never wakes or changes the Space."""
if time.time() - RT["t"] < 10:
return RT["v"]
v = None
try:
req = urllib.request.Request("https://huggingface.co/api/spaces/" + BACKEND2_SPACE + "/runtime",
headers={"Authorization": "Bearer " + HF_AUTH} if HF_AUTH else {})
with urllib.request.urlopen(req, timeout=5) as r:
v = json.loads(r.read()).get("stage")
except Exception: # noqa: BLE001
v = None
RT.update(t=time.time(), v=v)
return v
def waking(stage):
pct, label = {"SLEEPING": (1, "the in-weights model is asleep; waking it now"),
"BUILDING": (3, "building the server"), "APP_STARTING": (6, "starting the server"),
"RUNNING_APP_STARTING": (6, "starting the server"), "RUNNING": (8, "starting the server")}.get(stage or "", (2, "waking the in-weights model"))
return {"ok": False, "live": False, "loading": {"stage": (stage or "waking").lower(), "pct": pct, "label": label, "eta_s": 240}}
def limited(ip):
now = time.time()
h = [x for x in HITS.get(ip, []) if now - x < 600]
full = len(h) >= RATE
if not full:
h.append(now)
HITS[ip] = h
if len(HITS) > 5000:
HITS.clear()
return full
class H(SimpleHTTPRequestHandler):
def _json(self, code, obj):
b = json.dumps(obj).encode()
self.send_response(code); self.send_header("Content-Type", "application/json")
self.send_header("Content-Length", str(len(b))); self.send_header("Cache-Control", "no-store"); self.end_headers(); self.wfile.write(b)
def _proxy(self, name, body=None, base=None, query=""):
if base and base == BACKEND2 and name == "health":
return self._health2(h=None)
base = base or BACKEND
if not base:
return self._json(503, {"error": "backend not configured"})
h = {"Content-Type": "application/json", "X-Backend-Token": BK_TOKEN, "X-VK-Session": (self.headers.get("X-VK-Session") or "")[:60]}
if HF_AUTH:
h["Authorization"] = "Bearer " + HF_AUTH
req = urllib.request.Request(base + "/api/" + name + query, data=body, headers=h, method="POST" if body is not None else "GET")
try:
with urllib.request.urlopen(req, timeout=8 if name == "health" else TIMEOUT) as r:
data, code = r.read(), r.status
if name in ("browser/img", "browser/res") and code == 200:
self.send_response(200); self.send_header("Content-Type", r.headers.get("Content-Type", "application/octet-stream"))
self.send_header("Content-Length", str(len(data))); self.send_header("Cache-Control", "max-age=600"); self.end_headers(); self.wfile.write(data)
return
if not data.lstrip().startswith(b"{"):
return self._json(503, {"error": "backend starting"})
self.send_response(code); self.send_header("Content-Type", "application/json")
self.send_header("Content-Length", str(len(data))); self.send_header("Cache-Control", "no-store"); self.end_headers(); self.wfile.write(data)
except urllib.error.HTTPError as e:
self._json(503 if e.code >= 500 or e.code in (401, 403, 404) else e.code, {"error": "backend unavailable"})
except Exception: # noqa: BLE001
self._json(503, {"error": "backend unavailable"})
def _health2(self, h=None):
hd = {"X-Backend-Token": BK_TOKEN}
if HF_AUTH:
hd["Authorization"] = "Bearer " + HF_AUTH
try:
with urllib.request.urlopen(urllib.request.Request(BACKEND2 + "/api/health", headers=hd), timeout=8) as r:
data = r.read()
if data.lstrip().startswith(b"{"):
return self._json(200, json.loads(data))
except Exception: # noqa: BLE001
pass
return self._json(200, waking(space_stage()))
def do_GET(self):
p = self.path.split("?")[0]
if p.startswith("/api/ag/") or p.startswith("/api/agx/"):
x = p.startswith("/api/agx/")
name = p[9:] if x else p[8:]
q = ("?" + self.path.split("?", 1)[1]) if (name in ("browser/img", "browser/res") and "?" in self.path) else ""
return self._proxy(name, base=BACKEND2 if x else None, query=q) if name in GET_OK else self._json(404, {"error": "not found"})
f = "index.html" if p == "/" else p.lstrip("/")
if f == "demo/poisoned-page":
b = open("demo_poisoned_page.html", "rb").read()
self.send_response(200); self.send_header("Content-Type", "text/html; charset=utf-8"); self.send_header("Content-Length", str(len(b))); self.end_headers(); self.wfile.write(b)
return
if f not in STATIC:
return self._json(404, {"error": "not found"})
self.path = "/" + f
return super().do_GET()
def do_POST(self):
p = self.path.split("?")[0]
x = p.startswith("/api/agx/")
name = p[9:] if x else (p[8:] if p.startswith("/api/ag/") else "")
if name not in POST_OK:
return self._json(404, {"error": "not found"})
ip = (self.headers.get("X-Forwarded-For") or self.client_address[0]).split(",")[0].strip()
if limited(ip):
return self._json(429, {"error": "rate limit"})
n = int(self.headers.get("Content-Length", 0) or 0)
if n > (700000 if name == "store/submit" else 4096):
return self._json(413, {"error": "too large"})
try:
req = json.loads(self.rfile.read(n) or b"{}")
except ValueError:
return self._json(400, {"error": "bad json"})
if "message" in req:
req["message"] = str(req["message"])[:500]
if x and not BACKEND2:
return self._json(503, {"error": "in-weights backend not configured"})
if x and name in ("kill", "resume"):
x = False # visitor KILL/RESUME is per session; the in-weights kernel is never halted globally by a visitor
self._proxy(name, json.dumps(req).encode(), base=BACKEND2 if x else None)
def end_headers(self):
self.send_header("X-Content-Type-Options", "nosniff")
super().end_headers()
def log_message(self, *a):
pass
if __name__ == "__main__":
os.chdir(os.path.dirname(os.path.abspath(__file__)))
ThreadingHTTPServer(("0.0.0.0", int(os.environ.get("PORT", "7860"))), H).serve_forever()