Files
ARIA-AGENT/docker-compose.yml
T
duffyduckandClaude Opus 4.8 2284c1a780 fix(proxy): ARIA-Persona als VOLLER System-Prompt-Replace (--system-prompt)
Der Self-Grounding-Ansatz (268636c) allein reichte nicht: Sonnet 5 in Claude
Code haelt seine eingebaute "You are Claude Code"-Identitaet hart und liest den
synthetischen <previous_response> als "fabricated". Ursache bleibt der Kanal:
--append-system-prompt HAENGT ARIAs Persona nur hinten an Claude Codes Basis-
Identitaet an — bei duennem Kontext (Hauptchat) gewinnt die Basis und wehrt die
Persona als Injection ab. Anhaengen ist gegen das Anti-Injection-Training des
Modells nicht durchsetzbar.

Fix: System-Prompt VOLL ersetzen statt anhaengen — sed-Patch in docker-compose
schaltet manager.js buildArgs von --append-system-prompt auf --system-prompt.
Damit ist die ARIA-Persona DIE Identitaet des Modells (kein Anhaengsel), und
Claude Codes dynamische Sektionen (cwd '/', git, platform) — die "ich bin ein
Coding-Agent"-Signale — fallen weg. Bestaetigt per claude-code-guide: die CLI
isoliert bei --system-prompt vollstaendig, die eingebaute Identitaet leakt nicht.

extractSystemPrompt liefert weiterhin einen selbsttragenden Prompt (Persona +
Anker + Memory + Skills + Tool-Block); er darf bei --system-prompt nie leer sein
(Brain schickt immer System-Message + Tools -> real nie leer). Der IDENTITY_SEED
aus 268636c bleibt als Defense-in-Depth drin. Kommentare in openai-to-cli.js,
routes.js, agent.py, prompts.py entsprechend nachgezogen.

Deploy: Proxy UND Brain neu (--force-recreate; routes.js/openai-to-cli.js werden
frisch in den Proxy-Container ge-cp't). Verifikation am Container:
docker exec aria-proxy sh -c 'grep -o "\-\-system-prompt" /usr/local/lib/*/claude-max-api-proxy/dist/subprocess/manager.js'

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-10 22:44:02 +02:00

154 lines
7.3 KiB
YAML

services:
# ─── Claude Max API Proxy ───────────────────────────────
proxy:
image: node:22-alpine
container_name: aria-proxy
extra_hosts:
- "host.docker.internal:host-gateway" # Zugriff auf die VM via SSH
command: >-
sh -c "apk add --no-cache openssh-client bash curl &&
npm install -g @anthropic-ai/claude-code claude-max-api-proxy &&
DIST=$$(find /usr/local/lib -path '*/claude-max-api-proxy/dist' -type d | head -1) &&
sed -i 's/startServer({ port })/startServer({ port, host: process.env.HOST || \"127.0.0.1\" })/' $$DIST/server/standalone.js &&
sed -i 's/\"--no-session-persistence\",/\"--no-session-persistence\",\"--dangerously-skip-permissions\",/' $$DIST/subprocess/manager.js &&
sed -i 's/\"--dangerously-skip-permissions\",/\"--dangerously-skip-permissions\",\"--system-prompt\",options.systemPrompt,/' $$DIST/subprocess/manager.js &&
sed -i 's/const DEFAULT_TIMEOUT = 300000;/const DEFAULT_TIMEOUT = 86400000;/' $$DIST/subprocess/manager.js &&
sed -i '/prompt, \\/\\/ Pass prompt as argument/d' $$DIST/subprocess/manager.js &&
sed -i 's|this\\.process\\.stdin?\\.end();|this.process.stdin?.end(prompt);|' $$DIST/subprocess/manager.js &&
cp /proxy-patches/openai-to-cli.js $$DIST/adapter/openai-to-cli.js &&
cp /proxy-patches/cli-to-openai.js $$DIST/adapter/cli-to-openai.js &&
cp /proxy-patches/routes.js $$DIST/server/routes.js &&
claude-max-api"
volumes:
- ~/.claude:/root/.claude # Claude CLI Auth (Credentials in /root/.claude/.credentials.json)
- ./aria-data/ssh:/root/.ssh # SSH Keys fuer VM-Zugriff (aria-wohnung, rw fuer ARIA)
- ./aria-shared:/shared # Shared Volume fuer Datei-Austausch (Uploads von App)
- ./proxy-patches:/proxy-patches:ro # Tool-Use-Adapter (ueberschreibt npm-Version, read-only)
# Claude Code's eingebautes Auto-Memory liegt in ~/.claude/projects/.
# Wir ueberlagern das mit tmpfs damit ARIA nicht parallel zu ARIAs eigener
# Qdrant-DB ein File-Memory aufbaut (war Auslöser fuer doppelte Truth-Source).
# Tmpfs ist beim Container-Start leer und wird beim Container-Recreate
# weggeworfen — Claude Code sieht keine alten Files mehr und das was sie
# ggf. neu schreibt landet nicht auf dem VM-Host.
tmpfs:
- /root/.claude/projects
environment:
- HOST=0.0.0.0
- SHELL=/bin/bash # Claude Code Bash-Tool braucht bash (nicht nur sh/ash)
- CLAUDE_CODE_BUBBLEWRAP=1 # Erlaubt --dangerously-skip-permissions als root
restart: unless-stopped
networks:
- aria-net
# ─── Qdrant (Vector-DB fuer ARIAs Gedaechtnis) ────────
# Storage liegt im Repo-Bind-Mount aria-data/brain/qdrant.
# Damit Backup/Export/Import komplett ueber das Filesystem gehen.
qdrant:
image: qdrant/qdrant:latest
container_name: aria-qdrant
volumes:
- ./aria-data/brain/qdrant:/qdrant/storage
restart: unless-stopped
networks:
- aria-net
# ─── ARIA Brain (Agent + Memory) ─────────────────────────
# Loest das alte aria-core (OpenClaw) ab. Vector-DB-basiertes
# Memory, eigener Agent-Loop, SSH zur aria-wohnung-VM.
brain:
build: ./aria-brain
container_name: aria-brain
hostname: aria-wohnung-brain # damit ssh known_hosts stabil bleibt
extra_hosts:
- "host.docker.internal:host-gateway" # Zugriff auf die VM via SSH
depends_on:
- qdrant
- proxy
environment:
- QDRANT_HOST=aria-qdrant
- QDRANT_PORT=6333
- PROXY_URL=http://proxy:3456
- ARIA_AUTH_TOKEN=${ARIA_AUTH_TOKEN:-}
# Read-Timeout fuer den Proxy-Call. Hoch, weil Agent-Loops (Pentests
# etc.) auch eine Stunde+ dauern koennen. Der Proxy seinerseits hat
# einen Idle-Watchdog (Default 20min Inaktivitaet) der den Subprocess
# killt, der dann seinen close-Event sendet — Brain bekommt also
# immer was zurueck, auch bei wirklich haengenden Subprozessen.
# Connect/Write/Pool sind klein (10/30/10s) damit toter Proxy
# schnell erkannt wird (siehe proxy_client.py).
- PROXY_TIMEOUT_SEC=${PROXY_TIMEOUT_SEC:-86400}
# OAuth-Callback-URL Bestandteile. Brain baut daraus
# https://{RVS_HOST}:{RVS_PORT_PUBLIC}/oauth/callback/{service} als
# redirect_uri fuer Provider wie Spotify/Google/etc. RVS_PORT_PUBLIC
# ist der nach aussen exposed Port (= TLS-Port hinter Caddy/Nginx),
# nicht der interne RVS-Container-Port.
- RVS_HOST=${RVS_HOST:-}
- RVS_PORT_PUBLIC=${RVS_PORT_PUBLIC:-${RVS_PORT:-443}}
- RVS_TLS=${RVS_TLS:-true}
volumes:
- ./aria-data/brain/data:/data # Memory-Cache + Skills + Models (bind-mount fuer Export)
- ./aria-data/brain-import:/import:ro # Quell-MDs fuer den initialen Memory-Import (read-only)
- ./aria-data/ssh:/root/.ssh # SSH-Keys fuer aria-wohnung (geteilt mit Proxy)
- ./aria-shared:/shared # gleicher Austausch-Speicher wie Bridge
restart: unless-stopped
networks:
- aria-net
# ─── ARIA Voice Bridge ──────────────────────────────────
bridge:
build: ./bridge
container_name: aria-bridge
depends_on:
- brain
networks:
- aria-net
ports:
- "3001:3001" # Diagnostic Web-UI (Diagnostic teilt Netzwerk mit Bridge)
volumes:
- ./aria-shared:/shared # Shared Volume fuer Datei-Austausch
# Audio-Zugriff
- /run/user/1000/pulse:/run/user/1000/pulse
- /dev/snd:/dev/snd
devices:
- /dev/snd
environment:
- PULSE_SERVER=unix:/run/user/1000/pulse/native
- BRAIN_URL=http://aria-brain:8080
- ARIA_AUTH_TOKEN=${ARIA_AUTH_TOKEN:-}
- RVS_HOST=${RVS_HOST:-}
- RVS_PORT=${RVS_PORT:-443}
- RVS_TLS=${RVS_TLS:-true}
- RVS_TLS_FALLBACK=${RVS_TLS_FALLBACK:-true}
- RVS_TOKEN=${RVS_TOKEN:-}
restart: unless-stopped
# ─── Diagnostic (Selbstcheck-UI und Einstellungen) ────
# Teilt Netzwerk mit Bridge, damit der Diagnostic-Server die
# Bridge auf localhost erreichen kann.
diagnostic:
build: ./diagnostic
container_name: aria-diagnostic
depends_on:
- bridge
network_mode: "service:bridge"
volumes:
- /var/run/docker.sock:/var/run/docker.sock # Container Restart + Brain-Export/Import
- ./aria-data/config/diag-state:/data # Persistenter State (aktive Session etc.)
- ./aria-shared:/shared # Shared Volume (Uploads + Config + Voices)
- ./aria-data/brain:/brain # Brain-Export/Import (tar.gz aus Bind-Mount)
environment:
- ARIA_AUTH_TOKEN=${ARIA_AUTH_TOKEN:-}
- PROXY_URL=http://proxy:3456
- BRAIN_URL=http://aria-brain:8080
- RVS_HOST=${RVS_HOST:-}
- RVS_PORT=${RVS_PORT:-443}
- RVS_TLS=${RVS_TLS:-true}
- RVS_TLS_FALLBACK=${RVS_TLS_FALLBACK:-true}
- RVS_TOKEN=${RVS_TOKEN:-}
restart: unless-stopped
networks:
aria-net:
driver: bridge