mirror of
https://github.com/myronblair/jarvis
synced 2026-07-28 08:43:00 -05:00
Fix 3 arc reactor bugs: metrics_json→metric_data, system nesting, message→content in conversations
- guardian_loop + sitrep: SELECT metric_data (not metrics_json which does not exist) - guardian_loop: metrics are flat (cpu_percent at top level), not nested under system key - guardian_loop + sitrep: filter metric_type=system to avoid parsing proxmox blobs - guardian_loop: disk.mount key (not mountpoint) + fallback for both key names - sitrep: same metric_data + root-level key fixes - _guardian_inject_chat (x2): INSERT into conversations.content (not message) - /guardian/chat endpoint (x2): SELECT content (not message) from conversations Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+13
-13
@@ -945,10 +945,11 @@ async def guardian_loop() -> None:
|
|||||||
# ── 2. Metrics analysis ───────────────────────────────────────────
|
# ── 2. Metrics analysis ───────────────────────────────────────────
|
||||||
# Get latest metric per online agent
|
# Get latest metric per online agent
|
||||||
metrics_rows = await db_fetchall(
|
metrics_rows = await db_fetchall(
|
||||||
"""SELECT m.agent_id, r.hostname, m.metrics_json
|
"""SELECT m.agent_id, r.hostname, m.metric_data
|
||||||
FROM agent_metrics m
|
FROM agent_metrics m
|
||||||
JOIN registered_agents r ON r.agent_id = m.agent_id
|
JOIN registered_agents r ON r.agent_id = m.agent_id
|
||||||
WHERE r.status = 'online'
|
WHERE r.status = 'online'
|
||||||
|
AND m.metric_type = 'system'
|
||||||
AND m.recorded_at > DATE_SUB(NOW(), INTERVAL 5 MINUTE)
|
AND m.recorded_at > DATE_SUB(NOW(), INTERVAL 5 MINUTE)
|
||||||
ORDER BY m.recorded_at DESC"""
|
ORDER BY m.recorded_at DESC"""
|
||||||
)
|
)
|
||||||
@@ -961,8 +962,7 @@ async def guardian_loop() -> None:
|
|||||||
hostname = row["hostname"]
|
hostname = row["hostname"]
|
||||||
|
|
||||||
try:
|
try:
|
||||||
m = json.loads(row["metrics_json"]) if isinstance(row["metrics_json"], str) else row["metrics_json"]
|
sys_data = json.loads(row["metric_data"]) if isinstance(row["metric_data"], str) else row["metric_data"]
|
||||||
sys_data = m.get("system", {})
|
|
||||||
|
|
||||||
cpu = sys_data.get("cpu_percent")
|
cpu = sys_data.get("cpu_percent")
|
||||||
if cpu is not None and float(cpu) >= cpu_thresh:
|
if cpu is not None and float(cpu) >= cpu_thresh:
|
||||||
@@ -988,7 +988,7 @@ async def guardian_loop() -> None:
|
|||||||
for disk in disks:
|
for disk in disks:
|
||||||
dpct = disk.get("percent", 0)
|
dpct = disk.get("percent", 0)
|
||||||
if dpct and float(str(dpct).rstrip("%")) >= disk_thresh:
|
if dpct and float(str(dpct).rstrip("%")) >= disk_thresh:
|
||||||
mount = disk.get("mountpoint", "/")
|
mount = disk.get("mount", disk.get("mountpoint", "/"))
|
||||||
key = f"disk_{mount}"
|
key = f"disk_{mount}"
|
||||||
if await _guardian_cooldown_ok(aid, key):
|
if await _guardian_cooldown_ok(aid, key):
|
||||||
msg = f"{hostname}: Disk {mount} at {dpct}% (threshold: {disk_thresh}%)"
|
msg = f"{hostname}: Disk {mount} at {dpct}% (threshold: {disk_thresh}%)"
|
||||||
@@ -1051,7 +1051,7 @@ async def _guardian_inject_chat(message: str) -> None:
|
|||||||
"""Write a proactive JARVIS message into the conversations table so the HUD picks it up."""
|
"""Write a proactive JARVIS message into the conversations table so the HUD picks it up."""
|
||||||
try:
|
try:
|
||||||
await db_execute(
|
await db_execute(
|
||||||
"""INSERT INTO conversations (session_id, role, message, created_at)
|
"""INSERT INTO conversations (session_id, role, content, created_at)
|
||||||
VALUES ('guardian', 'assistant', %s, NOW())""",
|
VALUES ('guardian', 'assistant', %s, NOW())""",
|
||||||
(message,)
|
(message,)
|
||||||
)
|
)
|
||||||
@@ -1079,16 +1079,16 @@ async def handle_sitrep(payload: dict) -> dict:
|
|||||||
# 2. Get latest metrics per agent
|
# 2. Get latest metrics per agent
|
||||||
metrics_map = {}
|
metrics_map = {}
|
||||||
metrics_rows = await db_fetchall(
|
metrics_rows = await db_fetchall(
|
||||||
"""SELECT m.agent_id, m.metrics_json, m.recorded_at
|
"""SELECT m.agent_id, m.metric_data, m.recorded_at
|
||||||
FROM agent_metrics m
|
FROM agent_metrics m
|
||||||
WHERE m.recorded_at > DATE_SUB(NOW(), INTERVAL 10 MINUTE)
|
WHERE m.metric_type = 'system'
|
||||||
|
AND m.recorded_at > DATE_SUB(NOW(), INTERVAL 10 MINUTE)
|
||||||
ORDER BY m.recorded_at DESC"""
|
ORDER BY m.recorded_at DESC"""
|
||||||
)
|
)
|
||||||
for row in metrics_rows:
|
for row in metrics_rows:
|
||||||
if row["agent_id"] not in metrics_map:
|
if row["agent_id"] not in metrics_map:
|
||||||
try:
|
try:
|
||||||
m = json.loads(row["metrics_json"]) if isinstance(row["metrics_json"], str) else row["metrics_json"]
|
metrics_map[row["agent_id"]] = json.loads(row["metric_data"]) if isinstance(row["metric_data"], str) else row["metric_data"]
|
||||||
metrics_map[row["agent_id"]] = m
|
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@@ -1117,7 +1117,7 @@ async def handle_sitrep(payload: dict) -> dict:
|
|||||||
sys = m.get("system", {}) if m else {}
|
sys = m.get("system", {}) if m else {}
|
||||||
cpu = sys.get("cpu_percent", "?")
|
cpu = sys.get("cpu_percent", "?")
|
||||||
mem = sys.get("memory", {}).get("percent", "?") if isinstance(sys.get("memory"), dict) else "?"
|
mem = sys.get("memory", {}).get("percent", "?") if isinstance(sys.get("memory"), dict) else "?"
|
||||||
disk = next((d.get("percent","?") for d in (sys.get("disk") or []) if d.get("mountpoint") == "/"), "?")
|
disk = next((d.get("percent","?") for d in (sys.get("disk") or []) if d.get("mount","").rstrip("/") == "" or d.get("mountpoint","") == "/"), "?")
|
||||||
line = (f" {ag['hostname']} ({ag['status'].upper()}) — "
|
line = (f" {ag['hostname']} ({ag['status'].upper()}) — "
|
||||||
f"CPU:{cpu}% MEM:{mem}% DISK:{disk}%")
|
f"CPU:{cpu}% MEM:{mem}% DISK:{disk}%")
|
||||||
agent_lines.append(line)
|
agent_lines.append(line)
|
||||||
@@ -1806,7 +1806,7 @@ Keep the tone confident and action-oriented. Format with clear sections. Under 4
|
|||||||
|
|
||||||
# Store in conversations so HUD can surface it
|
# Store in conversations so HUD can surface it
|
||||||
await db_execute(
|
await db_execute(
|
||||||
"INSERT INTO conversations (session_id, role, message, created_at) VALUES ('guardian','assistant',%s,NOW())",
|
"INSERT INTO conversations (session_id, role, content, created_at) VALUES ('guardian','assistant',%s,NOW())",
|
||||||
(review_text,)
|
(review_text,)
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -2728,13 +2728,13 @@ async def guardian_chat_events(since: str = ""):
|
|||||||
"""Return proactive guardian messages injected into conversations."""
|
"""Return proactive guardian messages injected into conversations."""
|
||||||
if since:
|
if since:
|
||||||
rows = await db_fetchall(
|
rows = await db_fetchall(
|
||||||
"SELECT id, message, created_at FROM conversations "
|
"SELECT id, content, created_at FROM conversations"
|
||||||
"WHERE session_id='guardian' AND created_at > %s ORDER BY created_at ASC",
|
"WHERE session_id='guardian' AND created_at > %s ORDER BY created_at ASC",
|
||||||
(since,)
|
(since,)
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
rows = await db_fetchall(
|
rows = await db_fetchall(
|
||||||
"SELECT id, message, created_at FROM conversations "
|
"SELECT id, content, created_at FROM conversations"
|
||||||
"WHERE session_id='guardian' ORDER BY created_at DESC LIMIT 10"
|
"WHERE session_id='guardian' ORDER BY created_at DESC LIMIT 10"
|
||||||
)
|
)
|
||||||
return rows or []
|
return rows or []
|
||||||
|
|||||||
Reference in New Issue
Block a user