File size: 8,503 Bytes
57bd44d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
"""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()