From e16e3dea38f98c720282c94e711ce5fd699e3272 Mon Sep 17 00:00:00 2001
From: Mikei386 <44135113+Mikei386@users.noreply.github.com>
Date: Thu, 1 Oct 2026 09:21:36 +0200
Subject: [PATCH] Organize navigation and compact model detail lists
---
README.md | 16 ++++++++++++++++
catalog-ui.js | 7 ++++---
endpoint-ui.js | 2 +-
index.html | 2 +-
profiles-ui.js | 7 ++++---
studio.js | 10 +++++++---
style.css | 4 ++++
video-ui.js | 4 ++--
8 files changed, 39 insertions(+), 13 deletions(-)
diff --git a/README.md b/README.md
index 15489ca..bc2c77b 100644
--- a/README.md
+++ b/README.md
@@ -7,6 +7,22 @@ Die Navigation beginnt mit dem [Dashboard](DASHBOARD.md). Es zeigt die
Live-Telemetrie und die aus dem alten Athena-Dashboard übernommene History;
die frühere separate Hardware-Seite wurde entfernt.
+## Navigation und Detailansichten
+
+Die **Übersicht** enthält Dashboard und Steuerung (Endpunkt und GPU-Modi).
+**KI-Werkzeuge** trennt Chat & Sprachmodelle, Bildgenerierung, Musikgenerierung,
+Sprachausgabe, Spracherkennung, Stimmwerkzeuge und Videogenerierung.
+Zusätzliche Oberflächen stehen unter **Anwendungen → Weitere Dienste**.
+
+Unter **Einstellungen → Laufzeiten** führt eine aufklappbare Liste zu den
+Installations-, Versions- und Statusseiten. Die einzelnen Laufzeiten stehen
+nicht mehr separat in der Seitenleiste. Bibliothek und Profile verwenden
+kompakte, aufklappbare Zeilen: Details, API-Freigabe, Komponenten und Aktionen
+stehen in der geöffneten Zeile. Downloads behalten Fortschritt, Geschwindigkeit,
+Restzeit und Warteschlangenaktionen. Der laufende Betrieb wird zentral unter
+**Steuerung** angezeigt; Testbereiche behalten ihre jeweiligen Formulare.
+Bestehende URL-Fragmente bleiben gültig.
+
## Vorläufige Testinstallation auf Debian
Zielprodukt: nativer systemd-Dienst auf Debian. Der derzeitige Docker-Installer dient ausschließlich der isolierten Testphase.
diff --git a/catalog-ui.js b/catalog-ui.js
index f3759a4..269603c 100644
--- a/catalog-ui.js
+++ b/catalog-ui.js
@@ -14,7 +14,7 @@ window.CatalogUI = (() => {
function html(library, downloads=false) {
return `
HUGGING FACE · LIVE-KATALOG
${downloads ? 'Downloads' : library ? 'Deine Dateien auf Athena' : 'Das nächste Modell entdecken'}
${downloads ? 'Abgeschlossene Einträge ausblenden. Die Dateien bleiben in deiner Bibliothek.' : library ? 'Heruntergeladene Dateien mit festgehaltener Version und Integritätsprüfung.' : 'Modell suchen, Variante vergleichen und gezielt auf Athena herunterladen.'}
- ${downloads ? '' : library ? '' : `
Blendet anhand der Hub-Metadaten Finetunes, LoRAs, Merges und separate Quantisierungen aus. Unvollständig gekennzeichnete Ableitungen können sichtbar bleiben.
Beliebte Modelle
01 ENTDECKEN → 02 AUSWÄHLEN → 03 LADEN
Welches Modell interessiert dich?
Wähle ein Ergebnis, um Dateien, Varianten und Lizenz zu prüfen.
Downloads belegen Festplattenspeicher. Sie starten kein Modell. Für Bild, Audio und Video sind häufig mehrere Dateien und ein passender Worker erforderlich.
`}`;
+ ${downloads ? '' : library ? '
' : `
Blendet anhand der Hub-Metadaten Finetunes, LoRAs, Merges und separate Quantisierungen aus. Unvollständig gekennzeichnete Ableitungen können sichtbar bleiben.
Beliebte Modelle
01 ENTDECKEN → 02 AUSWÄHLEN → 03 LADEN
Welches Modell interessiert dich?
Wähle ein Ergebnis, um Dateien, Varianten und Lizenz zu prüfen.
Downloads belegen Festplattenspeicher. Sie starten kein Modell. Für Bild, Audio und Video sind häufig mehrere Dateien und ein passender Worker erforderlich.
Eigener Router für Deck-Profile. Bestehende Athena-Dienste bleiben unabhängig.
${settings?'
Lokaler API-Port
Der Zugriff verwendet den API-Token aus Zugang & API. Verwaltungsoberfläche und API haben getrennte Ports.
Am Endpunkt angebotene Profile
Nur explizit aktivierte, ausführbare Profile erscheinen in GET /v1/models. Aktivieren lädt noch kein Modell.
API-Routen
POST /v1/chat/completions · Text und Streaming POST /v1/images/generations · Qwen-Image-Rezept, ein Bild als b64_json POST /v1/audio/speech und POST /v1/audio/transcriptions · noch nicht eingerichtet (501)
Alle Routen nutzen denselben Port und Bearer-Token. Bei Bildaufträgen bestimmt das Profil Auflösung, Schritte, Guidance und Seed. Noch keine Bildbearbeitung oder Vision-Eingaben.
Eigener Router für Deck-Profile. Bestehende Athena-Dienste bleiben unabhängig.
${settings?'
Lokaler API-Port
Der Zugriff verwendet den API-Token aus Zugang & API-Token. Verwaltungsoberfläche und API haben getrennte Ports.
Am Endpunkt angebotene Profile
Nur explizit aktivierte, ausführbare Profile erscheinen in GET /v1/models. Aktivieren lädt noch kein Modell.
API-Routen
POST /v1/chat/completions · Text und Streaming POST /v1/images/generations · Qwen-Image-Rezept, ein Bild als b64_json POST /v1/audio/speech und POST /v1/audio/transcriptions · noch nicht eingerichtet (501)
Alle Routen nutzen denselben Port und Bearer-Token. Bei Bildaufträgen bestimmt das Profil Auflösung, Schritte, Guidance und Seed. Noch keine Bildbearbeitung oder Vision-Eingaben.
':''}`;
root=view.querySelector('#endpoint-page');
for(const action of ['start','stop'])root.querySelector('#endpoint-'+action).onclick=()=>mutate('/'+action,{});
root.querySelector('#endpoint-port-form')?.addEventListener('submit',event=>{event.preventDefault();mutate('/config',{port:Number(root.querySelector('#endpoint-port').value)});});
diff --git a/index.html b/index.html
index 6f75ff0..a86d788 100644
--- a/index.html
+++ b/index.html
@@ -1 +1 @@
-Athena DeckATHENA CONTROL SURFACEv0.7 · Router
+Athena DeckATHENA CONTROL SURFACEv0.7 · Router
diff --git a/profiles-ui.js b/profiles-ui.js
index 2ec140d..7194f7f 100644
--- a/profiles-ui.js
+++ b/profiles-ui.js
@@ -7,9 +7,10 @@ window.ProfilesUI=(()=>{
const root=document.querySelector('#live-profiles'),el=id=>root.querySelector('#'+id);let rows=[],models=[],schema={},enabled=[],gpus=[],projectors=[],entries=[],panelSequence=0;
const message=t=>{if(root.isConnected)el('profile-message').textContent=t;};
async function load(){try{const [p,c,h,ep]=await Promise.all([api('profiles'),api('catalog'),['chat','video'].includes(kind)?api('hardware').catch(()=>({gpus:[]})):Promise.resolve({gpus:[]}),api('endpoint')]);entries=c.entries;projectors=c.entries.filter(x=>x.role==='vision_projector'&&x.file.endsWith('.gguf'));enabled=ep.profiles.filter(x=>x.enabled).map(x=>x.id);gpus=h.gpus||[];if(!root.isConnected)return;rows=p.profiles.filter(x=>x.kind===kind);models=c.entries.filter(x=>x.kind===kind&&x.profile_eligible===true);schema=p.schemas[kind];el('profile-new').disabled=!models.length;
- el('profile-list').innerHTML=rows.map(p=>`GESPEICHERT AUF ATHENA
${e(p.name)}
${e(p.model?.file||'Modelldatei nicht verfügbar')}
`:''}${CatalogUI.executionHTML(p.execution)}${p.runnable?(kind==='video'?'Laufzeit bereit · Video-Modus in Übersicht aktivieren':'Laufzeit bereit · lädt bei Anfrage'):'Was fehlt zur Ausführung?'}${p.blockers.map(t=>`
${e(t)}
`).join('')}
${kind==='image'?``:''}
`).join('')||`
Noch keine Profile
${models.length?'Wähle eine heruntergeladene Modelldatei und lege dein erstes Profil an.':'Lade zuerst eine Gewichtsdatei unter Entdecken herunter.'}
${kind==='image'?'Der feste API-Name athena-image verwendet das hier freigegebene Bildprofil und dessen Auflösung. Höchstens ein Bildprofil ist am API-Endpunkt freigegeben. Ein neuer Haken ersetzt die bisherige Auswahl.':['audio','stt'].includes(kind)?'Eingerichtete Sprachprofile können am API-Endpunkt freigegeben werden.':kind==='chat'?'Mehrere Sprachmodellprofile können gleichzeitig am API-Endpunkt freigegeben sein.':kind==='video'?'Genau ein Videoprofil kann am API-Endpunkt freigegeben sein. Ein neuer Haken ersetzt die bisherige Auswahl. Die Übersicht lädt dieses Profil beim Wechsel auf Video; API-Name: athena-video. Zum Ändern der Freigabe zuerst auf LLM wechseln.':'Für diesen Bereich ist noch keine ausführbare Laufzeit am Endpunkt angebunden.'} Freigegeben bedeutet nicht bereits in den GPU-Speicher geladen.
`);
- root.querySelectorAll('[data-publish]').forEach(b=>b.onchange=async()=>{const checked=b.checked;root.querySelectorAll('[data-publish]').forEach(x=>x.disabled=true);try{await api('endpoint/profile',{id:b.dataset.publish,enabled:checked});await load();message(kind==='video'?'Video-Freigabe gespeichert. Die Übersicht lädt dieses Profil beim Wechsel auf Video.':'Endpunkt-Freigabe gespeichert. Geladen wird erst bei einer API-Anfrage.');}catch(error){await load();message(error.message);}});
+ const openRows=new Set([...root.querySelectorAll('.detail-row[open]')].map(x=>x.dataset.rowId));
+ el('profile-list').innerHTML=rows.map(p=>`${e(p.name)}${e(p.model?.file||'Modelldatei nicht verfügbar')}${p.parameters.context?`${e(p.parameters.context)} Token · ${e(p.parameters.slots||1)} Slots`:e(p.execution?.runtime||'Laufzeit prüfen')}${enabled.includes(p.id)?'API: freigegeben':'API: nicht freigegeben'}${p.runnable?'Bereit · lädt bei Anfrage':'Einrichtung fehlt'}
`:''}${CatalogUI.executionHTML(p.execution)}${p.runnable?(kind==='video'?'Laufzeit bereit · Video-Modus in Steuerung aktivieren':'Laufzeit bereit · lädt bei Anfrage'):'Was fehlt zur Ausführung?'}${p.blockers.map(t=>`
${e(t)}
`).join('')}
${kind==='image'?``:''}
`).join('')||`
Noch keine Profile
${models.length?'Wähle eine heruntergeladene Modelldatei und lege dein erstes Profil an.':'Lade zuerst eine Gewichtsdatei unter Entdecken herunter.'}
${kind==='image'?'Der feste API-Name athena-image verwendet das hier freigegebene Bildprofil und dessen Auflösung. Höchstens ein Bildprofil ist am API-Endpunkt freigegeben. Ein neuer Haken ersetzt die bisherige Auswahl.':['audio','stt'].includes(kind)?'Eingerichtete Sprachprofile können am API-Endpunkt freigegeben werden.':kind==='chat'?'Mehrere Sprachmodellprofile können gleichzeitig am API-Endpunkt freigegeben sein.':kind==='video'?'Genau ein Videoprofil kann am API-Endpunkt freigegeben sein. Ein neuer Haken ersetzt die bisherige Auswahl. Die Steuerung lädt dieses Profil beim Wechsel auf Video; API-Name: athena-video. Zum Ändern der Freigabe zuerst auf LLM wechseln.':kind==='music'?'Gib ein eingerichtetes Musikprofil frei, um es in der Steuerung verwenden zu können.':'Für diesen Bereich ist noch keine ausführbare Laufzeit am Endpunkt angebunden.'} Freigegeben bedeutet nicht bereits in den GPU-Speicher geladen.
`);
+ root.querySelectorAll('[data-publish]').forEach(b=>b.onchange=async()=>{const checked=b.checked;root.querySelectorAll('[data-publish]').forEach(x=>x.disabled=true);try{await api('endpoint/profile',{id:b.dataset.publish,enabled:checked});await load();message(kind==='video'?'Video-Freigabe gespeichert. Die Steuerung lädt dieses Profil beim Wechsel auf Video.':'Endpunkt-Freigabe gespeichert. Geladen wird erst bei einer API-Anfrage.');}catch(error){await load();message(error.message);}});
root.querySelectorAll('[data-delete]').forEach(b=>b.onclick=async()=>{const p=rows.find(p=>p.id===b.dataset.delete);if(!confirm(`Profil „${p.name}“ löschen? Modelldateien und Komponenten bleiben in der Bibliothek.`))return;b.disabled=true;try{await api('profiles/delete',{id:p.id,revision:p.revision});panelSequence++;el('profile-editor').replaceChildren();await load();message('Profil gelöscht. Modelldateien und Komponenten bleiben erhalten.');}catch(error){message(error.message);b.disabled=false;}});
root.querySelectorAll('[data-components]').forEach(b=>b.onclick=()=>components(rows.find(p=>p.id===b.dataset.components)));
root.querySelectorAll('[data-enhancers]').forEach(b=>b.onclick=()=>enhancers(rows.find(p=>p.id===b.dataset.enhancers)));
diff --git a/studio.js b/studio.js
index fb5fb5f..0f26ef8 100644
--- a/studio.js
+++ b/studio.js
@@ -1,14 +1,14 @@
/* Server-backed model management. Legacy browser drafts remain untouched. */
const Studio=(()=>{
let section='discover',category='';
- const labels={chat:'Sprachmodelle / Chat',image:'Bildgenerierung',audio:'Text-to-Speech (TTS)',stt:'Spracherkennung (STT)',music:'Musik',voice:'Stimme / Voice',video:'Video'};
+ const labels={chat:'Chat & Sprachmodelle',image:'Bildgenerierung',audio:'Sprachausgabe (TTS)',stt:'Spracherkennung (STT)',music:'Musikgenerierung',voice:'Stimmwerkzeuge',video:'Videogenerierung'};
const audioDescriptions={audio:'Geschriebenen Text vorlesen lassen. Die Suche zeigt Text-to-Speech-Modelle.',stt:'Gesprochene Sprache in Text umwandeln. Die Suche zeigt Spracherkennungsmodelle.',music:'Musik und Klänge aus Text erzeugen. Die Hub-Kategorie Text-to-Audio umfasst neben Musik auch Geräusche und andere Audioerzeugung.',voice:'Vorhandenes Audio bearbeiten: Stimmumwandlung, Audiotrennung und weitere Audio-to-Audio-Modelle. Eigenständige Studio-Oberflächen gehören unter Weitere Dienste.'};
function render(page,force=false,modelId=null){
if(page==='video'){VideoUI.runtime();return;}
if(!force&&document.querySelector('#studio')?.dataset.page===page)return;
if(category!==page){category=page;section='discover';}
if(modelId)section='profiles';
- const body=page==='stt-runtime'?STTUI.html(true):page==='tts-runtime'?TTSUI.html(true):['docker-runtime','services'].includes(page)?DockerUI.html(page==='services'):page==='runtimes'?runtimeOverview():page==='image-runtime'?imageRuntime():page==='runtime'?RuntimeUI.html():`
ATHENA / MODELLVERWALTUNG
${labels[page]}
${audioDescriptions[page]||'Modelle entdecken, herunterladen und mit gespeicherten Profilen konfigurieren.'}
Entdecken und Downloads sind verfügbar. Für diese Audio-Bereiche ist noch keine ausführbare Laufzeit in Deck angebunden. Gespeicherte Profile sind vorbereitend.
Entdecken und Downloads sind verfügbar. Für diese Audio-Bereiche ist noch keine ausführbare Laufzeit in Deck angebunden. Gespeicherte Profile sind vorbereitend.
Laufzeiten werden einmal eingerichtet und für kompatible Modelle wiederverwendet. Entdecken, Bibliothek und Profile zeigen den passenden Einrichtungsweg; unbekannte Modelle werden als noch nicht unterstützt gekennzeichnet. Textencoder und VAE werden separat in der Modellbibliothek verwaltet und einem Profil zugeordnet.
Spracherkennung
Qwen3-ASR mit llama.cpp und Audio-Projektor auf der CPU.
`;}
+ function runtimeOverview(){
+ const rows=[['llama.cpp','Chat & Sprachmodelle','CPU / CUDA · Versionen herunterladen, bauen und verwalten.','runtime'],['Bildlaufzeit','Bildgenerierung','Vorhandene Laufzeiten für kompatible Modelle wiederverwenden.','image-runtime'],['Sprachausgabe','TTS','Qwen3-TTS mit CUDA und eingebauten Stimmen.','tts-runtime'],['Spracherkennung','STT','Qwen3-ASR mit llama.cpp und Audio-Projektor.','stt-runtime'],['audio.cpp','Musik & Audio','Gemeinsame Audio-Laufzeit und modellabhängige Worker.','audio-cpp-runtime'],['LTX Original','Video','Originales LTX-Backend mit nativer API für LTX DeskWEB.','ltx-original-runtime'],['Docker','Weitere Dienste','Optionale Container-Umgebung für zusätzliche Oberflächen.','docker-runtime']];
+ return `
EINSTELLUNGEN
Laufzeiten
Einmal einrichten, für passende Modelle wiederverwenden. Öffne eine Laufzeit, um ihren Installationsstatus, Versionen und Optionen zu sehen. Zusatzdateien verwaltest du beim Profil unter Einrichtung & Komponenten.
Eigene Bildlaufzeit für Qwen-Image-2.1 GGUF und das unterstützte FLUX.2-Klein-9B-Modell. Die Umgebung kann über den Deck-Installer mitgeliefert oder hier separat installiert werden. Modelle laden erst bei einem Testauftrag.
Textencoder läuft auf der RTX 3060, Diffusionsmodell und VAE auf der RTX 5080. Bei großen FLUX-Gewichten wird zusätzlich System-RAM genutzt. Beide GPUs müssen frei sein. Pro Test wird ein eigener Prozess gestartet und anschließend beendet.
${e(r.label)} · ${r.available.length?'Bereits heruntergeladen':r.candidates.length?'Fehlt':'In dieser Quellversion nicht gefunden'}
${!r.available.length?r.candidates.map((c,j)=>``).join(''):''}`).join('')}`;root.querySelector('[data-close-components]').onclick=()=>{root.dataset.busy='0';poll();};root.querySelectorAll('[data-download-component]').forEach(d=>d.onclick=async()=>{const [i,j]=d.dataset.downloadComponent.split(':');const f=data.requirements[i].candidates[j];d.disabled=true;try{await api('catalog/download',{repo:f.repo,filename:f.name,revision:f.revision,kind:'video'});root.querySelector('.video-message').textContent='Download eingeplant. Fortschritt unter Downloads. Nach Abschluss werden die Komponenten automatisch erkannt.';}catch(x){root.querySelector('.video-message').textContent=x.message;d.disabled=false;}});}catch(x){root.dataset.busy='0';root.querySelector('.video-message').textContent=x.message;}});
- root.querySelectorAll('[data-select]').forEach(b=>b.onclick=async()=>{root.dataset.busy='1';try{await api('video/service',{id:b.dataset.select});root.querySelector('.video-message').textContent='Videomodell ausgewählt. Start über die Übersicht.';}catch(x){root.querySelector('.video-message').textContent=x.message;}finally{root.dataset.busy='0';}});
+ root.querySelectorAll('[data-select]').forEach(b=>b.onclick=async()=>{root.dataset.busy='1';try{await api('video/service',{id:b.dataset.select});root.querySelector('.video-message').textContent='Videomodell ausgewählt. Start über die Steuerung.';}catch(x){root.querySelector('.video-message').textContent=x.message;}finally{root.dataset.busy='0';}});
}}catch(x){root.textContent=x.message;}if(root.isConnected)setTimeout(poll,5000);}poll();
}
function runtime(){
const view=document.querySelector('#view');if(view.querySelector('#video-service-page'))return;
- view.innerHTML='
Video
LTX Original mit LTX DeskWEB oder die vorhandene ComfyUI-Laufzeit auswählen. Deck verwaltet Modelle, Komponenten und den GPU-Modus; Generierungsparameter gehören in die jeweilige Video-Oberfläche.
';
+ view.innerHTML='
Videogenerierung
LTX Original mit LTX DeskWEB oder die vorhandene ComfyUI-Laufzeit auswählen. Deck verwaltet Modelle, Komponenten und den GPU-Modus; Generierungsparameter gehören in die jeweilige Video-Oberfläche.
';
function show(tab){const root=view.querySelector('#video-content');if(tab==='runtime'){root.innerHTML='';services(root.firstChild);}else{root.innerHTML=CatalogUI.html(tab==='library',tab==='downloads');CatalogUI.bind('video',tab==='library',tab==='downloads');}}
view.querySelectorAll('[data-video-tab]').forEach(b=>b.onclick=()=>show(b.dataset.videoTab));show('runtime');
}