diff --git a/aria-brain/proxy_client.py b/aria-brain/proxy_client.py index 8bf7a8e..d747a07 100644 --- a/aria-brain/proxy_client.py +++ b/aria-brain/proxy_client.py @@ -9,8 +9,10 @@ neuen CLI-Prozess (Cold-Start), das dauert. from __future__ import annotations +import json import logging import os +from pathlib import Path from typing import List, Optional import httpx @@ -18,11 +20,28 @@ from pydantic import BaseModel logger = logging.getLogger(__name__) -DEFAULT_MODEL = os.environ.get("BRAIN_MODEL", "claude-sonnet-4") +RUNTIME_CONFIG_FILE = Path("/shared/config/runtime.json") +ENV_MODEL = os.environ.get("BRAIN_MODEL", "claude-sonnet-4") PROXY_URL = os.environ.get("PROXY_URL", "http://proxy:3456") PROXY_TIMEOUT_SEC = float(os.environ.get("PROXY_TIMEOUT_SEC", "300")) +def _read_model_from_runtime() -> str: + """Liest brainModel aus runtime.json. Fallback: ENV BRAIN_MODEL.""" + try: + if RUNTIME_CONFIG_FILE.exists(): + data = json.loads(RUNTIME_CONFIG_FILE.read_text(encoding="utf-8")) + m = (data.get("brainModel") or "").strip() + if m: + return m + except Exception as exc: + logger.warning("runtime.json lesen fehlgeschlagen: %s", exc) + return ENV_MODEL + + +DEFAULT_MODEL = _read_model_from_runtime() + + class Message(BaseModel): role: str # "system" | "user" | "assistant" | "tool" content: Optional[str] = None diff --git a/diagnostic/index.html b/diagnostic/index.html index 8d514eb..7272334 100644 --- a/diagnostic/index.html +++ b/diagnostic/index.html @@ -659,13 +659,21 @@ selbst (Skills + skill_create Meta-Tool). Es gibt keine granulare Permission-Maske, Brain weiss zur Laufzeit welche Tools es hat. --> - +
-

Model

+

Sprachmodell (Brain)

+
+ Welches Claude-Model nutzt das Brain pro Anfrage. Wert wird in + /shared/config/runtime.json als brainModel persistiert. + Bei Aenderung: aria-brain restarten (Reparatur-Section oben), damit's greift. +

+ Verfuegbar via Proxy: claude-sonnet-4 (Default — schnell, gut), + claude-opus-4 (langsam, smarter), claude-haiku-4-5 (sehr schnell, kleiner Kontext). +
Aktives Model: - +
diff --git a/diagnostic/server.js b/diagnostic/server.js index cca1022..6ede9aa 100644 --- a/diagnostic/server.js +++ b/diagnostic/server.js @@ -65,6 +65,7 @@ const RUNTIME_CONFIG_FILE = "/shared/config/runtime.json"; const RUNTIME_CONFIG_FIELDS = [ "RVS_HOST", "RVS_PORT", "RVS_TLS", "RVS_TOKEN", "ARIA_AUTH_TOKEN", "WHISPER_MODEL", "WHISPER_LANGUAGE", + "brainModel", ]; function readRuntimeConfig() { const envDefaults = { @@ -2164,42 +2165,42 @@ async function handleRestartSession(clientWs) { // Claude Code laeuft mit --dangerously-skip-permissions (Alles oder Nichts). // Root-Check wird via CLAUDE_CODE_BUBBLEWRAP=1 in docker-compose.yml umgangen. -// ── Einstellungen: Model ──────────────────────────────── +// ── Einstellungen: Model (Brain) ──────────────────────── +// Liest/schreibt brainModel in /shared/config/runtime.json — Brain liest +// das beim Container-Start. Bei Aenderung: aria-brain restarten +// (Einstellungen → Reparatur → 🚨 aria-brain neu). -async function handleGetModel(clientWs) { +function handleGetModel(clientWs) { try { - const raw = await dockerExec("aria-core", `echo $DEFAULT_MODEL`); - clientWs.send(JSON.stringify({ type: "model_info", model: raw.trim(), info: "Aktuelles Model (ENV)" })); + const cfg = readRuntimeConfig(); + const model = (cfg.brainModel || "").trim() || "claude-sonnet-4"; + clientWs.send(JSON.stringify({ + type: "model_info", + model, + info: "Brain-Model (runtime.json) — bei Aenderung: aria-brain restarten", + })); } catch (err) { clientWs.send(JSON.stringify({ type: "model_info", error: err.message })); } } -async function handleSetModel(clientWs, model) { +function handleSetModel(clientWs, model) { if (!model || typeof model !== "string") { clientWs.send(JSON.stringify({ type: "model_info", error: "Kein Model angegeben" })); return; } try { - // Model in Settings speichern (OpenClaw liest das) - const settingsPath = await findSettingsFile(); - const script = [ - 'const fs=require("fs");', - `const f="${settingsPath}";`, - 'let s={};try{s=JSON.parse(fs.readFileSync(f,"utf8"));}catch(e){}', - `s.model=${JSON.stringify(model)};`, - `const dir=f.substring(0,f.lastIndexOf("/"));`, - 'try{fs.mkdirSync(dir,{recursive:true});}catch(e){}', - 'fs.writeFileSync(f,JSON.stringify(s,null,2));', - ].join(""); - const b64 = Buffer.from(script).toString("base64"); - await dockerExec("aria-core", `echo ${b64} | base64 -d | node`); - - clientWs.send(JSON.stringify({ type: "model_info", model, info: `Model auf "${model}" gesetzt (Neustart noetig)` })); - log("info", "server", `Model gesetzt: ${model}`); + writeRuntimeConfig({ brainModel: model.trim() }); + log("info", "server", `Brain-Model gesetzt: ${model.trim()}`); + clientWs.send(JSON.stringify({ + type: "model_info", + model: model.trim(), + info: `Model auf "${model.trim()}" gesetzt — aria-brain neu starten damit's greift`, + })); } catch (err) { clientWs.send(JSON.stringify({ type: "model_info", error: err.message })); } + return; } // OpenClaw-Config-Handler entfernt — aria-core ist raus.