diff --git a/deploy/README.md b/deploy/README.md new file mode 100644 index 0000000..04e701e --- /dev/null +++ b/deploy/README.md @@ -0,0 +1,39 @@ +# Deploy + +## Dream cycle (`lyra-dream.service`) + +Lyra's unattended inner loop. Runs `lyra-dream --loop 1800` so she consolidates +memory and reflects every 30 min between conversations. Installed as a +**systemd user service** on `lyra-cortex` (10.0.0.41), running as `serversdown` +— no root needed to manage it. + +### Install / update + +```bash +cp deploy/lyra-dream.service ~/.config/systemd/user/lyra-dream.service +systemctl --user daemon-reload +systemctl --user enable --now lyra-dream.service +``` + +### Persist across reboot / logout (one-time, needs sudo) + +A user service stops when the user logs out and doesn't start at boot until +login — unless lingering is enabled: + +```bash +sudo loginctl enable-linger serversdown +``` + +### Operate + +```bash +systemctl --user status lyra-dream.service # is she ticking? +journalctl --user -u lyra-dream.service -f # watch her think (logbus -> stderr) +systemctl --user restart lyra-dream.service # after a code change +systemctl --user stop lyra-dream.service # quiet her down +``` + +Tunables live in `lyra/dream.py` (drive thresholds, curiosity gains) and the +`--loop` interval in the unit's `ExecStart`. The consolidation backend follows +`SUMMARY_BACKEND` in `.env` (cloud gpt-4o-mini for bulk; the MI50 is too slow +for the summarization backfill). diff --git a/deploy/lyra-dream.service b/deploy/lyra-dream.service new file mode 100644 index 0000000..ff9b4c4 --- /dev/null +++ b/deploy/lyra-dream.service @@ -0,0 +1,15 @@ +[Unit] +Description=Lyra dream cycle — unattended consolidation + reflection loop +Documentation=https://github.com/serversdown/project-lyra + +[Service] +Type=simple +WorkingDirectory=/home/serversdown/project-lyra +# Clear any stray VIRTUAL_ENV so uv resolves the project's own .venv. +UnsetEnvironment=VIRTUAL_ENV +ExecStart=/home/serversdown/.local/bin/uv run lyra-dream --loop 1800 +Restart=on-failure +RestartSec=30 + +[Install] +WantedBy=default.target diff --git a/lyra/logbus.py b/lyra/logbus.py index 08aefd4..3026a94 100644 --- a/lyra/logbus.py +++ b/lyra/logbus.py @@ -6,6 +6,7 @@ ephemeral — it's an activity feed, not durable logging. """ from __future__ import annotations +import sys import threading import time from collections import deque @@ -23,6 +24,10 @@ def log(level: str, msg: str, **fields) -> None: _EVENTS.append( {"seq": _SEQ, "ts": time.time(), "level": level, "msg": msg, "fields": fields} ) + # Mirror to stderr so out-of-band runs (e.g. the dream service under + # systemd/journald) are observable, not just via the in-process SSE feed. + extra = " ".join(f"{k}={v}" for k, v in fields.items()) + print(f"[{level}] {msg}{(' ' + extra) if extra else ''}", file=sys.stderr, flush=True) def since(seq: int) -> list[dict]: