feat(rpg): dynamically display parallel coder instance count (x2, x3) on active dev desk

This commit is contained in:
2026-10-03 22:05:42 +02:00
parent b3bb71f029
commit 36616420e3
2 changed files with 31 additions and 16 deletions
+12 -3
View File
@@ -722,6 +722,7 @@
agents[key].state = agentData.state; agents[key].state = agentData.state;
agents[key].currentTask = agentData.currentTask; agents[key].currentTask = agentData.currentTask;
agents[key].lastAction = agentData.lastAction; agents[key].lastAction = agentData.lastAction;
agents[key].parallelCount = agentData.parallelCount || 0;
if (agentData.liveLog && agentData.liveLog.length > 0) { if (agentData.liveLog && agentData.liveLog.length > 0) {
agents[key].liveLog = agentData.liveLog; agents[key].liveLog = agentData.liveLog;
} }
@@ -1416,15 +1417,23 @@
ctx.fillText("💾 DELEGATE", x - 6, y + 3 + bounce); ctx.fillText("💾 DELEGATE", x - 6, y + 3 + bounce);
} else if (agent.state === 'WORKING') { } else if (agent.state === 'WORKING') {
const count = agent.parallelCount || 1;
const bubbleW = (count > 1) ? 54 : 40;
ctx.fillStyle = "#064e3b"; ctx.fillStyle = "#064e3b";
ctx.fillRect(x - 10, y - 10, 40, 20); ctx.fillRect(x - 10, y - 10, bubbleW, 20);
ctx.strokeStyle = "#34d399"; ctx.strokeStyle = (count > 1) ? "#facc15" : "#34d399";
ctx.lineWidth = 1.5; ctx.lineWidth = 1.5;
ctx.strokeRect(x - 10, y - 10, 40, 20); ctx.strokeRect(x - 10, y - 10, bubbleW, 20);
ctx.font = "10px 'Press Start 2P'"; ctx.font = "10px 'Press Start 2P'";
ctx.fillStyle = "#34d399"; ctx.fillStyle = "#34d399";
ctx.fillText("</>", x - 4, y + 4); ctx.fillText("</>", x - 4, y + 4);
if (count > 1) {
ctx.font = "10px 'Press Start 2P'";
ctx.fillStyle = "#facc15";
ctx.fillText(`x${count}`, x + 24, y + 4);
}
} else if (agent.state === 'THINKING') { } else if (agent.state === 'THINKING') {
const bob = Math.sin(time * 0.01) * 2; const bob = Math.sin(time * 0.01) * 2;
ctx.fillStyle = "#713f12"; ctx.fillStyle = "#713f12";
+19 -13
View File
@@ -232,9 +232,8 @@ class RealtimeRPGHandler(http.server.SimpleHTTPRequestHandler):
lead_last_pulse_seconds = 999 lead_last_pulse_seconds = 999
lead_recent_logs = [] lead_recent_logs = []
coder_session_active = False coder_sessions = []
coder_task_desc = "" active_coder_count = 0
coder_recent_logs = []
try: try:
search_patterns = [ search_patterns = [
@@ -248,7 +247,7 @@ class RealtimeRPGHandler(http.server.SimpleHTTPRequestHandler):
rollout_files = sorted(all_rollout_files, key=os.path.getmtime, reverse=True) rollout_files = sorted(all_rollout_files, key=os.path.getmtime, reverse=True)
for rf in rollout_files[:10]: for rf in rollout_files[:15]:
age_seconds = round(time.time() - os.path.getmtime(rf), 1) age_seconds = round(time.time() - os.path.getmtime(rf), 1)
with open(rf, 'r') as fp: with open(rf, 'r') as fp:
lines = fp.readlines() lines = fp.readlines()
@@ -300,11 +299,14 @@ class RealtimeRPGHandler(http.server.SimpleHTTPRequestHandler):
session_prompt = first_prompt or "Heartbeat / Backlog Monitoring" session_prompt = first_prompt or "Heartbeat / Backlog Monitoring"
# Map to specific agent # Map to specific agent
if session_role == "coder" and not coder_session_active: if session_role == "coder":
if not is_completed and age_seconds < 60: if not is_completed and age_seconds < 60:
coder_session_active = True active_coder_count += 1
coder_task_desc = session_prompt[:120] coder_sessions.append({
coder_recent_logs = recent_logs "task": session_prompt[:120],
"logs": recent_logs,
"age": age_seconds
})
elif session_role == "lead" and not lead_heartbeat_active: elif session_role == "lead" and not lead_heartbeat_active:
lead_last_pulse_seconds = age_seconds lead_last_pulse_seconds = age_seconds
if not is_completed and age_seconds < 60: if not is_completed and age_seconds < 60:
@@ -321,23 +323,27 @@ class RealtimeRPGHandler(http.server.SimpleHTTPRequestHandler):
status["lead_heartbeat"] = {"error": str(e), "is_beating": False, "last_pulse_seconds_ago": 999} status["lead_heartbeat"] = {"error": str(e), "is_beating": False, "last_pulse_seconds_ago": 999}
# 4. Derive Agent RPG States STRICTLY for target_project # 4. Derive Agent RPG States STRICTLY for target_project
# Coder 1 # Coder 1 (supports multi-instance count x2, x3)
if "coder-tasks" in latest_active_tasks: if "coder-tasks" in latest_active_tasks:
task = latest_active_tasks["coder-tasks"] task = latest_active_tasks["coder-tasks"]
status["agents"]["coder1"]["state"] = "WORKING" status["agents"]["coder1"]["state"] = "WORKING"
status["agents"]["coder1"]["currentTask"] = f"Task #{task.get('issueNumber', '')}: {task.get('title', 'Coding')}" status["agents"]["coder1"]["currentTask"] = f"Task #{task.get('issueNumber', '')}: {task.get('title', 'Coding')}"
status["agents"]["coder1"]["lastAction"] = "BullMQ: Active Code Session" status["agents"]["coder1"]["lastAction"] = "BullMQ: Active Code Session"
status["agents"]["coder1"]["liveLog"] = ["git checkout feature-branch", "npm run test", "git commit -m 'feat: implementation'"] status["agents"]["coder1"]["liveLog"] = ["git checkout feature-branch", "npm run test", "git commit -m 'feat: implementation'"]
elif coder_session_active: status["agents"]["coder1"]["parallelCount"] = max(1, active_coder_count)
elif active_coder_count > 0:
status["agents"]["coder1"]["state"] = "WORKING" status["agents"]["coder1"]["state"] = "WORKING"
status["agents"]["coder1"]["currentTask"] = f"Aktiv: {coder_task_desc or 'Coding Session'}" primary_coder = coder_sessions[0]
status["agents"]["coder1"]["lastAction"] = "OpenClaw Coder Turn Active" status["agents"]["coder1"]["currentTask"] = f"Aktiv ({active_coder_count}x): {primary_coder['task'] or 'Coding Session'}"
status["agents"]["coder1"]["liveLog"] = coder_recent_logs or ["Implementing feature / bugfix..."] status["agents"]["coder1"]["lastAction"] = f"OpenClaw Coder Turn ({active_coder_count} parallel)"
status["agents"]["coder1"]["liveLog"] = primary_coder["logs"] or ["Implementing feature / bugfix..."]
status["agents"]["coder1"]["parallelCount"] = active_coder_count
else: else:
status["agents"]["coder1"]["state"] = "IDLE" status["agents"]["coder1"]["state"] = "IDLE"
status["agents"]["coder1"]["currentTask"] = f"Keine offenen Tasks in {target_project}" status["agents"]["coder1"]["currentTask"] = f"Keine offenen Tasks in {target_project}"
status["agents"]["coder1"]["lastAction"] = "Idle / Bereit" status["agents"]["coder1"]["lastAction"] = "Idle / Bereit"
status["agents"]["coder1"]["liveLog"] = ["Wartet auf neue Queue-Aufgaben..."] status["agents"]["coder1"]["liveLog"] = ["Wartet auf neue Queue-Aufgaben..."]
status["agents"]["coder1"]["parallelCount"] = 0
# Coder 2 (Tester / Staging) # Coder 2 (Tester / Staging)
if "tester-tasks" in latest_active_tasks or "deployments" in latest_active_tasks: if "tester-tasks" in latest_active_tasks or "deployments" in latest_active_tasks: