Neue Ansicht 'Von allein': Skills + Vorschlags-Bilanz der Box (+ schlafende P1-Basis)
User-Wunsch 15.07.: EIN Viewpoint, was die Box selbst geleistet hat - Chronik ist zu kompliziert. Neue Operativ-Ansicht #eigenleben: - Skills aus ~/.hermes/skills (= Lucys Satz) mit Klartext-Beschreibung, Nutzungszaehler (.usage.json) und Herkunft (selbst erstellt / von uns gebaut / mitgeliefert), aufklappbar mit vollem SKILL.md. - Vorschlags-Bilanz: angenommen (Auftragsbuch-Chronik) + abgelehnt mit Grund (Lern-Journal) als eine Timeline + Zaehler. Backend: services/eigenleben.py + routers/eigenleben.py (read-only). Mit an Bord (User-Ja, schlafend): P1-Basis des Gateway-Auszugs der Parallel-Session (config.V1_UPSTREAM + app.py-Weiche + gateway_forward) - ohne MC_V1_UPSTREAM in der Unit exakt altes Verhalten; Rest von P1 (gateway_app, deploy.sh, Unit, token_stats) committet die andere Session. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -26,9 +26,22 @@ _lock = threading.Lock()
|
||||
_stats: dict | None = None
|
||||
_dirty = False
|
||||
_last_flush = 0.0
|
||||
# mtime der Datei beim letzten eigenen Laden/Schreiben — seit dem Gateway-Auszug
|
||||
# (UMBAU v3 P1) schreibt der mc2-gateway-Prozess die Datei, das Steuerpult liest nur
|
||||
# noch: ohne mtime-Vergleich zeigte es ab Prozessstart eingefrorene Zahlen.
|
||||
_disk_mtime: float | None = None
|
||||
|
||||
|
||||
def _stat_mtime() -> float | None:
|
||||
try:
|
||||
return STATS_FILE.stat().st_mtime
|
||||
except OSError:
|
||||
return None
|
||||
|
||||
|
||||
def _load_from_disk() -> dict:
|
||||
global _disk_mtime
|
||||
_disk_mtime = _stat_mtime()
|
||||
if not STATS_FILE.exists():
|
||||
return dict(_BASELINE)
|
||||
try:
|
||||
@@ -51,19 +64,31 @@ def _ensure_loaded() -> dict:
|
||||
|
||||
|
||||
def _write(stats: dict) -> None:
|
||||
global _disk_mtime
|
||||
try:
|
||||
STATS_FILE.parent.mkdir(parents=True, exist_ok=True)
|
||||
tmp = STATS_FILE.with_suffix(".tmp")
|
||||
with open(tmp, "w", encoding="utf-8") as f:
|
||||
json.dump(stats, f)
|
||||
tmp.replace(STATS_FILE)
|
||||
_disk_mtime = _stat_mtime() # eigener Write ist kein Fremd-Update
|
||||
except OSError:
|
||||
log.warning("token_stats: Schreiben fehlgeschlagen", exc_info=True)
|
||||
|
||||
|
||||
def get_stats() -> dict:
|
||||
"""Aktueller Stand (inkl. noch nicht geflushter Inkremente) als Kopie."""
|
||||
"""Aktueller Stand (inkl. noch nicht geflushter Inkremente) als Kopie.
|
||||
|
||||
Multi-Prozess-fähig: Hat ein ANDERER Prozess (mc2-gateway) die Datei inzwischen
|
||||
geschrieben und liegen hier keine ungeflushten Inkremente, wird frisch geladen.
|
||||
Im Gateway-Prozess selbst ist nach jedem Flush Datei == Speicher → der
|
||||
mtime-Vergleich lädt dort nie unnötig nach."""
|
||||
global _stats
|
||||
with _lock:
|
||||
if _stats is not None and not _dirty:
|
||||
mtime = _stat_mtime()
|
||||
if mtime is not None and mtime != _disk_mtime:
|
||||
_stats = _load_from_disk()
|
||||
return json.loads(json.dumps(_ensure_loaded()))
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user