window.DockerUI=(()=>{ const esc=v=>String(v??'').replace(/[&<>"']/g,c=>({'&':'&','<':'<','>':'>','"':'"',"'":'''}[c])); const apps={ 'athena-ladypoly':{title:'LadyPoly YuE2',description:'Weboberfläche für Decks Musiklaufzeit.',port:8127,hint:'In der Steuerung Musik starten. Deck-Verbindung in LadyPoly einrichten.'}, 'athena-separator-web':{title:'Athena Separator Web',description:'Gesang oder Instrumente herauslösen; Verarbeitung durch Decks native Audio-Separator-Laufzeit.',port:8128,hint:'In der Steuerung Audio-Trennung starten. Modelle unter Audio-Trennung einrichten.'}, 'ltx-deskweb':{title:'LTX DeskWEB',description:'LTX-Webstudio für Videoerzeugung über Decks originale LTX-Laufzeit.',port:8118,hint:'Videoprofil freigeben und in der Steuerung Video starten.'}, 'athena-swarm-ui':{title:'SwarmUI',description:'API By URL · Oberfläche für Decks ComfyUI-Laufzeit.',port:8125,hint:'In der Steuerung Video mit ComfyUI starten.'} }; function appInfo(c){const a=apps[c.name];return a?`
${esc(a.description)}
${esc(a.title)} öffnen →${esc(a.hint)} SSH-Tunnel: Port ${a.port}.
`:'';} async function api(action='',data){const r=await fetch('/api/v1/docker'+action,data?{method:'POST',headers:{'Content-Type':'application/json','X-Athena-Deck':'1'},body:JSON.stringify(data)}:{});if(r.status===401){location.reload();throw Error('Bitte erneut anmelden.');}const value=await r.json();if(!r.ok)throw Error(value.error||'Docker-Anfrage fehlgeschlagen');return value;} function html(services=false){return `${services?'Zusätzliche Oberflächen werden getrennt von Modellen und Laufzeiten verwaltet. Hier erscheinen ausschließlich ausdrücklich für Deck markierte Anwendungscontainer.':'Optionale Umgebung für zusätzliche Studios. Native Modelllaufzeiten bleiben unabhängig davon.'}
`;} function bind(services=false){const panel=document.querySelector('#docker-panel'),message=document.querySelector('#docker-message');let signature='',pending=false,timer; async function refresh(){clearTimeout(timer);try{if(pending)return;const s=await api();if(!panel.isConnected)return;const next=JSON.stringify(s);if(signature!==next){signature=next;const running=s.job?.state==='running'; if(services){panel.innerHTML=`Beide Container-Labels müssen gesetzt sein:
io.athena-deck.managed=true\nio.athena-deck.role=applicationKeine automatische Übernahme vorhandener Container. Labels werden beim Erstellen in Docker Compose gesetzt. Starten und Stoppen betrifft nur markierte Container. Löschen entfernt den Container einschließlich seiner beschreibbaren Schicht; Images und Volumes bleiben erhalten.
Docker-Verbindung prüfen →'+esc(s.message)+'
${esc(c.image)}
${esc(c.state)} · ${esc(c.status)}
${appInfo(c)}Docker ist erreichbar. Kein Container trägt beide erforderlichen Labels. Bestehende Router-, WireGuard- und andere Container bleiben ausgeblendet.
${s.reachable?'Daemon erreichbar · Verbindung über begrenzten Systemhelfer':s.helper_available?'Systemhelfer erreichbar · Docker-Daemon nicht erreichbar':'Systemhelfer nicht verbunden'}
${esc(s.message)}
${s.job?`${esc(s.job.state)} · ${esc(s.job.phase)}
`:''}${!s.installed&&s.install_supported&&!running?'':``}Keine automatische Aktualisierung vorhandener Docker-Installationen. NVIDIA Container Toolkit und Treiber sind separate Voraussetzungen für GPU-Container. Die Paketinstallation wird nicht mitten im Vorgang abgebrochen.
Weitere Dienste öffnen →