fix(models): Modell-Liste kommt jetzt von Anthropic — und feste Versionen greifen wirklich
Zwei Fehler. Der zweite war der schlimmere.
1) Die Liste war handgepflegt und damit garantiert veraltet.
Sie kannte "Opus (aktuell: Opus 5)" — waehrend es laengst Opus 5.5,
Sonnet 5.5 und Fable 5.1 gab. Der Knopf "↻ Aktualisieren" las nur eine
lokale Datei neu und aktualisierte damit gar nichts.
Jetzt kommt die Liste aus Anthropics eigenem Modell-Katalog
(downloads.claude.ai/model-catalog/v1/catalog.json, Surface 'cc') —
dieselbe Quelle, aus der sich Claude Code selbst bedient. Oeffentlich,
ohne API-Key (die Models-API braucht einen; mit dem Max-Abo gibt es keinen).
6h-Cache plus Datei-Cache, der auch offline und bei abgelaufenem TTL
einspringt: eine etwas alte echte Liste ist besser als keine.
Die Tier-Aliase (opus/sonnet/haiku/fable) bleiben vorne und bleiben die
Empfehlung — sie folgen automatisch der neuesten Version. Darunter die
exakten Versionen, aeltere ausdruecklich als solche markiert.
2) Eine feste Version liess sich faktisch nicht waehlen.
extractModel() hatte eine MODEL_MAP und fiel fuer alles Unbekannte STILL
auf "opus" zurueck. Wer "claude-opus-5-5" setzte, bekam ohne jede Meldung
das Tier-Default. Schlimmer noch: claude-opus-5 und claude-fable-5 standen
selbst in der Map und wurden auf ihr Tier eingeschmolzen — eine bewusst
gewaehlte aeltere Version wurde also durch die neueste ersetzt.
Volle Modellnamen gehen jetzt unveraendert an die CLI. Die versteht sie
("--model: an alias for the latest model or a model's full name") und
meldet sich selbst klar, wenn sie einen Namen nicht kennt — ehrlicher als
ein stilles Downgrade. Nur echter Muell faellt noch auf "opus", und das
wird geloggt.
Nachgewiesen gegen den LIVE-Katalog und die echte CLI im Proxy-Container:
20 Pruefungen gruen, u.a. dass alle 12 gelieferten exakten Versionen den Proxy
unveraendert passieren. `claude --print --model claude-opus-5-5` antwortet.
Stefans aktive Einstellung ist der Alias "opus" — am laufenden Betrieb aendert
sich dadurch nichts.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
+50
-9
@@ -611,19 +611,27 @@
|
||||
<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>
|
||||
ARIA laeuft ueber dein Claude-Max-Abo (CLI) — waehlbar ist der <strong>Tier</strong>
|
||||
(Opus/Sonnet/Haiku), nicht eine feste Version. Die CLI nimmt automatisch das
|
||||
jeweils aktuelle Modell des Tiers.
|
||||
ARIA laeuft ueber dein Claude-Max-Abo (CLI). Du hast zwei Möglichkeiten:
|
||||
<br>
|
||||
<strong>Automatisch</strong> (Opus/Sonnet/Haiku/Fable) — folgt immer der neuesten
|
||||
Version dieses Tiers, ohne dass du etwas pflegen musst. Für den Alltag die
|
||||
richtige Wahl.
|
||||
<br>
|
||||
<strong>Feste Version</strong> (z.B. „Opus 5.5") — genau dieses Modell, auch wenn
|
||||
später ein neueres kommt.
|
||||
<br><br>
|
||||
Die Auswahlliste kommt aus <code>/shared/config/models.json</code> — dort kannst du
|
||||
Tiers/Beschreibungen anpassen (kein Neustart noetig, danach „↻ Aktualisieren").
|
||||
Die Liste kommt aus Anthropics eigenem <strong>Modell-Katalog</strong>
|
||||
(<code>downloads.claude.ai</code>) — dieselbe Quelle, aus der sich Claude Code
|
||||
selbst bedient. „↻ Aktualisieren" holt sie frisch; sonst gilt ein 6-Stunden-Cache.
|
||||
Die automatischen Tiers kommen weiterhin aus
|
||||
<code>/shared/config/models.json</code>.
|
||||
</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>
|
||||
<select id="setting-model-select" onchange="onModelSelectChange()" style="flex:1;background:#1E1E2E;border:1px solid #333;border-radius:4px;padding:6px 8px;color:#E0E0F0;font-family:inherit;font-size:12px;">
|
||||
<option value="">(lade Liste…)</option>
|
||||
</select>
|
||||
<button class="btn secondary" onclick="loadModelList()" title="Liste vom Proxy neu holen" style="padding:4px 8px;font-size:10px;">↻ Aktualisieren</button>
|
||||
<button class="btn secondary" onclick="loadModelList(true)" title="Modell-Liste frisch von Anthropic holen (Modell-Katalog)" style="padding:4px 8px;font-size:10px;">↻ Aktualisieren</button>
|
||||
<button class="btn" onclick="saveModel()" style="padding:4px 8px;font-size:10px;">Setzen</button>
|
||||
</div>
|
||||
<div id="model-desc" style="font-size:10px;color:#6a6a88;margin-bottom:6px;min-height:12px;"></div>
|
||||
@@ -7899,17 +7907,46 @@
|
||||
|
||||
// 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() {
|
||||
// force=true (Knopf „↻ Aktualisieren") holt die Liste frisch von Anthropic
|
||||
// statt aus dem Proxy-Cache.
|
||||
async function loadModelList(force) {
|
||||
const sel = document.getElementById('setting-model-select');
|
||||
const st = document.getElementById('model-status');
|
||||
if (!sel) return;
|
||||
if (force && st) { st.textContent = 'Hole Modell-Liste von Anthropic …'; st.style.color = '#8888AA'; }
|
||||
try {
|
||||
const r = await fetch('/api/models-list');
|
||||
const r = await fetch('/api/models-list' + (force ? '?refresh=1' : ''));
|
||||
const d = await r.json();
|
||||
if (!d.ok) throw new Error(d.error || 'Fehler');
|
||||
_modelListCache = d.models || [];
|
||||
sel.innerHTML = '';
|
||||
for (const m of _modelListCache) {
|
||||
// Nach Herkunft gruppieren, damit die Wahl klar ist:
|
||||
// Tier — folgt automatisch der neuesten Version (Empfehlung)
|
||||
// main — die aktuell von Anthropic vorgeschlagenen Versionen
|
||||
// overflow— aeltere Versionen, nur wenn man sie bewusst will
|
||||
const GROUPS = [
|
||||
['tier', 'Automatisch (folgt der neuesten Version)'],
|
||||
['main', 'Aktuelle Versionen'],
|
||||
['overflow', 'Ältere Versionen'],
|
||||
];
|
||||
for (const [section, label] of GROUPS) {
|
||||
const inGroup = _modelListCache.filter(m => (m.section || 'tier') === section);
|
||||
if (!inGroup.length) continue;
|
||||
const g = document.createElement('optgroup');
|
||||
g.label = label;
|
||||
for (const m of inGroup) {
|
||||
const opt = document.createElement('option');
|
||||
opt.value = m.id;
|
||||
opt.textContent = m.displayName || m.id;
|
||||
g.appendChild(opt);
|
||||
}
|
||||
sel.appendChild(g);
|
||||
}
|
||||
// Unbekannte Sektionen nicht verschlucken (aeltere Proxy-Version
|
||||
// liefert gar kein section-Feld -> die landen oben unter 'tier').
|
||||
const known = new Set(GROUPS.map(g => g[0]));
|
||||
const rest = _modelListCache.filter(m => !known.has(m.section || 'tier'));
|
||||
for (const m of rest) {
|
||||
const opt = document.createElement('option');
|
||||
opt.value = m.id;
|
||||
opt.textContent = m.displayName || m.id;
|
||||
@@ -7920,6 +7957,10 @@
|
||||
opt.value = ''; opt.textContent = '(keine Modelle vom Proxy)';
|
||||
sel.appendChild(opt);
|
||||
}
|
||||
if (st && d.catalogOk === false) {
|
||||
st.textContent = 'Anthropic-Katalog nicht erreichbar — nur die automatischen Tiers verfügbar.';
|
||||
st.style.color = '#FFD60A';
|
||||
}
|
||||
onModelSelectChange();
|
||||
// Aktuelles Model vom Brain holen → markiert die richtige Option
|
||||
loadModel();
|
||||
|
||||
@@ -2204,22 +2204,27 @@ 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") {
|
||||
} else if (req.url.startsWith("/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`);
|
||||
// ?refresh=1 weiterreichen: der Proxy umgeht damit seinen Katalog-Cache
|
||||
// und holt die Liste frisch von Anthropic („↻ Aktualisieren").
|
||||
const refresh = /[?&]refresh=1\b/.test(req.url) ? "?refresh=1" : "";
|
||||
const r = await fetch(`${PROXY_URL}/v1/models${refresh}`);
|
||||
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 || "",
|
||||
// section: tier | main | overflow — die UI gruppiert danach.
|
||||
section: m.section || "tier",
|
||||
}));
|
||||
res.writeHead(200, { "Content-Type": "application/json" });
|
||||
res.end(JSON.stringify({ ok: true, models }));
|
||||
res.end(JSON.stringify({ ok: true, models, catalogOk: d.catalog_ok !== false }));
|
||||
} catch (err) {
|
||||
res.writeHead(502, { "Content-Type": "application/json" });
|
||||
res.end(JSON.stringify({ ok: false, error: String(err && err.message || err) }));
|
||||
|
||||
Reference in New Issue
Block a user