feat(rpg): add day/night ambient lighting, multi-coder NPCs, thought bubbles, XP/level system, CI incident alarm, and interactive Kanban modal
This commit is contained in:
+756
-139
File diff suppressed because it is too large
Load Diff
@@ -25,6 +25,44 @@ class RealtimeRPGHandler(http.server.SimpleHTTPRequestHandler):
|
|||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super().__init__(*args, directory=DIRECTORY, **kwargs)
|
super().__init__(*args, directory=DIRECTORY, **kwargs)
|
||||||
|
|
||||||
|
def do_POST(self):
|
||||||
|
parsed_url = urllib.parse.urlparse(self.path)
|
||||||
|
if parsed_url.path == '/api/issue':
|
||||||
|
content_length = int(self.headers.get('Content-Length', 0))
|
||||||
|
post_data = self.rfile.read(content_length).decode('utf-8')
|
||||||
|
try:
|
||||||
|
payload = json.loads(post_data)
|
||||||
|
project = payload.get('project', 'camper-knowledge-graph')
|
||||||
|
title = payload.get('title', '').strip()
|
||||||
|
body = payload.get('body', 'Erstellt über Agent RPG Terminal').strip()
|
||||||
|
if not title:
|
||||||
|
self.send_response(400)
|
||||||
|
self.end_headers()
|
||||||
|
self.wfile.write(json.dumps({"error": "Title is required"}).encode('utf-8'))
|
||||||
|
return
|
||||||
|
|
||||||
|
req = urllib.request.Request(
|
||||||
|
f"{GITEA_BASE_URL}/repos/openclaw/{project}/issues",
|
||||||
|
data=json.dumps({"title": title, "body": body}).encode('utf-8'),
|
||||||
|
headers={'Authorization': f'token {GITEA_TOKEN}', 'Content-Type': 'application/json'}
|
||||||
|
)
|
||||||
|
with urllib.request.urlopen(req, timeout=3) as resp:
|
||||||
|
resp_data = json.loads(resp.read().decode())
|
||||||
|
self.send_response(201)
|
||||||
|
self.send_header('Content-Type', 'application/json')
|
||||||
|
self.send_header('Access-Control-Allow-Origin', '*')
|
||||||
|
self.end_headers()
|
||||||
|
self.wfile.write(json.dumps({"success": True, "issue": resp_data}).encode('utf-8'))
|
||||||
|
except Exception as e:
|
||||||
|
self.send_response(500)
|
||||||
|
self.send_header('Content-Type', 'application/json')
|
||||||
|
self.send_header('Access-Control-Allow-Origin', '*')
|
||||||
|
self.end_headers()
|
||||||
|
self.wfile.write(json.dumps({"error": str(e)}).encode('utf-8'))
|
||||||
|
else:
|
||||||
|
self.send_response(404)
|
||||||
|
self.end_headers()
|
||||||
|
|
||||||
def do_GET(self):
|
def do_GET(self):
|
||||||
parsed_url = urllib.parse.urlparse(self.path)
|
parsed_url = urllib.parse.urlparse(self.path)
|
||||||
if parsed_url.path == '/api/status':
|
if parsed_url.path == '/api/status':
|
||||||
@@ -66,6 +104,11 @@ class RealtimeRPGHandler(http.server.SimpleHTTPRequestHandler):
|
|||||||
"ci_status": "PASSING",
|
"ci_status": "PASSING",
|
||||||
"connected": True
|
"connected": True
|
||||||
},
|
},
|
||||||
|
"metrics": {
|
||||||
|
"active_agents": 0,
|
||||||
|
"token_velocity": 0,
|
||||||
|
"system_health": 100
|
||||||
|
},
|
||||||
"agents": {
|
"agents": {
|
||||||
"coder1": {
|
"coder1": {
|
||||||
"name": f"Coder #{target_project[:4].upper()}",
|
"name": f"Coder #{target_project[:4].upper()}",
|
||||||
@@ -144,8 +187,9 @@ class RealtimeRPGHandler(http.server.SimpleHTTPRequestHandler):
|
|||||||
|
|
||||||
# 2. Collect Gitea Live PRs & Issues for Whiteboard Kanban strictly for target_project
|
# 2. Collect Gitea Live PRs & Issues for Whiteboard Kanban strictly for target_project
|
||||||
try:
|
try:
|
||||||
# Check Gitea Actions API for actively running workflows
|
# Check Gitea Actions API for actively running workflows and recent failure
|
||||||
active_runs_count = 0
|
active_runs_count = 0
|
||||||
|
latest_run_failed = False
|
||||||
try:
|
try:
|
||||||
req_runs = urllib.request.Request(
|
req_runs = urllib.request.Request(
|
||||||
f"{GITEA_BASE_URL}/repos/openclaw/{target_project}/actions/runs?limit=10",
|
f"{GITEA_BASE_URL}/repos/openclaw/{target_project}/actions/runs?limit=10",
|
||||||
@@ -153,14 +197,22 @@ class RealtimeRPGHandler(http.server.SimpleHTTPRequestHandler):
|
|||||||
)
|
)
|
||||||
with urllib.request.urlopen(req_runs, timeout=2) as resp:
|
with urllib.request.urlopen(req_runs, timeout=2) as resp:
|
||||||
runs_data = json.loads(resp.read().decode())
|
runs_data = json.loads(resp.read().decode())
|
||||||
for r in runs_data.get("workflow_runs", []):
|
runs = runs_data.get("workflow_runs", [])
|
||||||
|
for r in runs:
|
||||||
if r.get("status") in ["running", "waiting", "queued"]:
|
if r.get("status") in ["running", "waiting", "queued"]:
|
||||||
active_runs_count += 1
|
active_runs_count += 1
|
||||||
|
if runs and runs[0].get("status") == "completed" and runs[0].get("conclusion") in ["failure", "cancelled"]:
|
||||||
|
latest_run_failed = True
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
status["gitea"]["active_ci_jobs"] = active_runs_count
|
status["gitea"]["active_ci_jobs"] = active_runs_count
|
||||||
status["gitea"]["ci_status"] = "BUILDING" if active_runs_count > 0 else "PASSING"
|
if active_runs_count > 0:
|
||||||
|
status["gitea"]["ci_status"] = "BUILDING"
|
||||||
|
elif latest_run_failed:
|
||||||
|
status["gitea"]["ci_status"] = "FAILURE"
|
||||||
|
else:
|
||||||
|
status["gitea"]["ci_status"] = "PASSING"
|
||||||
|
|
||||||
# Fetch Open Pull Requests
|
# Fetch Open Pull Requests
|
||||||
req_prs = urllib.request.Request(
|
req_prs = urllib.request.Request(
|
||||||
@@ -389,6 +441,14 @@ class RealtimeRPGHandler(http.server.SimpleHTTPRequestHandler):
|
|||||||
status["agents"]["reviewer"]["lastAction"] = "Idle / Bereit"
|
status["agents"]["reviewer"]["lastAction"] = "Idle / Bereit"
|
||||||
status["agents"]["reviewer"]["liveLog"] = ["PR Watcher aktiv"]
|
status["agents"]["reviewer"]["liveLog"] = ["PR Watcher aktiv"]
|
||||||
|
|
||||||
|
status["agents"]["coder_instances"] = coder_sessions
|
||||||
|
|
||||||
|
# Calculate live system metrics
|
||||||
|
active_count = sum(1 for a in status["agents"].values() if isinstance(a, dict) and a.get("state") == "WORKING")
|
||||||
|
status["metrics"]["active_agents"] = active_count
|
||||||
|
status["metrics"]["token_velocity"] = (active_count * 185) + (total_active * 240)
|
||||||
|
status["metrics"]["system_health"] = 90 if status["gitea"]["ci_status"] == "FAILURE" else 100
|
||||||
|
|
||||||
return status
|
return status
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|||||||
Reference in New Issue
Block a user