diff --git a/diagnostic/index.html b/diagnostic/index.html index 15ea631..97cf45b 100644 --- a/diagnostic/index.html +++ b/diagnostic/index.html @@ -878,20 +878,32 @@

Sprachmodell (Brain)

- 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.", }, ], });