window.ImageTestUI=(()=>{ const e=v=>String(v??'').replace(/[&<>"']/g,c=>({'&':'&','<':'<','>':'>','"':'"',"'":'''}[c])); async function api(path,data){const r=await fetch('/api/v1/'+path,data?{method:'POST',headers:{'Content-Type':'application/json','X-Athena-Deck':'1'},body:JSON.stringify(data)}:{});const v=await r.json();if(!r.ok)throw Error(v.error||'Anfrage fehlgeschlagen');return v;} function html(readonly=false){return `

${readonly?'Bildlaufzeit':'Bildmodell testen'}

Ein Bild mit deinem gespeicherten Profil erzeugen. Der eigene Worker beendet sich nach dem Auftrag.

${readonly?'':`

Auflösung, Schritte, Guidance und Seed stammen aus dem Profil. Maximal 1024 × 1024 Pixel. Beide GPUs müssen frei sein; Deck stoppt keine produktiven Modelle. Der erste Start kann einige Minuten dauern.

`}

Textencoder: RTX 3060 · Diffusionsmodell und VAE: RTX 5080. CPU/RAM werden weiterhin zum Laden und Auslagern benötigt. GPU-Last entsteht nicht während aller Verarbeitungsschritte. Aktuelle Hardware-Messwerte →

`;} function bind(readonly=false){ const root=document.querySelector('#image-test'),el=id=>root.querySelector('#'+id);let profiles=[],status=null,lastJob='',timer,submitting=false,previewId=null; const message=t=>{if(root.isConnected)el('image-test-message').textContent=t;}; function selection(){if(readonly)return;const p=profiles.find(p=>p.id===el('image-test-profile').value),max=p?.capabilities?.reference_images||0;el('image-profile-info').textContent=p?`${p.parameters.width} × ${p.parameters.height} · ${p.parameters.steps} Schritte · Guidance ${p.parameters.guidance} · Seed ${p.parameters.seed}${p.blockers.length?' · '+p.blockers.join(' '):''}`:'';el('image-reference-label').hidden=!max;el('image-reference-files').disabled=!max;el('image-reference-info').textContent=max?`Dieses Profil erlaubt bis zu ${max} Referenzbilder. Reihenfolge: wie ausgewählt; PNG/JPEG/WebP, je höchstens 10 MiB.`:'Dieses Profil unterstützt keine Referenzbilder.';el('image-generate').disabled=submitting||!p?.runnable||!status?.runtime_installed||status?.job?.state==='running';el('image-preview-enhancer').disabled=submitting||!p?.prompt_enhancer?.[el('image-reference-files').files.length?'i2i':'t2i'];} async function preview(){ const button=el('image-preview-enhancer'),area=el('image-enhancer-preview');button.disabled=true;area.textContent='Prompt-Aufwerter startet; Bildmodell wartet.'; try{ const form=new FormData();form.set('profile_id',el('image-test-profile').value);form.set('prompt',el('image-test-form').elements.prompt.value); for(const file of el('image-reference-files').files)form.append('image[]',file); const response=await fetch('/api/v1/prompt-enhancers/preview',{method:'POST',headers:{'X-Athena-Deck':'1'},body:form});const job=await response.json(); if(!response.ok)throw Error(job.error||'Vorschau konnte nicht starten.');previewId=job.id; async function poll(){ if(!root.isConnected||previewId!==job.id)return; const state=(await api('prompt-enhancers')).preview;if(!state||state.id!==job.id)return; if(state.state==='running'){area.textContent=state.phase;setTimeout(poll,2000);return;} if(state.state!=='complete')throw Error(state.phase||'Aufbereitung fehlgeschlagen.'); area.innerHTML=`

Vorschlag · Seitenverhältnis: ${e(state.result.wh_ratio||'kein Vorschlag')}

`; area.querySelector('textarea').value=state.result.prompt; area.querySelector('#image-use-enhanced').onclick=()=>{el('image-test-form').elements.prompt.value=area.querySelector('textarea').value;el('image-skip-enhancer').value='1';area.textContent='Überarbeiteter Prompt übernommen. Bildgenerierung bereitet ihn nicht erneut auf.';}; area.querySelector('#image-use-original').onclick=()=>{el('image-skip-enhancer').value='1';area.textContent='Originalprompt bleibt. Für diesen Bildtest wird die Aufbereitung übersprungen.';}; } poll().catch(error=>{area.textContent=error.message;}); }catch(error){area.textContent=error.message;}finally{button.disabled=false;} } async function refresh(){try{status=await api('image-tests');if(!root.isConnected)return;const j=status.job,signature=JSON.stringify(j);if(signature!==lastJob){lastJob=signature;el('image-test-state').innerHTML=j?`${e({running:'LÄUFT',complete:'FERTIG',failed:'FEHLGESCHLAGEN',cancelled:'ABGEBROCHEN',interrupted:'UNTERBROCHEN'}[j.state]||j.state)}

${e(j.profile_name)}

${e(j.phase)}

${e(j.gpu)}${j.encoder_gpu?' · Textencoder: '+e(j.encoder_gpu):''} · Seed ${e(j.seed)}

${j.state==='running'?'':''}`:`

${status.runtime_installed?'Bildlaufzeit ist installiert':'Bildlaufzeit noch nicht installiert'}

Noch kein Bildtest gestartet.

`; el('image-test-result').innerHTML=j?.state==='complete'?`
Ergebnis des Bildtests
PNG herunterladen
`:''; el('image-cancel')?.addEventListener('click',async event=>{event.target.disabled=true;try{await api('image-tests/cancel',{});message('Abbruch angefordert; der eigene Bildworker wird beendet.');}catch(error){message(error.message);}}); }selection();}catch(error){message(error.message);}finally{if(root.isConnected)timer=setTimeout(refresh,2000);}} if(!readonly){api('profiles').then(v=>{if(!root.isConnected)return;profiles=v.profiles.filter(p=>p.kind==='image');el('image-test-profile').innerHTML=profiles.map(p=>``).join('')||'';selection();}).catch(error=>message(error.message));const invalidate=()=>{previewId=null;el('image-skip-enhancer').value='0';el('image-enhancer-preview').replaceChildren();};el('image-test-profile').onchange=()=>{el('image-reference-files').value='';invalidate();selection();}; el('image-reference-files').onchange=()=>{invalidate();selection();}; el('image-test-form').elements.prompt.oninput=invalidate; el('image-preview-enhancer').onclick=preview; el('image-test-form').onsubmit=async event=>{event.preventDefault();submitting=true;selection();try{const form=new FormData(event.target),p=profiles.find(p=>p.id===el('image-test-profile').value),files=[...el('image-reference-files').files],max=p?.capabilities?.reference_images||0;if(files.length>max)throw Error(`Dieses Profil erlaubt höchstens ${max} Referenzbilder.`);if(files.some(f=>f.size>10*1024*1024))throw Error('Jedes Referenzbild darf höchstens 10 MiB groß sein.');form.delete('image[]');for(const file of files)form.append('image[]',file);const r=await fetch('/api/v1/image-tests/start',{method:'POST',headers:{'X-Athena-Deck':'1'},body:form});const result=await r.json();if(!r.ok)throw Error(result.error||'Bildtest fehlgeschlagen.');message('Bildtest gestartet.');}catch(error){message(error.message);}finally{submitting=false;selection();}}; } refresh(); } function bindInstaller(){ const root=document.querySelector('#image-runtime-install');let pending=false; async function refresh(){try{const s=await api('image-runtime');if(!root.isConnected)return;const running=s.job?.state==='running';root.innerHTML=`

${s.installed?'Installiert · '+e(s.origin):'Noch nicht installiert'}

ComfyUI ${e(s.comfy_revision.slice(0,12))} · GGUF ${e(s.gguf_revision.slice(0,12))}

${e(s.job?.phase||'Installation richtet eine eigene Python-Umgebung mit ComfyUI, GGUF-Unterstützung und CUDA-PyTorch ein. Mindestens 25 GiB freier Speicher und Internetzugang erforderlich.')}

Systemvoraussetzungen: Python mit venv, Git und kompatibler NVIDIA-Treiber. Die Installation ändert keine Host-Pakete oder anderen Dienste.

`;root.querySelector('button').onclick=async()=>{pending=true;root.querySelector('button').disabled=true;try{await api('image-runtime/'+(running?'cancel':'install'),{});}catch(error){alert(error.message);}finally{pending=false;}};}catch(error){if(root.isConnected)root.textContent=error.message;}finally{if(root.isConnected)setTimeout(refresh,2000);}} refresh(); } return {html,bind,bindInstaller}; })();