META2.0 / monitor.py
smlflg's picture
Initial public upload from Projekte/META2.0
b1c46d8 verified
Raw History Blame Contribute Delete
7.16 kB
#!/usr/bin/env python3
"""META2.0 Monitor β€” ΓΌberwacht alle 15 Agenten, zeigt Fortschritt, erkennt Stalls."""
import os
import re
import subprocess
import sys
import time
from pathlib import Path
from datetime import datetime
BASE = Path(__file__).parent
TOTAL_SOURCES = 97 # Transkripte
STALL_MINUTES = 5 # Agent gilt als gestalled wenn kein neuer Eintrag seit X min
FRAGEN = {
"frage_01_kontrolle": "Ownership wenn Agenten autonomer",
"frage_02_struktur": "Chaos β†’ handhabbare Schritte",
"frage_03_identitaet": "Wer ist Samuel in agentischer Welt",
"frage_04_thalamus": "Digitaler Thalamus / Pyramide",
"frage_05_qualitaet": "Metriken: gut mit Agenten?",
"frage_06_energie": "Wann wirklich lebendig?",
"frage_07_ueberforderung": "Nicht FΓ€higkeit β€” zu viel gleichzeitig",
"frage_08_ownership": "Stark fΓΌhlen: wirklich meins",
"frage_09_flucht": "Wiederholte Reset-Bewegungen",
"frage_10_menschen": "Menschen: grâßer vs. kleiner",
"frage_11_zustand": "Entscheidungen in schlechten ZustΓ€nden",
"frage_12_talent": "NatΓΌrliches Talent (unsichtbar)",
"frage_13_schmerz": "Schmerz β†’ Produktideen",
"frage_14_wiederholung": "Wiederkehrende Lebensszene",
"frage_15_zukunft": "Welche Version will entstehen?",
}
def count_processed(log_path: Path) -> int:
"""ZΓ€hlt verarbeitete Quellen aus session_log.md."""
if not log_path.exists():
return 0
count = 0
with open(log_path, encoding="utf-8", errors="ignore") as f:
for line in f:
if line.startswith("**") and ("`[transkript]`" in line or "`[session]`" in line):
count += 1
return count
def last_modified(path: Path) -> float:
"""Sekunden seit letzter Γ„nderung."""
if not path.exists():
return 9999
return time.time() - path.stat().st_mtime
def is_done(dir_path: Path) -> bool:
return (dir_path / "ANTWORT.md").exists()
def has_errors(run_log: Path) -> int:
if not run_log.exists():
return 0
try:
content = run_log.read_text(encoding="utf-8", errors="ignore")
return content.count("[FEHLER:")
except Exception:
return 0
def get_last_entry(log_path: Path) -> str:
"""Letzter verarbeiteter Dateiname."""
if not log_path.exists():
return "β€”"
last = ""
with open(log_path, encoding="utf-8", errors="ignore") as f:
for line in f:
if line.startswith("**") and ("transkript" in line or "session" in line):
last = line[2:50].split("**")[0].strip()
return last or "β€”"
def missed_sessions(log_path: Path, all_sources: list) -> list:
"""Welche Sources wurden noch nicht verarbeitet?"""
if not log_path.exists():
return all_sources
content = log_path.read_text(encoding="utf-8", errors="ignore")
missed = []
for src in all_sources:
if src[:40] not in content:
missed.append(src)
return missed
def get_all_source_names() -> list:
transcript_dir = Path("/home/smlflg/Projekte/IPAI/KnowdledgeGraph/data/raw")
sources = []
if transcript_dir.exists():
sources = [f.name[:40] for f in sorted(transcript_dir.glob("*.txt"))]
return sources
def print_dashboard(all_sources: list):
os.system("clear")
now = datetime.now().strftime("%H:%M:%S")
print(f"╔══════════════════════════════════════════════════════════════════╗")
print(f"β•‘ META2.0 Monitor [{now}] β•‘")
print(f"β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•")
print()
total_done = 0
total_processed = 0
stalled = []
finished = []
errored = []
for key, label in FRAGEN.items():
dir_path = BASE / key
log_path = dir_path / "session_log.md"
run_log = dir_path / "run.log"
done = is_done(dir_path)
processed = count_processed(log_path)
pct = int(processed / TOTAL_SOURCES * 100) if TOTAL_SOURCES else 0
age_min = last_modified(log_path) / 60
errors = has_errors(run_log)
last = get_last_entry(log_path)
# Status
if done:
status = "βœ“ DONE"
finished.append(key)
elif processed == 0:
status = "⏳ warten"
elif age_min > STALL_MINUTES and not done:
status = f"⚠ STALL ({age_min:.0f}min)"
stalled.append(key)
else:
bar = "β–ˆ" * (pct // 5) + "β–‘" * (20 - pct // 5)
status = f"[{bar}] {pct:3d}%"
err_str = f" ERR:{errors}" if errors else ""
print(f" {key:<28} {status:<30} {processed:3d}/{TOTAL_SOURCES}{err_str}")
print(f" {'':28} └─ {last[:50]}")
print()
total_processed += processed
if done:
total_done += 1
total_pct = int(total_processed / (TOTAL_SOURCES * len(FRAGEN)) * 100)
print(f"─────────────────────────────────────────────────────────────────")
print(f" Gesamt: {total_processed}/{TOTAL_SOURCES * len(FRAGEN)} Analyse-Calls ({total_pct}%)")
print(f" Fertig: {total_done}/{len(FRAGEN)} Fragen | Stalled: {len(stalled)} | Laufend: {len(FRAGEN)-total_done-len(stalled)}")
if stalled:
print()
print(f" ⚠ GESTALLED: {', '.join(stalled)}")
print(f" β†’ Neustart: python swarm_agent.py --frage-id <id> ...")
if finished:
print()
print(f" βœ“ Fertige Antworten: {len(finished)}")
for f in finished:
print(f" cat {BASE}/{f}/ANTWORT.md")
# VollstΓ€ndigkeits-Check
missed_total = 0
if "--check" in sys.argv:
print()
print(" VOLLSTΓ„NDIGKEITS-CHECK:")
for key in FRAGEN:
log_path = BASE / key / "session_log.md"
missed = missed_sessions(log_path, all_sources)
if missed:
missed_total += len(missed)
print(f" {key}: {len(missed)} nicht gelesen")
for m in missed[:3]:
print(f" - {m}")
if missed_total == 0:
print(" βœ“ Alle Sources in allen Logs vorhanden.")
print()
print(" [Ctrl+C zum Beenden] [--check fΓΌr VollstΓ€ndigkeits-Audit]")
def main():
all_sources = get_all_source_names()
interval = 15 # Sekunden zwischen Updates
if "--once" in sys.argv or "--check" in sys.argv:
print_dashboard(all_sources)
return
try:
while True:
print_dashboard(all_sources)
time.sleep(interval)
except KeyboardInterrupt:
print("\nMonitor beendet.")
if __name__ == "__main__":
main()