- Welches Claude-Model nutzt das Brain pro Anfrage. Wert wird in
+ Welches Claude-Model das Brain pro Anfrage nutzt. 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).
+ ARIA laeuft ueber dein Claude-Max-Abo (CLI) — waehlbar ist der Tier
+ (Opus/Sonnet/Haiku), nicht eine feste Version. Die CLI nimmt automatisch das
+ jeweils aktuelle Modell des Tiers.
Aktives Model:
-
-
+
+
-
+
+
+
+ Erweitert: freie Model-ID
+
+
+
+
+
+
@@ -1504,6 +1516,8 @@
send({ action: 'load_chat_history' });
// Brain-Card initial laden (sonst zeigt sie "Lade...")
try { loadBrainStatus(); } catch {}
+ // Sprachmodell-Dropdown befuellen (kuratierte Tier-Liste vom Proxy)
+ try { loadModelList(); } catch {}
};
// Brain-Status periodisch refreshen damit die Card live bleibt
@@ -1966,8 +1980,14 @@
// session_restarted / openclaw_config WS-Events entfernt — aria-core ist raus.
if (msg.type === 'model_info') {
const el = document.getElementById('setting-model');
+ const sel = document.getElementById('setting-model-select');
const st = document.getElementById('model-status');
if (el && msg.model) el.value = msg.model;
+ // Dropdown auf das aktuelle Model stellen (falls in der Liste).
+ if (sel && msg.model) {
+ const has = Array.from(sel.options).some(o => o.value === msg.model);
+ if (has) { sel.value = msg.model; onModelSelectChange(); }
+ }
if (st) {
st.textContent = msg.info || msg.error || '';
st.style.color = msg.error ? '#FF6B6B' : '#34C759';
@@ -6062,14 +6082,66 @@
// ── Einstellungen: Model ────────────────────────────────
+ let _modelListCache = [];
+
function loadModel() {
send({ action: 'get_model' });
}
+ // Kuratierte Tier-Liste vom Proxy holen (via Diagnostic-Server) und ins
+ // Dropdown fuellen. Danach get_model, damit das aktive Model markiert wird.
+ async function loadModelList() {
+ const sel = document.getElementById('setting-model-select');
+ const st = document.getElementById('model-status');
+ if (!sel) return;
+ try {
+ const r = await fetch('/api/models-list');
+ const d = await r.json();
+ if (!d.ok) throw new Error(d.error || 'Fehler');
+ _modelListCache = d.models || [];
+ sel.innerHTML = '';
+ for (const m of _modelListCache) {
+ const opt = document.createElement('option');
+ opt.value = m.id;
+ opt.textContent = m.displayName || m.id;
+ sel.appendChild(opt);
+ }
+ if (!_modelListCache.length) {
+ const opt = document.createElement('option');
+ opt.value = ''; opt.textContent = '(keine Modelle vom Proxy)';
+ sel.appendChild(opt);
+ }
+ onModelSelectChange();
+ // Aktuelles Model vom Brain holen → markiert die richtige Option
+ loadModel();
+ } catch (e) {
+ if (st) { st.textContent = 'Model-Liste laden fehlgeschlagen: ' + e.message; st.style.color = '#FF6B6B'; }
+ }
+ }
+
+ function onModelSelectChange() {
+ const sel = document.getElementById('setting-model-select');
+ const desc = document.getElementById('model-desc');
+ if (!sel || !desc) return;
+ const m = _modelListCache.find(x => x.id === sel.value);
+ desc.textContent = m && m.description ? m.description : '';
+ }
+
function saveModel() {
+ const sel = document.getElementById('setting-model-select');
+ const model = sel && sel.value ? sel.value : '';
+ if (!model) return;
+ send({ action: 'set_model', model });
+ const st = document.getElementById('model-status');
+ if (st) { st.textContent = 'Gesetzt — aria-brain neu starten (Reparatur oben), damit es greift.'; st.style.color = '#FFD60A'; }
+ }
+
+ function saveModelFreeText() {
const model = document.getElementById('setting-model').value.trim();
if (!model) return;
send({ action: 'set_model', model });
+ const st = document.getElementById('model-status');
+ if (st) { st.textContent = 'Gesetzt (Freitext) — aria-brain neu starten, damit es greift.'; st.style.color = '#FFD60A'; }
}
// ── Einstellungen: OpenClaw Config ──────────────────────
diff --git a/diagnostic/server.js b/diagnostic/server.js
index b989ce0..fb1fbd7 100644
--- a/diagnostic/server.js
+++ b/diagnostic/server.js
@@ -1625,6 +1625,28 @@ const server = http.createServer((req, res) => {
res.end(JSON.stringify({ ok: false, error: err.message }));
}
return;
+ } else if (req.url === "/api/models-list" && req.method === "GET") {
+ // Kuratierte Model-Liste vom Proxy (/v1/models) — Tier-Auswahl fuers
+ // Sprachmodell-Dropdown. ARIA laeuft ueber das Max-Abo/CLI, waehlbar ist
+ // der Tier (opus/sonnet/haiku), keine feste Version.
+ (async () => {
+ try {
+ const r = await fetch(`${PROXY_URL}/v1/models`);
+ const d = await r.json();
+ const models = (d.data || []).map(m => ({
+ id: m.id,
+ tier: m.tier || m.id,
+ displayName: m.display_name || m.id,
+ description: m.description || "",
+ }));
+ res.writeHead(200, { "Content-Type": "application/json" });
+ res.end(JSON.stringify({ ok: true, models }));
+ } catch (err) {
+ res.writeHead(502, { "Content-Type": "application/json" });
+ res.end(JSON.stringify({ ok: false, error: String(err && err.message || err) }));
+ }
+ })();
+ return;
} else if (req.url === "/api/files-list" && req.method === "GET") {
// Liste alle Dateien in /shared/uploads/ — die kommen entweder vom User
// (Upload aus App/Diagnostic) oder von ARIA (aria_. Pattern).
diff --git a/proxy-patches/routes.js b/proxy-patches/routes.js
index b954351..acc558a 100644
--- a/proxy-patches/routes.js
+++ b/proxy-patches/routes.js
@@ -453,26 +453,32 @@ async function handleNonStreamingResponse(res, subprocess, cliInput, requestId)
* Returns available models
*/
export function handleModels(_req, res) {
+ // ARIA laeuft ueber das Claude-Max-Abo via CLI — waehlbar ist der TIER
+ // (opus/sonnet/haiku), nicht eine feste Modellversion. Die CLI loest den
+ // Alias auf das AKTUELLE Modell des Tiers auf. Die id-Strings muessen von
+ // openai-to-cli.js extractModel() erkannt werden (MODEL_MAP). display_name/
+ // tier/description sind ARIA-Zusatzfelder fuers Diagnostic-Dropdown.
+ const created = Math.floor(Date.now() / 1000);
res.json({
object: "list",
data: [
{
- id: "claude-opus-4",
- object: "model",
- owned_by: "anthropic",
- created: Math.floor(Date.now() / 1000),
+ id: "claude-sonnet-4", object: "model", owned_by: "anthropic", created,
+ tier: "sonnet",
+ display_name: "Sonnet (aktuell: Sonnet 5)",
+ description: "Schnell & gut — Standard fuer den Alltag.",
},
{
- id: "claude-sonnet-4",
- object: "model",
- owned_by: "anthropic",
- created: Math.floor(Date.now() / 1000),
+ id: "claude-opus-4", object: "model", owned_by: "anthropic", created,
+ tier: "opus",
+ display_name: "Opus (aktuell: Opus 4.8)",
+ description: "Langsamer, aber am schlausten — fuer schwere/lange Aufgaben.",
},
{
- id: "claude-haiku-4",
- object: "model",
- owned_by: "anthropic",
- created: Math.floor(Date.now() / 1000),
+ id: "claude-haiku-4", object: "model", owned_by: "anthropic", created,
+ tier: "haiku",
+ display_name: "Haiku (aktuell: Haiku 4.5)",
+ description: "Sehr schnell & guenstig, kleinerer Kontext — fuer einfache Tasks.",
},
],
});