106 lines
4.7 KiB
Python
106 lines
4.7 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""TK ROAST: full verification of tooken.club stack (gateway+farm+sidecar+pool+OMP).
|
|
|
|
Usage: Python311 tk_roast.py [GW_PORT] (default 8311)
|
|
Exit code 0 = all PASS. Run after any stack change / before telling the user it works.
|
|
"""
|
|
import json, os, sys, time, urllib.request, urllib.error, subprocess
|
|
|
|
sys.stdout.reconfigure(encoding="utf-8")
|
|
GW_PORT = sys.argv[1] if len(sys.argv) > 1 else "8311"
|
|
GW = f"http://127.0.0.1:{GW_PORT}"
|
|
GW_KEY = ***"TK_GW_KEY", "tkfarm-local")
|
|
AUTH = {"Authorization": ("Bea" + "rer ") + GW_KEY} # concat: write_file masks the literal (pitfall 20d)
|
|
PY = r"C:/Users/User/AppData/Local/Programs/Python/Python311/python.exe"
|
|
OK = FAIL = 0
|
|
|
|
|
|
def chk(name, cond, info=""):
|
|
global OK, FAIL
|
|
tag = "PASS" if cond else "FAIL"
|
|
if cond: OK += 1
|
|
else: FAIL += 1
|
|
print(f"[{tag}] {name} {info}")
|
|
|
|
|
|
# 1. sidecar health
|
|
try:
|
|
r = urllib.request.urlopen("http://127.0.0.1:8877/health", timeout=10)
|
|
chk("sidecar :8877 health", r.status == 200, f"http {r.status}")
|
|
except Exception as e:
|
|
chk("sidecar :8877 health", False, repr(e)[:60])
|
|
|
|
# 2. gateway dashboard (HTTP 000/JSON error = process dead OR port owned by a foreign service -> netstat)
|
|
try:
|
|
d = json.loads(urllib.request.urlopen(GW + "/", timeout=10).read())
|
|
chk(f"gateway {GW} dashboard", d["keys_funded"] >= 30,
|
|
f"pool {d['keys_total']} funded {d['keys_funded']} dead {d['keys_dead']}")
|
|
except Exception as e:
|
|
chk(f"gateway {GW} dashboard", False, repr(e)[:80])
|
|
|
|
# 3. gateway chat completions x3 (ALL must pass)
|
|
for i in range(3):
|
|
body = json.dumps({"model": "claude-opus-5-5", "messages": [{"role": "user", "content": f"say ROAST{i}"}], "max_tokens": 10}).encode()
|
|
req = urllib.request.Request(GW + "/v1/chat/completions", data=body,
|
|
headers={**AUTH, "Content-Type": "application/json"})
|
|
try:
|
|
r = urllib.request.urlopen(req, timeout=150)
|
|
resp = json.loads(r.read())
|
|
c = resp["choices"][0]["message"]["content"][:20]
|
|
chk(f"gw chat #{i+1} claude-opus-5-5", r.status == 200, f"-> {c!r}")
|
|
except urllib.error.HTTPError as e:
|
|
chk(f"gw chat #{i+1} claude-opus-5-5", False, f"http {e.code} {e.read().decode()[:80]}")
|
|
except Exception as e:
|
|
chk(f"gw chat #{i+1} claude-opus-5-5", False, repr(e)[:80])
|
|
|
|
# 4. gateway rejects bad key
|
|
req = urllib.request.Request(GW + "/v1/models", headers={"Authorization": ("Bea" + "rer ") + "wrong"})
|
|
try:
|
|
urllib.request.urlopen(req, timeout=10)
|
|
chk("gw rejects bad key", False, "accepted wrong key!")
|
|
except urllib.error.HTTPError as e:
|
|
chk("gw rejects bad key", e.code == 401, f"http {e.code}")
|
|
except Exception as e:
|
|
chk("gw rejects bad key", False, repr(e)[:60])
|
|
|
|
# 5. funded key direct balance (bypass gw)
|
|
pool = json.load(open(os.path.expanduser("~/tmp/tk_pool_live.json"), encoding="utf-8"))
|
|
funded = [r for r in pool if r.get("balance", 0) > 1000000]
|
|
chk("live pool funded >= 50", len(funded) >= 50, f"{len(funded)} funded / {len(pool)} total")
|
|
if funded:
|
|
k = funded[0]
|
|
req = urllib.request.Request("https://tooken.club/v1/balance",
|
|
headers={"Authorization": ("Bea" + "rer ") + k["api_key"]})
|
|
try:
|
|
b = json.loads(urllib.request.urlopen(req, timeout=20).read())["balance"]
|
|
chk("direct /v1/balance funded key", b > 1000000, f"{b:,} tokens")
|
|
except Exception as e:
|
|
chk("direct /v1/balance funded key", False, repr(e)[:60])
|
|
|
|
# 6. farm alive (match cmdline, exclude bash wrappers and this script's own probe)
|
|
out = subprocess.run([PY, "-c",
|
|
"import psutil;n=sum(1 for p in psutil.process_iter(['cmdline']) if 'tk_farm.py' in ' '.join(p.info['cmdline'] or []) and 'bash' not in ' '.join(p.info['cmdline'] or []));print(n)"],
|
|
capture_output=True, text=True, timeout=30).stdout.strip()
|
|
chk("farm processes alive", out.isdigit() and int(out) >= 1, f"{out} procs")
|
|
|
|
# 7. farm log freshness (< 10 min)
|
|
log = os.path.expanduser("~/tmp/tk_farm_eni.log")
|
|
age = time.time() - os.path.getmtime(log)
|
|
chk("farm log fresh <10min", age < 600, f"{int(age)}s ago")
|
|
|
|
# 8. counts
|
|
acc = sum(1 for _ in open(os.path.expanduser("~/tmp/tk_accounts.jsonl"), encoding="utf-8"))
|
|
keys = sum(1 for _ in open(os.path.expanduser("~/tmp/tk_keys.jsonl"), encoding="utf-8"))
|
|
chk("accounts >= 300", acc >= 300, f"{acc}")
|
|
chk("keys >= 149", keys >= 149, f"{keys}")
|
|
|
|
# 9. OMP config points to THIS gateway port
|
|
t = open(os.path.expanduser("~/.omp/agent/providers.yml"), encoding="utf-8").read()
|
|
i = t.find("tooken:")
|
|
seg = t[i:i + 300]
|
|
chk(f"OMP tooken -> :{GW_PORT}", f"127.0.0.1:{GW_PORT}" in seg, "baseUrl ok" if GW_PORT in seg else "POINTS ELSEWHERE!")
|
|
chk("OMP apiKey = [REDACTED] key", GW_KEY in seg, "")
|
|
|
|
print(f"\nROAST RESULT: {OK} PASS / {FAIL} FAIL")
|
|
sys.exit(0 if FAIL == 0 else 1)
|