serversdown dfb6425395 feat: session modes (Talk/Cash) + live session HUD
Lyra now switches register based on what she's doing at the table instead of
being a wishy-washy companion mid-session.

Modes (lyra/modes.py):
- Talk (default companion) + Cash (live cash copilot); a mode = prompt card +
  tool allow-list. Tool gating via tools.specs(allow=).
- Two-register Cash voice: act-first one-line logging when fed facts; full warm
  companion voice for strategy / tilt / mental game.
- mode persisted per chat session (new sessions.mode column); auto-switch into
  Cash when start_session fires; UI forces cloud backend in Cash (tools only
  fire there).

Stack tracking + HUD:
- log_stack tool + poker_stack_log table; live net while sitting (stack - buy-in).
- poker.hud() bundle; /session HUD page (stack sparkline, hands, villains, notes,
  stats) polling /session/data every 5s; Talk/Cash switcher + Session nav.

Endpoints: /session, /session/data, GET/POST /sessions/{id}/mode, /modes.
tests/test_modes.py (gating, mode roundtrip, stack/HUD); 36 tests green. v0.3.0.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 05:28:15 +00:00
2026-06-18 19:38:55 +00:00

Lyra

A persistent, autonomous AI companion. One agent — her first job is Brian's live poker copilot, but the deeper aim is an emergence experiment: give an LLM the things a mind has (continuous memory, a self-model, mood, drives, reflection, a sense of time) and see whether it starts to feel like a someone rather than a chatbot.

Python 3.11+, managed with uv. Single SQLite file for all state. Runs on a home lab; nothing leaves the LAN except optional cloud LLM calls.

Architecture

Two layers, deliberately split so the agent stays general:

  • Domain-agnostic core — memory, self-state, the dream cycle, tool-calling, the web UI.
  • Poker domain pack (lyra/poker.py, lyra/equity.py) — sessions, hands, villain dossiers, stats, deterministic equity. Swappable; the core doesn't know about poker.

Backends (lyra/llm.py), role-based:

Role Backend Why
Live chat + tools cloud (OpenAI, gpt-4o default; model picker in Settings) sharp, reliable function-calling
Dream cycle / consolidation / reflection mi50 (llama.cpp on the home GPU) free, unattended, quality≈cloud for these tasks
Embeddings (memory recall) local (Ollama nomic-embed-text, 3090) free, private

Tools (poker, equity, journaling) only fire on the cloud backend — local/MI50 models don't do reliable tool-calling here.

Memory & consolidation (tiers)

Raw exchanges → per-session gists → a standing profile of Brian → monthly era digests → a current narrative → her self-state. Recall is brute-force cosine over embeddings. The dream cycle (lyra/dream.py) runs unattended and, driven by four drives (continuity / coherence / curiosity / stability), summarizes new sessions, rebuilds the profile/eras/narrative, and reflects — evolving her mood, self-narrative, and journal between conversations.

She reflects in two steps (draft → examine her own draft for flattery/drift → revise), perceives time (current moment + how long since you last spoke / she last reflected), and keeps a permanent journal.

Poker copilot

She runs in modes (lyra/modes.py). 💬 Talk is the default companion (journaling + read-only poker lookups). ♠ Cash is the live copilot: she gets the full session toolset and a two-register voice — quiet and act-first when you're feeding her facts to log (stack, a hand, a read → one-line confirm, no narration), but fully present and warm when you ask for strategy or you're tilting / card-dead / steaming. Opening a session auto-switches her into Cash mode.

Talk to her during a session; she drives tools behind the scenes:

  • Session trackingstart_session, add_buyin, end_session → net, hours, $/hr.
  • Stack trackinglog_stack records your stack as the night goes → live net while you're still sitting, and a stack-over-time sparkline on the HUD.
  • Hand histories — vomit rough shorthand ("AKs btn, 3bet, flop A72…"), she reconstructs a structured, replayable hand (unknown cards = x, never invented).
  • Villain file — named opponents auto-build persistent dossiers; basic stats (VPIP/PFR) emerge once a player has enough logged hands.
  • Deterministic equity (analyze_spot) — exact equity / made hands / outs via a real poker evaluator. She is required to use it, never eyeballs board math.
  • Stats & recapsrunning_stats; generate_recap writes her .md session log.

Web app (served by lyra-web, default :7078)

/ chat (Markdown, model picker, 👍/👎 rating, Talk/Cash mode switcher) · /session live session HUD (stack + sparkline, hands, villains, notes; mobile Session tab) · /logs live activity · /self read-her-mind (mood, drives, reflections) · /journal her thoughts · /hands recorded hands → /hand/{id} replayer · /recap/{id} session writeup (+ .md export). 👍/👎 ratings on replies and thoughts are stored as (context, content, rating) — a fine-tune / preference dataset built passively (/ratings/export → JSONL).

Setup

uv sync
cp .env.example .env      # set OPENAI_API_KEY; point LOCAL_BASE_URL / MI50_BASE_URL at your boxes
uv run lyra-web           # web UI on :7078

Run as services (reboot-resilient) — see deploy/:

cp deploy/*.service ~/.config/systemd/user/ && systemctl --user daemon-reload
systemctl --user enable --now lyra-web.service lyra-dream.service
sudo loginctl enable-linger "$USER"   # survive logout/reboot

CLIs: lyra-dream (one pass / --loop), lyra-reflect, lyra-summarize, lyra-profile, lyra-era, lyra-narrative, lyra-import (ChatGPT history).

Status

Working system. Poker copilot + full memory/dream-cycle/journal/ratings in place. Moonshots and deferred work live in docs/PARKED_IDEAS.md (own/fine-tuned model, self-modification sandbox, RTO/cfr-core solver tooling). Pre-rebuild design docs are kept in docs/ as history.

S
Description
Beepo Boop this is a robot beep.
Readme 7.8 MiB
Languages
Python 60.4%
HTML 32.9%
CSS 6.7%