atlas-os/scripts/atlas_autonomy_export.py
Chaib Aarab 301cc75de9 init: Atlas OS — open-source patterns + tools for solo founder LLM cluster
3 browser-native chat surfaces (atlas-chat / atlas-hud / atlas-command, no build step)
+ 11 Python automation scripts (cluster, tray, finance, reminders, autonomy loops)
+ 2 patterns documented (cluster-then-polish, anti-impulse R1-R10)
MIT licensed, anonymized from production stack.
2026-05-26 16:21:16 +02:00

143 lines
5.2 KiB
Python

#!/usr/bin/env python3
"""
atlas_autonomy_export.py - Expose autonomy loop state via JSON for live dashboard.
Reads:
- autonomy_queue.json (pending/completed)
- autonomy_loop.log (last 50 lines)
- vault/00_Atlas_Wiki/_autonomy/*.md (last 20 outputs)
Writes:
- atlas-autonomy.json — consumed by Atlas Command AUTONOMY tab
Runs: every 1 min via Atlas-Autonomy-Export schtask (lightweight).
"""
import json
import sys
import subprocess
from pathlib import Path
from datetime import datetime
import io
if sys.stdout.encoding != 'utf-8':
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8', errors='replace')
QUEUE = Path(r"C:\Users\Gebruiker\.config\atlas\autonomy_queue.json")
LOG = Path(r"C:\Users\Gebruiker\.config\atlas\autonomy_loop.log")
AUTO = Path(r"C:\Users\Gebruiker\MEGA\Atlas Corporation\00_Atlas_Wiki\_autonomy")
OUT = Path(r"C:\Users\Gebruiker\AppData\Local\Atlas\analyses\atlas-autonomy.json")
SSH = "root@<YOUR_VPS_IP>"
REMOTE = "/opt/atlas/dashboard/atlas-autonomy.json"
def parse_frontmatter(text):
"""Extract simple YAML frontmatter (between --- markers)."""
if not text.startswith("---"):
return {}, text
end = text.find("---", 3)
if end == -1:
return {}, text
yaml_block = text[3:end].strip()
body = text[end+3:].strip()
fm = {}
for line in yaml_block.split("\n"):
if ":" in line:
k, v = line.split(":", 1)
fm[k.strip()] = v.strip()
return fm, body
def main():
state = {
"generated_at": datetime.now().isoformat(timespec="seconds"),
"loop_running": False,
"queue_pending": 0,
"queue_completed": 0,
"log_tail": [],
"recent_outputs": [],
"next_fire": None,
"task_state": None,
}
# Queue
if QUEUE.exists():
try:
q = json.loads(QUEUE.read_text(encoding="utf-8"))
state["queue_pending"] = len(q.get("pending", []))
state["queue_completed"] = len(q.get("completed", []))
if q.get("completed"):
last = q["completed"][-1]
state["last_completed"] = {
"topic": last.get("topic"),
"node": last.get("node"),
"model": last.get("model"),
"completed_at": last.get("completed_at"),
"elapsed_s": last.get("elapsed_s"),
}
except Exception as e:
state["queue_err"] = str(e)[:100]
# Log tail
if LOG.exists():
try:
lines = LOG.read_text(encoding="utf-8", errors="replace").splitlines()
state["log_tail"] = lines[-50:]
except Exception:
pass
# Schtask state
try:
r = subprocess.run(
["powershell.exe", "-NoProfile", "-Command",
"$t=Get-ScheduledTask -TaskName Atlas-Autonomy-Hourly -ErrorAction SilentlyContinue;"
"if ($t) { $i=Get-ScheduledTaskInfo $t; "
"Write-Output ('STATE:' + $t.State + '|LAST:' + $i.LastRunTime + '|NEXT:' + $i.NextRunTime + '|RESULT:' + $i.LastTaskResult) }"],
capture_output=True, text=True, timeout=10
)
out = r.stdout.strip()
if out.startswith("STATE:"):
parts = dict(p.split(":", 1) for p in out[6:].split("|"))
state["task_state"] = "STATE:" + out[6:]
state["loop_running"] = (parts.get("STATE") != "Disabled")
state["next_fire"] = parts.get("NEXT")
except Exception as e:
state["task_state_err"] = str(e)[:100]
# Recent outputs (last 20 by mtime)
if AUTO.exists():
try:
md_files = sorted(AUTO.glob("*.md"), key=lambda p: p.stat().st_mtime, reverse=True)[:20]
for p in md_files:
try:
text = p.read_text(encoding="utf-8", errors="replace")
fm, body = parse_frontmatter(text)
state["recent_outputs"].append({
"filename": p.name,
"mtime": datetime.fromtimestamp(p.stat().st_mtime).isoformat(timespec="seconds"),
"topic": fm.get("topic", "?"),
"node": fm.get("node", "?"),
"model": fm.get("model", "?"),
"elapsed_s": fm.get("elapsed_s", "?"),
"polish_status": fm.get("polish_status", "?"),
"body_preview": body[:400].replace("\n", " ").strip(),
})
except Exception:
pass
except Exception as e:
state["outputs_err"] = str(e)[:100]
state["recent_output_count"] = len(state["recent_outputs"])
OUT.parent.mkdir(parents=True, exist_ok=True)
OUT.write_text(json.dumps(state, indent=2, ensure_ascii=False), encoding="utf-8")
print(f"wrote {OUT}")
print(f" pending={state['queue_pending']} completed={state['queue_completed']} outputs={state['recent_output_count']}")
try:
subprocess.run(["scp", str(OUT), f"{SSH}:{REMOTE}"], check=True, timeout=20)
print(f"pushed to {SSH}:{REMOTE}")
except Exception as e:
print(f"scp fail: {e}")
if __name__ == "__main__":
main()