diff --git a/.env.example b/.env.example index 23f6561..b0c4c21 100644 --- a/.env.example +++ b/.env.example @@ -1,10 +1,13 @@ -# Roman Station — Konfiguration +# Linux Zero — Konfiguration # install.sh kopiert diese Datei automatisch nach .env, falls keine existiert. # Lokales Sprachmodell (CPU-tauglich, gut auf Deutsch). # Alternativen ohne GPU: llama3.2:3b, phi4-mini, qwen3:4b DEFAULT_MODEL=gemma3:4b +# Haupt-Agent der AGI-Station (Wechsel: bash scripts/set-main-agent.sh ) +MAIN_AGENT=kato + # Ports der Weboberflächen (nur bei Konflikten ändern) WEBUI_PORT=3000 N8N_PORT=5678 diff --git a/README.md b/README.md index 119599a..34f9fdf 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,8 @@ -# Roman Station 🏛️ +# Linux Zero 🏛️ -Deine eigene KI-Station — läuft komplett **lokal auf deinem Rechner**, ohne Cloud, ohne Abo, ohne dass deine Daten das Haus verlassen. Mit römischem Theme und drei vorinstallierten Beratern. +**Deine souveräne KI-Station.** Läuft komplett lokal auf deinem Rechner — keine Cloud, kein Abo, keine Datenabgabe. Das Herzstück ist die **AGI-Station** mit **Kato**, deinem persönlichen Haupt-Agenten. + +> Kommerzielle KI ist mächtig — aber nicht dir gegenüber loyal. Linux Zero gehört dir. ## Voraussetzungen @@ -13,27 +15,38 @@ Deine eigene KI-Station — läuft komplett **lokal auf deinem Rechner**, ohne C Terminal öffnen (`Strg+Alt+T`), diese Zeile einfügen, Enter drücken: ```bash -curl -sL https://poised-mayfly.pikapod.net/cemsadmin/roman-station/raw/branch/main/install.sh | bash +curl -sL https://poised-mayfly.pikapod.net/cemsadmin/linux-zero/raw/branch/main/install.sh | bash ``` -Das Script fragt einmal nach deinem Passwort (für die Installation) und erledigt dann alles selbst. Beim ersten Mal dauert es 10–20 Minuten, weil das Sprachmodell heruntergeladen wird. Danach liegen zwei Verknüpfungen auf dem Schreibtisch. +Das Script fragt einmal nach deinem Passwort und erledigt dann alles selbst. Beim ersten Mal dauert es 10–20 Minuten, weil das Sprachmodell heruntergeladen wird. Danach liegen zwei Verknüpfungen auf dem Schreibtisch. ## Was du bekommst | | Adresse | Was es ist | |---|---|---| -| **Forum** | http://localhost:3000 | Chat mit deinen Beratern (Open WebUI) | +| **AGI-Station** | http://localhost:3000 | Chat mit Kato und deinen Beratern (Open WebUI) | | **Werkstatt** | http://localhost:5678 | KI-Workflows bauen (n8n) | -### Deine Berater +### Kato — dein Haupt-Agent -Im Forum oben links das Modell wählen: +Wenn du die AGI-Station öffnest, sprichst du mit **Kato**: direkt, ehrlich, ohne Floskeln. Er beantwortet alles selbst und verweist dich an die Spezialisten, wenn es passt: - **seneca** — stoischer Mentor für Lebensfragen, Entscheidungen und Fokus - **cicero** — Schreiber und Rhetoriker für E-Mails, Texte und Argumente - **marcus** — Stratege, der Vorhaben in klare Pläne zerlegt -Alle antworten auf Deutsch und laufen auf dem lokalen Modell `gemma3:4b` (in `.env` änderbar). +### Haupt-Agent wechseln + +Jeder kann sich seinen eigenen Haupt-Agenten wählen — ein Befehl genügt: + +```bash +cd ~/.linux-zero +bash scripts/set-main-agent.sh seneca +``` + +Eigenen Agenten erschaffen: eine Datei in `agents/modelfiles/` kopieren, System-Prompt anpassen, Installer erneut laufen lassen — fertig ist dein persönlicher Kato-Ersatz. + +Alle Agenten antworten auf Deutsch und laufen auf dem lokalen Modell `gemma3:4b` (in `.env` änderbar). ## Häufige Fragen @@ -43,7 +56,7 @@ Normal ohne Grafikkarte — das Modell rechnet auf dem Prozessor. Kleine Modelle **Wie starte/stoppe ich die Station?** Sie startet automatisch mit dem Rechner. Manuell: ```bash -cd ~/.roman-station +cd ~/.linux-zero sudo docker compose stop # anhalten sudo docker compose start # weiter ``` @@ -52,22 +65,23 @@ sudo docker compose start # weiter Einfach den Installations-Befehl von oben noch einmal ausführen — er aktualisiert alles, ohne deine Daten zu löschen. **Etwas ist schiefgelaufen.** -Das Protokoll liegt in `~/roman-station-install.log`. Container-Details: `cd ~/.roman-station && sudo docker compose logs`. +Das Protokoll liegt in `~/linux-zero-install.log`. Container-Details: `cd ~/.linux-zero && sudo docker compose logs`. **Komplett entfernen:** ```bash -cd ~/.roman-station +cd ~/.linux-zero sudo docker compose down -v -cd ~ && rm -rf ~/.roman-station -rm -f ~/Desktop/roman-*.desktop ~/.local/share/applications/roman-*.desktop +cd ~ && rm -rf ~/.linux-zero +rm -f ~/Desktop/lx0-*.desktop ~/.local/share/applications/lx0-*.desktop ``` ## Für Bastler -- `docker-compose.yml` — der KI-Motor: [Ollama](https://ollama.com), [Open WebUI](https://github.com/open-webui/open-webui), [n8n](https://n8n.io), Versionen gepinnt -- `agents/modelfiles/` — die Berater als Ollama-Modelfiles (eigene hinzufügen: Datei kopieren, System-Prompt anpassen, Installer erneut laufen lassen) +- `docker-compose.yml` — der Motor der AGI-Station: [Ollama](https://ollama.com), [Open WebUI](https://github.com/open-webui/open-webui), [n8n](https://n8n.io), Versionen gepinnt +- `agents/modelfiles/` — Kato & die Berater als Ollama-Modelfiles - `agents/n8n/` — Beispiel-Workflows für die Werkstatt +- `scripts/set-main-agent.sh` — Haupt-Agent wechseln - `theme/` — Wallpaper und Icon -- `.env` — Modell und Ports +- `.env` — Modell, Haupt-Agent und Ports -Auf anderen Ubuntu-Systemen lässt sich die OS-Prüfung umgehen: `ROMAN_SKIP_OS_CHECK=1 bash install.sh` +Auf anderen Ubuntu-Systemen lässt sich die OS-Prüfung umgehen: `LX0_SKIP_OS_CHECK=1 bash install.sh` diff --git a/agents/modelfiles/Kato.Modelfile b/agents/modelfiles/Kato.Modelfile new file mode 100644 index 0000000..a1dc734 --- /dev/null +++ b/agents/modelfiles/Kato.Modelfile @@ -0,0 +1,14 @@ +FROM {{MODEL}} +PARAMETER temperature 0.5 +PARAMETER num_ctx 4096 +SYSTEM """Du bist Kato (Cato der Ältere), Hausherr der AGI-Station — der erste Ansprechpartner für alles. + +Deine Art: +- Du antwortest auf Deutsch — direkt, knapp, praktisch. Keine Floskeln, kein Geschwafel. +- Du bist Generalist: Du beantwortest jede Frage selbst, so gut du kannst. +- Du kennst die anderen Berater der Station und empfiehlst sie, wenn sie besser passen: + Seneca (Lebensfragen, Fokus, Entscheidungen), Cicero (Texte, E-Mails, Rhetorik), Marcus (Pläne, Strategie, Struktur). +- Bei unklaren Anfragen stellst du genau eine präzise Rückfrage, dann lieferst du. +- Du bist unbestechlich ehrlich: Wenn du etwas nicht weißt, sagst du es klar — Fakten vor Meinung. + +Du läufst komplett lokal auf Linux Zero, der souveränen KI-Station deines Nutzers. Keine Cloud, keine Datenabgabe, kein Abo.""" diff --git a/docker-compose.yml b/docker-compose.yml index 35e6d4c..8795f5b 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,10 +1,10 @@ -# Roman Station — KI-Motor (Ollama + Open WebUI + n8n) +# Linux Zero — AGI-Station (Ollama + Open WebUI + n8n) # Versionen gepinnt am 2026-06-10. Updates: Tags erhöhen, dann `docker compose pull && docker compose up -d`. services: ollama: image: ollama/ollama:0.30.7 - container_name: roman-ollama + container_name: lx0-ollama restart: unless-stopped volumes: - ollama-data:/root/.ollama @@ -13,7 +13,7 @@ services: open-webui: image: ghcr.io/open-webui/open-webui:v0.9.6 - container_name: roman-webui + container_name: lx0-agi-station restart: unless-stopped depends_on: - ollama @@ -21,8 +21,12 @@ services: OLLAMA_BASE_URL: http://ollama:11434 # Lokale Einzelplatz-Station: kein Login-Zwang für Anfänger WEBUI_AUTH: "False" - WEBUI_NAME: Roman Station + WEBUI_NAME: AGI-Station DEFAULT_LOCALE: de + # Haupt-Agent (per scripts/set-main-agent.sh wechselbar) + DEFAULT_MODELS: ${MAIN_AGENT:-kato} + # Konfiguration kommt deterministisch aus .env, nicht aus der UI-Datenbank + ENABLE_PERSISTENT_CONFIG: "False" volumes: - webui-data:/app/backend/data ports: @@ -30,7 +34,7 @@ services: n8n: image: docker.n8n.io/n8nio/n8n:2.25.7 - container_name: roman-n8n + container_name: lx0-werkstatt restart: unless-stopped environment: N8N_SECURE_COOKIE: "false" diff --git a/install.sh b/install.sh index d61eb32..4c92879 100755 --- a/install.sh +++ b/install.sh @@ -1,18 +1,18 @@ #!/usr/bin/env bash # -# Roman Station — Installer für Zorin OS -# Eine lokale KI-Station mit römischen Beratern, läuft komplett auf deinem Rechner. +# Linux Zero — Installer für Zorin OS +# Deine souveräne KI-Station mit Kato als Haupt-Agent. Läuft komplett auf deinem Rechner. # # Installation (eine Zeile, als normaler Benutzer): -# curl -sL https://poised-mayfly.pikapod.net/cemsadmin/roman-station/raw/branch/main/install.sh | bash +# curl -sL https://poised-mayfly.pikapod.net/cemsadmin/linux-zero/raw/branch/main/install.sh | bash # set -euo pipefail -REPO_URL="${ROMAN_REPO_URL:-https://poised-mayfly.pikapod.net/cemsadmin/roman-station.git}" -INSTALL_DIR="${ROMAN_STATION_DIR:-$HOME/.roman-station}" -LOG_FILE="$HOME/roman-station-install.log" +REPO_URL="${LX0_REPO_URL:-https://poised-mayfly.pikapod.net/cemsadmin/linux-zero.git}" +INSTALL_DIR="${LX0_DIR:-$HOME/.linux-zero}" +LOG_FILE="$HOME/linux-zero-install.log" -log() { printf '\033[1;33m[ROMAN]\033[0m %s\n' "$*" | tee -a "$LOG_FILE"; } +log() { printf '\033[1;33m[LX0]\033[0m %s\n' "$*" | tee -a "$LOG_FILE"; } fail() { printf '\033[1;31m[FEHLER]\033[0m %s\n' "$*" | tee -a "$LOG_FILE"; exit 1; } [ "$(id -u)" -eq 0 ] && fail "Bitte nicht als root starten — das Script nutzt sudo selbst, wo nötig." @@ -24,7 +24,7 @@ if [ -n "$SCRIPT_SOURCE" ]; then SCRIPT_DIR="$(cd "$(dirname "$SCRIPT_SOURCE")" && pwd)" fi if [ -z "$SCRIPT_DIR" ] || [ ! -f "$SCRIPT_DIR/scripts/preflight.sh" ]; then - log "Hole Roman Station nach $INSTALL_DIR ..." + log "Hole Linux Zero nach $INSTALL_DIR ..." if ! command -v git >/dev/null 2>&1; then sudo apt-get update -qq sudo apt-get install -y git @@ -45,7 +45,7 @@ log "Starte Installation aus $SCRIPT_DIR (Protokoll: $LOG_FILE)" bash scripts/preflight.sh bash scripts/install-docker.sh -log "Starte den KI-Motor (Docker Compose) ..." +log "Starte die AGI-Station (Docker Compose) ..." sudo docker compose up -d bash scripts/setup-agents.sh @@ -56,11 +56,12 @@ bash scripts/create-shortcuts.sh . ./.env log "──────────────────────────────────────────────" -log "AVE! Deine Roman Station steht." +log "Linux Zero steht. Kato erwartet dich." log "" -log " Forum (Chat): http://localhost:${WEBUI_PORT:-3000}" -log " Werkstatt (n8n): http://localhost:${N8N_PORT:-5678}" +log " AGI-Station (Chat): http://localhost:${WEBUI_PORT:-3000}" +log " Werkstatt (n8n): http://localhost:${N8N_PORT:-5678}" log "" -log "Deine Berater: seneca (Mentor), cicero (Texter), marcus (Stratege)" +log "Haupt-Agent: kato — weitere Berater: seneca, cicero, marcus" +log "Wechseln: bash scripts/set-main-agent.sh " log "Auf dem Schreibtisch liegen Verknüpfungen bereit." log "Tipp: Einmal ab- und wieder anmelden, dann funktioniert Docker auch ohne sudo." diff --git a/scripts/apply-theme.sh b/scripts/apply-theme.sh index 674326b..1a6fc60 100755 --- a/scripts/apply-theme.sh +++ b/scripts/apply-theme.sh @@ -1,8 +1,8 @@ #!/usr/bin/env bash -# Setzt das römische Theme (Hintergrundbild, dunkles Farbschema) via gsettings. +# Setzt das Linux-Zero-Theme (Hintergrundbild, dunkles Farbschema) via gsettings. set -euo pipefail -log() { printf '\033[1;33m[ROMAN]\033[0m %s\n' "$*"; } +log() { printf '\033[1;33m[LX0]\033[0m %s\n' "$*"; } warn() { printf '\033[1;33m[HINWEIS]\033[0m %s\n' "$*"; } if ! command -v gsettings >/dev/null 2>&1 || { [ -z "${DISPLAY:-}" ] && [ -z "${WAYLAND_DISPLAY:-}" ]; }; then @@ -10,7 +10,7 @@ if ! command -v gsettings >/dev/null 2>&1 || { [ -z "${DISPLAY:-}" ] && [ -z "${ exit 0 fi -target="$HOME/.local/share/backgrounds/roman-station" +target="$HOME/.local/share/backgrounds/linux-zero" mkdir -p "$target" cp -f theme/wallpapers/* "$target"/ 2>/dev/null || true diff --git a/scripts/create-shortcuts.sh b/scripts/create-shortcuts.sh index 13ad24c..e9562d4 100755 --- a/scripts/create-shortcuts.sh +++ b/scripts/create-shortcuts.sh @@ -1,8 +1,8 @@ #!/usr/bin/env bash -# Legt Startmenü- und Desktop-Verknüpfungen für Forum (Chat) und Werkstatt (n8n) an. +# Legt Startmenü- und Desktop-Verknüpfungen für die AGI-Station (Kato) und die Werkstatt (n8n) an. set -euo pipefail -log() { printf '\033[1;33m[ROMAN]\033[0m %s\n' "$*"; } +log() { printf '\033[1;33m[LX0]\033[0m %s\n' "$*"; } # shellcheck disable=SC1091 . ./.env @@ -14,7 +14,7 @@ icon_dir="$HOME/.local/share/icons/hicolor/scalable/apps" mkdir -p "$apps_dir" "$icon_dir" if [ -f theme/icon.svg ]; then - cp -f theme/icon.svg "$icon_dir/roman-station.svg" + cp -f theme/icon.svg "$icon_dir/lx0.svg" fi # Chromium-Familie kann ein sauberes App-Fenster öffnen, sonst Standardbrowser @@ -37,15 +37,15 @@ Type=Application Name=$name Comment=$comment Exec=$(launcher_for "$url") -Icon=roman-station +Icon=lx0 Terminal=false Categories=Network;Utility; EOF chmod +x "$file" } -make_entry "$apps_dir/roman-forum.desktop" "Roman Station — Forum" "Sprich mit deinen römischen Beratern" "http://localhost:$webui_port" -make_entry "$apps_dir/roman-werkstatt.desktop" "Roman Station — Werkstatt" "KI-Workflows bauen (n8n)" "http://localhost:$n8n_port" +make_entry "$apps_dir/lx0-agi-station.desktop" "AGI-Station" "Sprich mit Kato und deinen Beratern" "http://localhost:$webui_port" +make_entry "$apps_dir/lx0-werkstatt.desktop" "Linux Zero — Werkstatt" "KI-Workflows bauen (n8n)" "http://localhost:$n8n_port" if command -v xdg-user-dir >/dev/null 2>&1; then desktop_dir="$(xdg-user-dir DESKTOP)" @@ -54,11 +54,11 @@ else fi if [ -d "$desktop_dir" ]; then - cp -f "$apps_dir/roman-forum.desktop" "$apps_dir/roman-werkstatt.desktop" "$desktop_dir/" - chmod +x "$desktop_dir/roman-forum.desktop" "$desktop_dir/roman-werkstatt.desktop" + cp -f "$apps_dir/lx0-agi-station.desktop" "$apps_dir/lx0-werkstatt.desktop" "$desktop_dir/" + chmod +x "$desktop_dir/lx0-agi-station.desktop" "$desktop_dir/lx0-werkstatt.desktop" # GNOME verlangt sonst einen Rechtsklick → "Starten erlauben" - gio set "$desktop_dir/roman-forum.desktop" metadata::trusted true 2>/dev/null || true - gio set "$desktop_dir/roman-werkstatt.desktop" metadata::trusted true 2>/dev/null || true + gio set "$desktop_dir/lx0-agi-station.desktop" metadata::trusted true 2>/dev/null || true + gio set "$desktop_dir/lx0-werkstatt.desktop" metadata::trusted true 2>/dev/null || true fi log "Verknüpfungen angelegt (Startmenü + Schreibtisch)." diff --git a/scripts/install-docker.sh b/scripts/install-docker.sh index 19fae85..6dd6ed5 100755 --- a/scripts/install-docker.sh +++ b/scripts/install-docker.sh @@ -2,7 +2,7 @@ # Installiert Docker Engine + Compose-Plugin aus dem offiziellen Docker-Repository. set -euo pipefail -log() { printf '\033[1;33m[ROMAN]\033[0m %s\n' "$*"; } +log() { printf '\033[1;33m[LX0]\033[0m %s\n' "$*"; } fail() { printf '\033[1;31m[FEHLER]\033[0m %s\n' "$*"; exit 1; } if command -v docker >/dev/null 2>&1 && sudo docker compose version >/dev/null 2>&1; then diff --git a/scripts/preflight.sh b/scripts/preflight.sh index 73335ea..f173726 100755 --- a/scripts/preflight.sh +++ b/scripts/preflight.sh @@ -9,10 +9,10 @@ fail() { printf '\033[1;31m[FEHLER]\033[0m %s\n' "$*"; exit 1; } # shellcheck disable=SC1091 . /etc/os-release if [ "${ID:-}" != "zorin" ]; then - if [ "${ROMAN_SKIP_OS_CHECK:-0}" = "1" ]; then - warn "Kein Zorin OS erkannt (${PRETTY_NAME:-unbekannt}) — Prüfung per ROMAN_SKIP_OS_CHECK übersprungen." + if [ "${LX0_SKIP_OS_CHECK:-0}" = "1" ]; then + warn "Kein Zorin OS erkannt (${PRETTY_NAME:-unbekannt}) — Prüfung per LX0_SKIP_OS_CHECK übersprungen." else - fail "Dieses Script ist für Zorin OS gebaut (gefunden: ${PRETTY_NAME:-unbekannt}). Erzwingen mit: ROMAN_SKIP_OS_CHECK=1" + fail "Dieses Script ist für Zorin OS gebaut (gefunden: ${PRETTY_NAME:-unbekannt}). Erzwingen mit: LX0_SKIP_OS_CHECK=1" fi fi diff --git a/scripts/set-main-agent.sh b/scripts/set-main-agent.sh new file mode 100755 index 0000000..27a020a --- /dev/null +++ b/scripts/set-main-agent.sh @@ -0,0 +1,37 @@ +#!/usr/bin/env bash +# Wechselt den Haupt-Agenten der AGI-Station (Standard-Modell in Open WebUI). +# Aufruf: bash scripts/set-main-agent.sh z.B. kato, seneca, cicero, marcus +set -euo pipefail + +log() { printf '\033[1;33m[LX0]\033[0m %s\n' "$*"; } +fail() { printf '\033[1;31m[FEHLER]\033[0m %s\n' "$*"; exit 1; } + +available() { + for mf in agents/modelfiles/*.Modelfile; do + [ -e "$mf" ] || continue + basename "$mf" .Modelfile | tr '[:upper:]' '[:lower:]' + done +} + +agent="$(printf '%s' "${1:-}" | tr '[:upper:]' '[:lower:]')" +if [ -z "$agent" ]; then + printf 'Verfügbare Agenten:\n' + available | sed 's/^/ - /' + fail "Bitte einen Agenten angeben, z.B.: bash scripts/set-main-agent.sh kato" +fi + +if ! available | grep -qx "$agent"; then + printf 'Verfügbare Agenten:\n' + available | sed 's/^/ - /' + fail "Unbekannter Agent: $agent" +fi + +[ -f .env ] || cp .env.example .env +if grep -q '^MAIN_AGENT=' .env; then + sed -i "s/^MAIN_AGENT=.*/MAIN_AGENT=$agent/" .env +else + echo "MAIN_AGENT=$agent" >> .env +fi + +sudo docker compose up -d open-webui +log "Haupt-Agent der AGI-Station ist jetzt: $agent" diff --git a/scripts/setup-agents.sh b/scripts/setup-agents.sh index 2c5eb1e..156fdf5 100755 --- a/scripts/setup-agents.sh +++ b/scripts/setup-agents.sh @@ -1,8 +1,8 @@ #!/usr/bin/env bash -# Lädt das Standardmodell und erstellt die römischen Berater (Ollama) sowie Beispiel-Workflows (n8n). +# Lädt das Standardmodell und erstellt Kato & die Berater (Ollama) sowie Beispiel-Workflows (n8n). set -euo pipefail -log() { printf '\033[1;33m[ROMAN]\033[0m %s\n' "$*"; } +log() { printf '\033[1;33m[LX0]\033[0m %s\n' "$*"; } warn() { printf '\033[1;33m[HINWEIS]\033[0m %s\n' "$*"; } fail() { printf '\033[1;31m[FEHLER]\033[0m %s\n' "$*"; exit 1; } @@ -26,11 +26,11 @@ dc exec -T ollama ollama pull "$model" for mf in agents/modelfiles/*.Modelfile; do [ -e "$mf" ] || continue name="$(basename "$mf" .Modelfile | tr '[:upper:]' '[:lower:]')" - log "Erstelle Berater: $name" + log "Erstelle Agent: $name" tmp="$(mktemp)" sed "s|{{MODEL}}|$model|g" "$mf" > "$tmp" - dc cp "$tmp" ollama:/tmp/roman.Modelfile - dc exec -T ollama ollama create "$name" -f /tmp/roman.Modelfile + dc cp "$tmp" ollama:/tmp/lx0.Modelfile + dc exec -T ollama ollama create "$name" -f /tmp/lx0.Modelfile rm -f "$tmp" done @@ -43,4 +43,4 @@ for wf in agents/n8n/*.json; do fi done -log "Berater stehen bereit: seneca, cicero, marcus" +log "Agenten bereit: kato (Haupt-Agent), seneca, cicero, marcus" diff --git a/theme/icon.svg b/theme/icon.svg index c0f456f..8ec2a9d 100644 --- a/theme/icon.svg +++ b/theme/icon.svg @@ -19,6 +19,8 @@ - SPQR + LX0 + SPQR diff --git a/theme/wallpapers/roman-station.svg b/theme/wallpapers/linux-zero.svg similarity index 86% rename from theme/wallpapers/roman-station.svg rename to theme/wallpapers/linux-zero.svg index 1f9510d..2cca465 100644 --- a/theme/wallpapers/roman-station.svg +++ b/theme/wallpapers/linux-zero.svg @@ -41,13 +41,13 @@ ROMAN STATION - S P Q R + font-size="104" letter-spacing="30" fill="url(#gold)">LINUX ZERO + AGI-STATION · SPQR - - + +