fix(diagnostic+brain): Sprachmodell-Einstellung auf runtime.json umgestellt
War kaputt nach OpenClaw-Abriss: handleGetModel/handleSetModel haben gegen
aria-core (dockerExec + node-script in den Container) gearbeitet, der gibt's
nicht mehr.
diagnostic/server.js
- handleGetModel/handleSetModel lesen/schreiben jetzt brainModel in
/shared/config/runtime.json
- RUNTIME_CONFIG_FIELDS um "brainModel" erweitert
- Tote Variante (findSettingsFile + base64-node-script) komplett raus
aria-brain/proxy_client.py
- Liest brainModel aus runtime.json beim Container-Start
- Fallback: BRAIN_MODEL env → "claude-sonnet-4" Default
- Bei Aenderung in Diagnostic: aria-brain restarten damit's greift
(Hinweis steht in der UI)
diagnostic/index.html
- Section "Model" → "Sprachmodell (Brain)"
- Hinweis-Block mit Default-Erklaerung und Restart-Hinweis
- Modelle: claude-sonnet-4 (default), claude-opus-4, claude-haiku-4-5
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -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
|
||||
|
||||
+11
-3
@@ -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-Einstellungen -->
|
||||
<!-- Brain-Model-Einstellung -->
|
||||
<div class="settings-section">
|
||||
<h2>Model</h2>
|
||||
<h2>Sprachmodell (Brain)</h2>
|
||||
<div class="card" style="max-width:500px;">
|
||||
<div style="font-size:11px;color:#8888AA;margin-bottom:10px;line-height:1.5;">
|
||||
Welches Claude-Model nutzt das Brain pro Anfrage. Wert wird in
|
||||
<code>/shared/config/runtime.json</code> als <code>brainModel</code> persistiert.
|
||||
Bei Aenderung: <strong>aria-brain restarten</strong> (Reparatur-Section oben), damit's greift.
|
||||
<br><br>
|
||||
Verfuegbar via Proxy: <code>claude-sonnet-4</code> (Default — schnell, gut),
|
||||
<code>claude-opus-4</code> (langsam, smarter), <code>claude-haiku-4-5</code> (sehr schnell, kleiner Kontext).
|
||||
</div>
|
||||
<div style="display:flex;align-items:center;gap:8px;margin-bottom:8px;">
|
||||
<span style="font-size:12px;color:#8888AA;white-space:nowrap;">Aktives Model:</span>
|
||||
<input type="text" id="setting-model" placeholder="z.B. proxy/claude-sonnet-4" style="flex:1;background:#1E1E2E;border:1px solid #333;border-radius:4px;padding:6px 8px;color:#E0E0F0;font-family:inherit;font-size:12px;">
|
||||
<input type="text" id="setting-model" placeholder="claude-sonnet-4" style="flex:1;background:#1E1E2E;border:1px solid #333;border-radius:4px;padding:6px 8px;color:#E0E0F0;font-family:inherit;font-size:12px;">
|
||||
<button class="btn secondary" onclick="loadModel()" style="padding:4px 8px;font-size:10px;">Laden</button>
|
||||
<button class="btn" onclick="saveModel()" style="padding:4px 8px;font-size:10px;">Setzen</button>
|
||||
</div>
|
||||
|
||||
+22
-21
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user