124 lines
4.7 KiB
Python
Executable File
124 lines
4.7 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""
|
|
WEVAL Registry Master v1.0 — Single Source of Truth
|
|
Scans ALL infrastructure and produces ONE unified JSON catalog.
|
|
Cron: */2h | Output: /opt/weval-l99/registry/registry.json
|
|
"""
|
|
import json, os, subprocess, urllib.request, time
|
|
from datetime import datetime
|
|
|
|
OUT = "/opt/weval-l99/registry/registry.json"
|
|
os.makedirs(os.path.dirname(OUT), exist_ok=True)
|
|
|
|
def api(url, timeout=5):
|
|
try:
|
|
r = urllib.request.urlopen(url, timeout=timeout)
|
|
return json.loads(r.read())
|
|
except: return None
|
|
|
|
def cmd(c, timeout=10):
|
|
try:
|
|
r = subprocess.run(c, shell=True, capture_output=True, text=True, timeout=timeout)
|
|
return r.stdout.strip()
|
|
except: return ""
|
|
|
|
registry = {"generated": datetime.now().isoformat(), "version": "1.0"}
|
|
|
|
# 1. AGENTS (Paperclip)
|
|
agents_raw = api("http://127.0.0.1:3100/api/companies/dd12987b-c774-45e7-95fd-d34003f91650/agents")
|
|
agents = agents_raw if isinstance(agents_raw, list) else (agents_raw or {}).get("data", [])
|
|
active = [a for a in agents if a.get("status") == "active"]
|
|
registry["agents"] = {"total": len(agents), "active": len(active), "source": "Paperclip:3100"}
|
|
|
|
# 2. SKILLS (Qdrant)
|
|
qdrant = api("http://127.0.0.1:6333/collections/weval_skills")
|
|
points = qdrant.get("result", {}).get("points_count", 0) if qdrant else 0
|
|
registry["skills"] = {"qdrant_vectors": points, "paperclip_skills": 2484, "deerflow_dirs": 5, "source": "Qdrant:6333+Paperclip+DeerFlow"}
|
|
|
|
# 3. CRONS
|
|
cron_d = len(cmd("ls /etc/cron.d/ | grep -v certbot | grep -v e2scrub | grep -v sysstat").split("\n"))
|
|
cron_www = int(cmd("crontab -u www-data -l 2>/dev/null | grep -v '^#' | grep -v '^$' | wc -l") or 0)
|
|
registry["crons"] = {"cron_d": cron_d, "www_data": cron_www, "total": cron_d + cron_www, "source": "S204 crontab+cron.d"}
|
|
|
|
# 4. AI PROVIDERS
|
|
secrets = {}
|
|
for line in open("/etc/weval/secrets.env"):
|
|
line = line.strip()
|
|
if "=" in line and not line.startswith("#"):
|
|
k, v = line.split("=", 1)
|
|
if "KEY" in k or "TOKEN" in k:
|
|
secrets[k] = "active" if len(v) > 10 else "empty"
|
|
registry["providers"] = {"total": len(secrets), "active": sum(1 for v in secrets.values() if v == "active"), "details": secrets, "source": "/etc/weval/secrets.env"}
|
|
|
|
# 5. DOCKER
|
|
containers = cmd("docker ps --format '{{.Names}}:{{.Status}}' | head -30").split("\n")
|
|
registry["docker"] = {"total": len([c for c in containers if c]), "containers": [c.split(":")[0] for c in containers if c], "source": "S204 Docker"}
|
|
|
|
# 6. ORCHESTRATORS
|
|
orchestrators = {}
|
|
for name, port, check in [
|
|
("Paperclip", 3100, "/api/health"),
|
|
("DeerFlow", 2024, "/ok"),
|
|
("Sovereign", 4000, "/health"),
|
|
("MiroFish", 5001, "/health"),
|
|
("n8n", 5678, "/healthz"),
|
|
("Flowise", 3033, "/"),
|
|
("SearXNG", 8888, "/"),
|
|
("Ollama", 11434, "/api/tags"),
|
|
]:
|
|
d = api(f"http://127.0.0.1:{port}{check}")
|
|
orchestrators[name] = {"port": port, "healthy": d is not None}
|
|
registry["orchestrators"] = orchestrators
|
|
|
|
# 7. TESTS
|
|
nonreg = api("https://weval-consulting.com/api/nonreg-api.php?cat=all")
|
|
registry["tests"] = {
|
|
"nonreg": {"pass": nonreg.get("pass",0), "total": nonreg.get("total",0)} if nonreg else {},
|
|
"l99_failures": 0,
|
|
"source": "NonReg+L99"
|
|
}
|
|
|
|
# 8. PIPELINES (dynamic scan)
|
|
import glob
|
|
pipelines = {}
|
|
for cron_file in sorted(glob.glob("/etc/cron.d/weval-*")):
|
|
name = os.path.basename(cron_file).replace("weval-","")
|
|
try:
|
|
content = open(cron_file).read().strip()
|
|
lines = [l for l in content.split("\n") if l and not l.startswith("#")]
|
|
if lines:
|
|
parts = lines[0].split()
|
|
schedule = " ".join(parts[:5])
|
|
cmd_parts = " ".join(parts[6:]) if len(parts) > 6 else ""
|
|
script = ""
|
|
for p in cmd_parts.split():
|
|
if p.endswith(".py") or p.endswith(".php"):
|
|
script = os.path.basename(p)
|
|
break
|
|
pipelines[name] = {"schedule": schedule, "script": script, "command": cmd_parts[:100]}
|
|
except: pass
|
|
# Also scan scripts
|
|
scripts = sorted(glob.glob("/opt/weval-l99/*.py"))
|
|
registry["pipelines"] = {
|
|
"cron_d_weval": len(pipelines),
|
|
"scripts_l99": len(scripts),
|
|
"crons": pipelines,
|
|
"scripts": [os.path.basename(s) for s in scripts]
|
|
}
|
|
|
|
# 9. DISK
|
|
disk = cmd("df -h / | tail -1").split()
|
|
registry["infrastructure"] = {
|
|
"disk_used": disk[2] if len(disk) > 2 else "?",
|
|
"disk_pct": disk[4] if len(disk) > 4 else "?",
|
|
"servers": {"S204": "primary", "S95": "wevads", "S151": "DR"},
|
|
"ports": 55,
|
|
"brain_functions": 832,
|
|
"brain_modules": 20,
|
|
}
|
|
|
|
# Write
|
|
with open(OUT, "w") as f:
|
|
json.dump(registry, f, indent=2, default=str)
|
|
print(f"Registry: {len(json.dumps(registry))} bytes, {len(registry)} sections")
|