From 992a642b402c496b4618eceafe40e1255145fe87 Mon Sep 17 00:00:00 2001 From: techjarves Date: Sun, 7 Jun 2026 10:10:53 +0530 Subject: [PATCH] add ModelManager component and infrastructure to support local model management, downloading, and server integration --- README.md | 4 +- app/dist/assets/event-DtK1umGE.js | 1 + app/dist/assets/index-CL30r104.js | 121 ++++++++++++++++++ app/dist/index.html | 2 +- app/frontend/src/components/Generator.jsx | 6 +- .../src/components/ImageConstraints.jsx | 20 --- app/frontend/src/components/ModelManager.jsx | 8 +- app/frontend/src/services/api.js | 32 ++++- scripts/serve.cjs | 46 +++++-- start.bat | 23 ++-- 10 files changed, 207 insertions(+), 56 deletions(-) create mode 100644 app/dist/assets/event-DtK1umGE.js create mode 100644 app/dist/assets/index-CL30r104.js diff --git a/README.md b/README.md index f59a128..f02ba37 100644 --- a/README.md +++ b/README.md @@ -86,9 +86,9 @@ Typical generation times for an image with **20 steps** (e.g. 512x512 resolution ## 🛠️ Troubleshooting * **Reset Environment:** If a build fails or you want to clear dependencies, run `scripts/reset.ps1`. (This preserves your models and generated images). -* **Port Conflicts:** The application binds to ports `1420` (Frontend) and `8080` (Backend API). Ensure these are free. +* **Port Conflicts:** The frontend uses `1420` by default. The backend tries `8080` first, then automatically falls back to a free port if `8080` is already busy. --- ## 📝 License -This project is licensed under the MIT License - see the [LICENSE](LICENSE) file. Bundles [stable-diffusion.cpp](https://github.com/leejet/stable-diffusion.cpp) (MIT License). Model weights are subject to their respective creators' licenses. \ No newline at end of file +This project is licensed under the MIT License - see the [LICENSE](LICENSE) file. Bundles [stable-diffusion.cpp](https://github.com/leejet/stable-diffusion.cpp) (MIT License). Model weights are subject to their respective creators' licenses. diff --git a/app/dist/assets/event-DtK1umGE.js b/app/dist/assets/event-DtK1umGE.js new file mode 100644 index 0000000..5400c43 --- /dev/null +++ b/app/dist/assets/event-DtK1umGE.js @@ -0,0 +1 @@ +import{i as D,t as i}from"./index-CL30r104.js";var _;(function(r){r.WINDOW_RESIZED="tauri://resize",r.WINDOW_MOVED="tauri://move",r.WINDOW_CLOSE_REQUESTED="tauri://close-requested",r.WINDOW_DESTROYED="tauri://destroyed",r.WINDOW_FOCUS="tauri://focus",r.WINDOW_BLUR="tauri://blur",r.WINDOW_SCALE_FACTOR_CHANGED="tauri://scale-change",r.WINDOW_THEME_CHANGED="tauri://theme-changed",r.WINDOW_CREATED="tauri://window-created",r.WINDOW_SUSPENDED="tauri://suspended",r.WINDOW_RESUMED="tauri://resumed",r.WEBVIEW_CREATED="tauri://webview-created",r.DRAG_ENTER="tauri://drag-enter",r.DRAG_OVER="tauri://drag-over",r.DRAG_DROP="tauri://drag-drop",r.DRAG_LEAVE="tauri://drag-leave"})(_||(_={}));async function l(r,a){window.__TAURI_EVENT_PLUGIN_INTERNALS__.unregisterListener(r,a),await D("plugin:event|unlisten",{event:r,eventId:a})}async function n(r,a,e){var t;const W=typeof e?.target=="string"?{kind:"AnyLabel",label:e.target}:(t=e?.target)!==null&&t!==void 0?t:{kind:"Any"};return D("plugin:event|listen",{event:r,target:W,handler:i(a)}).then(d=>async()=>l(r,d))}export{_ as TauriEvent,n as listen}; diff --git a/app/dist/assets/index-CL30r104.js b/app/dist/assets/index-CL30r104.js new file mode 100644 index 0000000..037e9dd --- /dev/null +++ b/app/dist/assets/index-CL30r104.js @@ -0,0 +1,121 @@ +(function(){const b=document.createElement("link").relList;if(b&&b.supports&&b.supports("modulepreload"))return;for(const _ of document.querySelectorAll('link[rel="modulepreload"]'))r(_);new MutationObserver(_=>{for(const N of _)if(N.type==="childList")for(const G of N.addedNodes)G.tagName==="LINK"&&G.rel==="modulepreload"&&r(G)}).observe(document,{childList:!0,subtree:!0});function E(_){const N={};return _.integrity&&(N.integrity=_.integrity),_.referrerPolicy&&(N.referrerPolicy=_.referrerPolicy),_.crossOrigin==="use-credentials"?N.credentials="include":_.crossOrigin==="anonymous"?N.credentials="omit":N.credentials="same-origin",N}function r(_){if(_.ep)return;_.ep=!0;const N=E(_);fetch(_.href,N)}})();function sm(f){return f&&f.__esModule&&Object.prototype.hasOwnProperty.call(f,"default")?f.default:f}var Us={exports:{}},ei={};var Zd;function E0(){if(Zd)return ei;Zd=1;var f=Symbol.for("react.transitional.element"),b=Symbol.for("react.fragment");function E(r,_,N){var G=null;if(N!==void 0&&(G=""+N),_.key!==void 0&&(G=""+_.key),"key"in _){N={};for(var H in _)H!=="key"&&(N[H]=_[H])}else N=_;return _=N.ref,{$$typeof:f,type:r,key:G,ref:_!==void 0?_:null,props:N}}return ei.Fragment=b,ei.jsx=E,ei.jsxs=E,ei}var Vd;function N0(){return Vd||(Vd=1,Us.exports=E0()),Us.exports}var c=N0(),ws={exports:{}},ie={};var Kd;function A0(){if(Kd)return ie;Kd=1;var f=Symbol.for("react.transitional.element"),b=Symbol.for("react.portal"),E=Symbol.for("react.fragment"),r=Symbol.for("react.strict_mode"),_=Symbol.for("react.profiler"),N=Symbol.for("react.consumer"),G=Symbol.for("react.context"),H=Symbol.for("react.forward_ref"),B=Symbol.for("react.suspense"),y=Symbol.for("react.memo"),A=Symbol.for("react.lazy"),O=Symbol.for("react.activity"),L=Symbol.iterator;function Z(d){return d===null||typeof d!="object"?null:(d=L&&d[L]||d["@@iterator"],typeof d=="function"?d:null)}var V={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},W=Object.assign,ue={};function F(d,j,w){this.props=d,this.context=j,this.refs=ue,this.updater=w||V}F.prototype.isReactComponent={},F.prototype.setState=function(d,j){if(typeof d!="object"&&typeof d!="function"&&d!=null)throw Error("takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,d,j,"setState")},F.prototype.forceUpdate=function(d){this.updater.enqueueForceUpdate(this,d,"forceUpdate")};function Ce(){}Ce.prototype=F.prototype;function Te(d,j,w){this.props=d,this.context=j,this.refs=ue,this.updater=w||V}var Qe=Te.prototype=new Ce;Qe.constructor=Te,W(Qe,F.prototype),Qe.isPureReactComponent=!0;var Le=Array.isArray;function Me(){}var te={H:null,A:null,T:null,S:null},Se=Object.prototype.hasOwnProperty;function ft(d,j,w){var q=w.ref;return{$$typeof:f,type:d,key:j,ref:q!==void 0?q:null,props:w}}function _t(d,j){return ft(d.type,j,d.props)}function ye(d){return typeof d=="object"&&d!==null&&d.$$typeof===f}function Ve(d){var j={"=":"=0",":":"=2"};return"$"+d.replace(/[=:]/g,function(w){return j[w]})}var nt=/\/+/g;function Ke(d,j){return typeof d=="object"&&d!==null&&d.key!=null?Ve(""+d.key):j.toString(36)}function Ye(d){switch(d.status){case"fulfilled":return d.value;case"rejected":throw d.reason;default:switch(typeof d.status=="string"?d.then(Me,Me):(d.status="pending",d.then(function(j){d.status==="pending"&&(d.status="fulfilled",d.value=j)},function(j){d.status==="pending"&&(d.status="rejected",d.reason=j)})),d.status){case"fulfilled":return d.value;case"rejected":throw d.reason}}throw d}function x(d,j,w,q,J){var ae=typeof d;(ae==="undefined"||ae==="boolean")&&(d=null);var de=!1;if(d===null)de=!0;else switch(ae){case"bigint":case"string":case"number":de=!0;break;case"object":switch(d.$$typeof){case f:case b:de=!0;break;case A:return de=d._init,x(de(d._payload),j,w,q,J)}}if(de)return J=J(d),de=q===""?"."+Ke(d,0):q,Le(J)?(w="",de!=null&&(w=de.replace(nt,"$&/")+"/"),x(J,j,w,"",function(it){return it})):J!=null&&(ye(J)&&(J=_t(J,w+(J.key==null||d&&d.key===J.key?"":(""+J.key).replace(nt,"$&/")+"/")+de)),j.push(J)),1;de=0;var ke=q===""?".":q+":";if(Le(d))for(var Ee=0;Ee>>1,re=x[ge];if(0<_(re,C))x[ge]=C,x[K]=re,K=ge;else break e}}function E(x){return x.length===0?null:x[0]}function r(x){if(x.length===0)return null;var C=x[0],K=x.pop();if(K!==C){x[0]=K;e:for(var ge=0,re=x.length,d=re>>>1;ge_(w,K))q_(J,w)?(x[ge]=J,x[q]=K,ge=q):(x[ge]=w,x[j]=K,ge=j);else if(q_(J,K))x[ge]=J,x[q]=K,ge=q;else break e}}return C}function _(x,C){var K=x.sortIndex-C.sortIndex;return K!==0?K:x.id-C.id}if(f.unstable_now=void 0,typeof performance=="object"&&typeof performance.now=="function"){var N=performance;f.unstable_now=function(){return N.now()}}else{var G=Date,H=G.now();f.unstable_now=function(){return G.now()-H}}var B=[],y=[],A=1,O=null,L=3,Z=!1,V=!1,W=!1,ue=!1,F=typeof setTimeout=="function"?setTimeout:null,Ce=typeof clearTimeout=="function"?clearTimeout:null,Te=typeof setImmediate<"u"?setImmediate:null;function Qe(x){for(var C=E(y);C!==null;){if(C.callback===null)r(y);else if(C.startTime<=x)r(y),C.sortIndex=C.expirationTime,b(B,C);else break;C=E(y)}}function Le(x){if(W=!1,Qe(x),!V)if(E(B)!==null)V=!0,Me||(Me=!0,Ve());else{var C=E(y);C!==null&&Ye(Le,C.startTime-x)}}var Me=!1,te=-1,Se=5,ft=-1;function _t(){return ue?!0:!(f.unstable_now()-ftx&&_t());){var ge=O.callback;if(typeof ge=="function"){O.callback=null,L=O.priorityLevel;var re=ge(O.expirationTime<=x);if(x=f.unstable_now(),typeof re=="function"){O.callback=re,Qe(x),C=!0;break t}O===E(B)&&r(B),Qe(x)}else r(B);O=E(B)}if(O!==null)C=!0;else{var d=E(y);d!==null&&Ye(Le,d.startTime-x),C=!1}}break e}finally{O=null,L=K,Z=!1}C=void 0}}finally{C?Ve():Me=!1}}}var Ve;if(typeof Te=="function")Ve=function(){Te(ye)};else if(typeof MessageChannel<"u"){var nt=new MessageChannel,Ke=nt.port2;nt.port1.onmessage=ye,Ve=function(){Ke.postMessage(null)}}else Ve=function(){F(ye,0)};function Ye(x,C){te=F(function(){x(f.unstable_now())},C)}f.unstable_IdlePriority=5,f.unstable_ImmediatePriority=1,f.unstable_LowPriority=4,f.unstable_NormalPriority=3,f.unstable_Profiling=null,f.unstable_UserBlockingPriority=2,f.unstable_cancelCallback=function(x){x.callback=null},f.unstable_forceFrameRate=function(x){0>x||125ge?(x.sortIndex=K,b(y,x),E(B)===null&&x===E(y)&&(W?(Ce(te),te=-1):W=!0,Ye(Le,K-ge))):(x.sortIndex=re,b(B,x),V||Z||(V=!0,Me||(Me=!0,Ve()))),x},f.unstable_shouldYield=_t,f.unstable_wrapCallback=function(x){var C=L;return function(){var K=L;L=C;try{return x.apply(this,arguments)}finally{L=K}}}})(Hs)),Hs}var Wd;function O0(){return Wd||(Wd=1,Rs.exports=C0()),Rs.exports}var Gs={exports:{}},xt={};var Fd;function U0(){if(Fd)return xt;Fd=1;var f=ks();function b(B){var y="https://react.dev/errors/"+B;if(1"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(f)}catch(b){console.error(b)}}return f(),Gs.exports=U0(),Gs.exports}var Pd;function B0(){if(Pd)return ti;Pd=1;var f=O0(),b=ks(),E=w0();function r(e){var t="https://react.dev/errors/"+e;if(1re||(e.current=ge[re],ge[re]=null,re--)}function w(e,t){re++,ge[re]=e.current,e.current=t}var q=d(null),J=d(null),ae=d(null),de=d(null);function ke(e,t){switch(w(ae,t),w(J,e),w(q,null),t.nodeType){case 9:case 11:e=(e=t.documentElement)&&(e=e.namespaceURI)?hd(e):0;break;default:if(e=t.tagName,t=t.namespaceURI)t=hd(t),e=yd(t,e);else switch(e){case"svg":e=1;break;case"math":e=2;break;default:e=0}}j(q),w(q,e)}function Ee(){j(q),j(J),j(ae)}function it(e){e.memoizedState!==null&&w(de,e);var t=q.current,l=yd(t,e.type);t!==l&&(w(J,e),w(q,l))}function ot(e){J.current===e&&(j(q),j(J)),de.current===e&&(j(de),Wn._currentValue=K)}var ht,cl;function Ut(e){if(ht===void 0)try{throw Error()}catch(l){var t=l.stack.trim().match(/\n( *(at )?)/);ht=t&&t[1]||"",cl=-1)":-1n||o[a]!==p[n]){var z=` +`+o[a].replace(" at new "," at ");return e.displayName&&z.includes("")&&(z=z.replace("",e.displayName)),z}while(1<=a&&0<=n);break}}}finally{k=!1,Error.prepareStackTrace=l}return(l=e?e.displayName||e.name:"")?Ut(l):""}function D(e,t){switch(e.tag){case 26:case 27:case 5:return Ut(e.type);case 16:return Ut("Lazy");case 13:return e.child!==t&&t!==null?Ut("Suspense Fallback"):Ut("Suspense");case 19:return Ut("SuspenseList");case 0:case 15:return se(e.type,!1);case 11:return se(e.type.render,!1);case 1:return se(e.type,!0);case 31:return Ut("Activity");default:return""}}function R(e){try{var t="",l=null;do t+=D(e,l),l=e,e=e.return;while(e);return t}catch(a){return` +Error generating stack: `+a.message+` +`+a.stack}}var I=Object.prototype.hasOwnProperty,P=f.unstable_scheduleCallback,Tt=f.unstable_cancelCallback,It=f.unstable_shouldYield,sl=f.unstable_requestPaint,ut=f.unstable_now,Y=f.unstable_getCurrentPriorityLevel,le=f.unstable_ImmediatePriority,He=f.unstable_UserBlockingPriority,Pe=f.unstable_NormalPriority,jt=f.unstable_LowPriority,ll=f.unstable_IdlePriority,xa=f.log,_a=f.unstable_setDisableYieldValue,We=null,ne=null;function fe(e){if(typeof xa=="function"&&_a(e),ne&&typeof ne.setStrictMode=="function")try{ne.setStrictMode(We,e)}catch{}}var pe=Math.clz32?Math.clz32:Re,Ne=Math.log,ct=Math.LN2;function Re(e){return e>>>=0,e===0?32:31-(Ne(e)/ct|0)|0}var rt=256,St=262144,wt=4194304;function fl(e){var t=e&42;if(t!==0)return t;switch(e&-e){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:return 64;case 128:return 128;case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:return e&261888;case 262144:case 524288:case 1048576:case 2097152:return e&3932160;case 4194304:case 8388608:case 16777216:case 33554432:return e&62914560;case 67108864:return 67108864;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 0;default:return e}}function ii(e,t,l){var a=e.pendingLanes;if(a===0)return 0;var n=0,i=e.suspendedLanes,u=e.pingedLanes;e=e.warmLanes;var s=a&134217727;return s!==0?(a=s&~i,a!==0?n=fl(a):(u&=s,u!==0?n=fl(u):l||(l=s&~e,l!==0&&(n=fl(l))))):(s=a&~i,s!==0?n=fl(s):u!==0?n=fl(u):l||(l=a&~e,l!==0&&(n=fl(l)))),n===0?0:t!==0&&t!==n&&(t&i)===0&&(i=n&-n,l=t&-t,i>=l||i===32&&(l&4194048)!==0)?t:n}function fn(e,t){return(e.pendingLanes&~(e.suspendedLanes&~e.pingedLanes)&t)===0}function hm(e,t){switch(e){case 1:case 2:case 4:case 8:case 64:return t+250;case 16:case 32:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return t+5e3;case 4194304:case 8388608:case 16777216:case 33554432:return-1;case 67108864:case 134217728:case 268435456:case 536870912:case 1073741824:return-1;default:return-1}}function Ks(){var e=wt;return wt<<=1,(wt&62914560)===0&&(wt=4194304),e}function xu(e){for(var t=[],l=0;31>l;l++)t.push(e);return t}function on(e,t){e.pendingLanes|=t,t!==268435456&&(e.suspendedLanes=0,e.pingedLanes=0,e.warmLanes=0)}function ym(e,t,l,a,n,i){var u=e.pendingLanes;e.pendingLanes=l,e.suspendedLanes=0,e.pingedLanes=0,e.warmLanes=0,e.expiredLanes&=l,e.entangledLanes&=l,e.errorRecoveryDisabledLanes&=l,e.shellSuspendCounter=0;var s=e.entanglements,o=e.expirationTimes,p=e.hiddenUpdates;for(l=u&~l;0"u")return null;try{return e.activeElement||e.body}catch{return e.body}}var xm=/[\n"\\]/g;function Qt(e){return e.replace(xm,function(t){return"\\"+t.charCodeAt(0).toString(16)+" "})}function Eu(e,t,l,a,n,i,u,s){e.name="",u!=null&&typeof u!="function"&&typeof u!="symbol"&&typeof u!="boolean"?e.type=u:e.removeAttribute("type"),t!=null?u==="number"?(t===0&&e.value===""||e.value!=t)&&(e.value=""+Xt(t)):e.value!==""+Xt(t)&&(e.value=""+Xt(t)):u!=="submit"&&u!=="reset"||e.removeAttribute("value"),t!=null?Nu(e,u,Xt(t)):l!=null?Nu(e,u,Xt(l)):a!=null&&e.removeAttribute("value"),n==null&&i!=null&&(e.defaultChecked=!!i),n!=null&&(e.checked=n&&typeof n!="function"&&typeof n!="symbol"),s!=null&&typeof s!="function"&&typeof s!="symbol"&&typeof s!="boolean"?e.name=""+Xt(s):e.removeAttribute("name")}function cf(e,t,l,a,n,i,u,s){if(i!=null&&typeof i!="function"&&typeof i!="symbol"&&typeof i!="boolean"&&(e.type=i),t!=null||l!=null){if(!(i!=="submit"&&i!=="reset"||t!=null)){Mu(e);return}l=l!=null?""+Xt(l):"",t=t!=null?""+Xt(t):l,s||t===e.value||(e.value=t),e.defaultValue=t}a=a??n,a=typeof a!="function"&&typeof a!="symbol"&&!!a,e.checked=s?e.checked:!!a,e.defaultChecked=!!a,u!=null&&typeof u!="function"&&typeof u!="symbol"&&typeof u!="boolean"&&(e.name=u),Mu(e)}function Nu(e,t,l){t==="number"&&si(e.ownerDocument)===e||e.defaultValue===""+l||(e.defaultValue=""+l)}function Na(e,t,l,a){if(e=e.options,t){t={};for(var n=0;n"u"||typeof window.document>"u"||typeof window.document.createElement>"u"),Uu=!1;if(dl)try{var hn={};Object.defineProperty(hn,"passive",{get:function(){Uu=!0}}),window.addEventListener("test",hn,hn),window.removeEventListener("test",hn,hn)}catch{Uu=!1}var Dl=null,wu=null,oi=null;function hf(){if(oi)return oi;var e,t=wu,l=t.length,a,n="value"in Dl?Dl.value:Dl.textContent,i=n.length;for(e=0;e=pn),Sf=" ",xf=!1;function _f(e,t){switch(e){case"keyup":return $m.indexOf(t.keyCode)!==-1;case"keydown":return t.keyCode!==229;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function jf(e){return e=e.detail,typeof e=="object"&&"data"in e?e.data:null}var Oa=!1;function Fm(e,t){switch(e){case"compositionend":return jf(t);case"keypress":return t.which!==32?null:(xf=!0,Sf);case"textInput":return e=t.data,e===Sf&&xf?null:e;default:return null}}function Im(e,t){if(Oa)return e==="compositionend"||!qu&&_f(e,t)?(e=hf(),oi=wu=Dl=null,Oa=!1,e):null;switch(e){case"paste":return null;case"keypress":if(!(t.ctrlKey||t.altKey||t.metaKey)||t.ctrlKey&&t.altKey){if(t.char&&1=t)return{node:l,offset:t-e};e=a}e:{for(;l;){if(l.nextSibling){l=l.nextSibling;break e}l=l.parentNode}l=void 0}l=Cf(l)}}function Uf(e,t){return e&&t?e===t?!0:e&&e.nodeType===3?!1:t&&t.nodeType===3?Uf(e,t.parentNode):"contains"in e?e.contains(t):e.compareDocumentPosition?!!(e.compareDocumentPosition(t)&16):!1:!1}function wf(e){e=e!=null&&e.ownerDocument!=null&&e.ownerDocument.defaultView!=null?e.ownerDocument.defaultView:window;for(var t=si(e.document);t instanceof e.HTMLIFrameElement;){try{var l=typeof t.contentWindow.location.href=="string"}catch{l=!1}if(l)e=t.contentWindow;else break;t=si(e.document)}return t}function Xu(e){var t=e&&e.nodeName&&e.nodeName.toLowerCase();return t&&(t==="input"&&(e.type==="text"||e.type==="search"||e.type==="tel"||e.type==="url"||e.type==="password")||t==="textarea"||e.contentEditable==="true")}var uh=dl&&"documentMode"in document&&11>=document.documentMode,Ua=null,Qu=null,xn=null,ku=!1;function Bf(e,t,l){var a=l.window===l?l.document:l.nodeType===9?l:l.ownerDocument;ku||Ua==null||Ua!==si(a)||(a=Ua,"selectionStart"in a&&Xu(a)?a={start:a.selectionStart,end:a.selectionEnd}:(a=(a.ownerDocument&&a.ownerDocument.defaultView||window).getSelection(),a={anchorNode:a.anchorNode,anchorOffset:a.anchorOffset,focusNode:a.focusNode,focusOffset:a.focusOffset}),xn&&Sn(xn,a)||(xn=a,a=au(Qu,"onSelect"),0>=u,n-=u,al=1<<32-pe(t)+n|l<oe?(be=Q,Q=null):be=Q.sibling;var je=v(h,Q,g[oe],T);if(je===null){Q===null&&(Q=be);break}e&&Q&&je.alternate===null&&t(h,Q),m=i(je,m,oe),_e===null?$=je:_e.sibling=je,_e=je,Q=be}if(oe===g.length)return l(h,Q),xe&&hl(h,oe),$;if(Q===null){for(;oeoe?(be=Q,Q=null):be=Q.sibling;var Il=v(h,Q,je.value,T);if(Il===null){Q===null&&(Q=be);break}e&&Q&&Il.alternate===null&&t(h,Q),m=i(Il,m,oe),_e===null?$=Il:_e.sibling=Il,_e=Il,Q=be}if(je.done)return l(h,Q),xe&&hl(h,oe),$;if(Q===null){for(;!je.done;oe++,je=g.next())je=M(h,je.value,T),je!==null&&(m=i(je,m,oe),_e===null?$=je:_e.sibling=je,_e=je);return xe&&hl(h,oe),$}for(Q=a(Q);!je.done;oe++,je=g.next())je=S(Q,h,oe,je.value,T),je!==null&&(e&&je.alternate!==null&&Q.delete(je.key===null?oe:je.key),m=i(je,m,oe),_e===null?$=je:_e.sibling=je,_e=je);return e&&Q.forEach(function(M0){return t(h,M0)}),xe&&hl(h,oe),$}function we(h,m,g,T){if(typeof g=="object"&&g!==null&&g.type===W&&g.key===null&&(g=g.props.children),typeof g=="object"&&g!==null){switch(g.$$typeof){case Z:e:{for(var $=g.key;m!==null;){if(m.key===$){if($=g.type,$===W){if(m.tag===7){l(h,m.sibling),T=n(m,g.props.children),T.return=h,h=T;break e}}else if(m.elementType===$||typeof $=="object"&&$!==null&&$.$$typeof===Se&&ma($)===m.type){l(h,m.sibling),T=n(m,g.props),En(T,g),T.return=h,h=T;break e}l(h,m);break}else t(h,m);m=m.sibling}g.type===W?(T=sa(g.props.children,h.mode,T,g.key),T.return=h,h=T):(T=Si(g.type,g.key,g.props,null,h.mode,T),En(T,g),T.return=h,h=T)}return u(h);case V:e:{for($=g.key;m!==null;){if(m.key===$)if(m.tag===4&&m.stateNode.containerInfo===g.containerInfo&&m.stateNode.implementation===g.implementation){l(h,m.sibling),T=n(m,g.children||[]),T.return=h,h=T;break e}else{l(h,m);break}else t(h,m);m=m.sibling}T=Fu(g,h.mode,T),T.return=h,h=T}return u(h);case Se:return g=ma(g),we(h,m,g,T)}if(Ye(g))return X(h,m,g,T);if(Ve(g)){if($=Ve(g),typeof $!="function")throw Error(r(150));return g=$.call(g),ee(h,m,g,T)}if(typeof g.then=="function")return we(h,m,Ei(g),T);if(g.$$typeof===Te)return we(h,m,ji(h,g),T);Ni(h,g)}return typeof g=="string"&&g!==""||typeof g=="number"||typeof g=="bigint"?(g=""+g,m!==null&&m.tag===6?(l(h,m.sibling),T=n(m,g),T.return=h,h=T):(l(h,m),T=Wu(g,h.mode,T),T.return=h,h=T),u(h)):l(h,m)}return function(h,m,g,T){try{Mn=0;var $=we(h,m,g,T);return ka=null,$}catch(Q){if(Q===Qa||Q===Ti)throw Q;var _e=Rt(29,Q,null,h.mode);return _e.lanes=T,_e.return=h,_e}}}var ya=no(!0),io=no(!1),Bl=!1;function fc(e){e.updateQueue={baseState:e.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,lanes:0,hiddenCallbacks:null},callbacks:null}}function oc(e,t){e=e.updateQueue,t.updateQueue===e&&(t.updateQueue={baseState:e.baseState,firstBaseUpdate:e.firstBaseUpdate,lastBaseUpdate:e.lastBaseUpdate,shared:e.shared,callbacks:null})}function Rl(e){return{lane:e,tag:0,payload:null,callback:null,next:null}}function Hl(e,t,l){var a=e.updateQueue;if(a===null)return null;if(a=a.shared,(ze&2)!==0){var n=a.pending;return n===null?t.next=t:(t.next=n.next,n.next=t),a.pending=t,t=bi(e),Xf(e,null,l),t}return vi(e,a,t,l),bi(e)}function Nn(e,t,l){if(t=t.updateQueue,t!==null&&(t=t.shared,(l&4194048)!==0)){var a=t.lanes;a&=e.pendingLanes,l|=a,t.lanes=l,$s(e,l)}}function rc(e,t){var l=e.updateQueue,a=e.alternate;if(a!==null&&(a=a.updateQueue,l===a)){var n=null,i=null;if(l=l.firstBaseUpdate,l!==null){do{var u={lane:l.lane,tag:l.tag,payload:l.payload,callback:null,next:null};i===null?n=i=u:i=i.next=u,l=l.next}while(l!==null);i===null?n=i=t:i=i.next=t}else n=i=t;l={baseState:a.baseState,firstBaseUpdate:n,lastBaseUpdate:i,shared:a.shared,callbacks:a.callbacks},e.updateQueue=l;return}e=l.lastBaseUpdate,e===null?l.firstBaseUpdate=t:e.next=t,l.lastBaseUpdate=t}var dc=!1;function An(){if(dc){var e=Xa;if(e!==null)throw e}}function Dn(e,t,l,a){dc=!1;var n=e.updateQueue;Bl=!1;var i=n.firstBaseUpdate,u=n.lastBaseUpdate,s=n.shared.pending;if(s!==null){n.shared.pending=null;var o=s,p=o.next;o.next=null,u===null?i=p:u.next=p,u=o;var z=e.alternate;z!==null&&(z=z.updateQueue,s=z.lastBaseUpdate,s!==u&&(s===null?z.firstBaseUpdate=p:s.next=p,z.lastBaseUpdate=o))}if(i!==null){var M=n.baseState;u=0,z=p=o=null,s=i;do{var v=s.lane&-536870913,S=v!==s.lane;if(S?(ve&v)===v:(a&v)===v){v!==0&&v===Ya&&(dc=!0),z!==null&&(z=z.next={lane:0,tag:s.tag,payload:s.payload,callback:null,next:null});e:{var X=e,ee=s;v=t;var we=l;switch(ee.tag){case 1:if(X=ee.payload,typeof X=="function"){M=X.call(we,M,v);break e}M=X;break e;case 3:X.flags=X.flags&-65537|128;case 0:if(X=ee.payload,v=typeof X=="function"?X.call(we,M,v):X,v==null)break e;M=O({},M,v);break e;case 2:Bl=!0}}v=s.callback,v!==null&&(e.flags|=64,S&&(e.flags|=8192),S=n.callbacks,S===null?n.callbacks=[v]:S.push(v))}else S={lane:v,tag:s.tag,payload:s.payload,callback:s.callback,next:null},z===null?(p=z=S,o=M):z=z.next=S,u|=v;if(s=s.next,s===null){if(s=n.shared.pending,s===null)break;S=s,s=S.next,S.next=null,n.lastBaseUpdate=S,n.shared.pending=null}}while(!0);z===null&&(o=M),n.baseState=o,n.firstBaseUpdate=p,n.lastBaseUpdate=z,i===null&&(n.shared.lanes=0),Xl|=u,e.lanes=u,e.memoizedState=M}}function uo(e,t){if(typeof e!="function")throw Error(r(191,e));e.call(t)}function co(e,t){var l=e.callbacks;if(l!==null)for(e.callbacks=null,e=0;ei?i:8;var u=x.T,s={};x.T=s,Cc(e,!1,t,l);try{var o=n(),p=x.S;if(p!==null&&p(s,o),o!==null&&typeof o=="object"&&typeof o.then=="function"){var z=yh(o,a);Un(e,t,z,Yt(e))}else Un(e,t,a,Yt(e))}catch(M){Un(e,t,{then:function(){},status:"rejected",reason:M},Yt())}finally{C.p=i,u!==null&&s.types!==null&&(u.types=s.types),x.T=u}}function xh(){}function Ac(e,t,l,a){if(e.tag!==5)throw Error(r(476));var n=Lo(e).queue;qo(e,n,t,K,l===null?xh:function(){return Yo(e),l(a)})}function Lo(e){var t=e.memoizedState;if(t!==null)return t;t={memoizedState:K,baseState:K,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:vl,lastRenderedState:K},next:null};var l={};return t.next={memoizedState:l,baseState:l,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:vl,lastRenderedState:l},next:null},e.memoizedState=t,e=e.alternate,e!==null&&(e.memoizedState=t),t}function Yo(e){var t=Lo(e);t.next===null&&(t=e.alternate.memoizedState),Un(e,t.next.queue,{},Yt())}function Dc(){return pt(Wn)}function Xo(){return Ie().memoizedState}function Qo(){return Ie().memoizedState}function _h(e){for(var t=e.return;t!==null;){switch(t.tag){case 24:case 3:var l=Yt();e=Rl(l);var a=Hl(t,e,l);a!==null&&(Ot(a,t,l),Nn(a,t,l)),t={cache:ic()},e.payload=t;return}t=t.return}}function jh(e,t,l){var a=Yt();l={lane:a,revertLane:0,gesture:null,action:l,hasEagerState:!1,eagerState:null,next:null},Gi(e)?Zo(t,l):(l=Ju(e,t,l,a),l!==null&&(Ot(l,e,a),Vo(l,t,a)))}function ko(e,t,l){var a=Yt();Un(e,t,l,a)}function Un(e,t,l,a){var n={lane:a,revertLane:0,gesture:null,action:l,hasEagerState:!1,eagerState:null,next:null};if(Gi(e))Zo(t,n);else{var i=e.alternate;if(e.lanes===0&&(i===null||i.lanes===0)&&(i=t.lastRenderedReducer,i!==null))try{var u=t.lastRenderedState,s=i(u,l);if(n.hasEagerState=!0,n.eagerState=s,Bt(s,u))return vi(e,t,n,0),Be===null&&pi(),!1}catch{}if(l=Ju(e,t,n,a),l!==null)return Ot(l,e,a),Vo(l,t,a),!0}return!1}function Cc(e,t,l,a){if(a={lane:2,revertLane:fs(),gesture:null,action:a,hasEagerState:!1,eagerState:null,next:null},Gi(e)){if(t)throw Error(r(479))}else t=Ju(e,l,a,2),t!==null&&Ot(t,e,2)}function Gi(e){var t=e.alternate;return e===ce||t!==null&&t===ce}function Zo(e,t){Va=Ci=!0;var l=e.pending;l===null?t.next=t:(t.next=l.next,l.next=t),e.pending=t}function Vo(e,t,l){if((l&4194048)!==0){var a=t.lanes;a&=e.pendingLanes,l|=a,t.lanes=l,$s(e,l)}}var wn={readContext:pt,use:wi,useCallback:Je,useContext:Je,useEffect:Je,useImperativeHandle:Je,useLayoutEffect:Je,useInsertionEffect:Je,useMemo:Je,useReducer:Je,useRef:Je,useState:Je,useDebugValue:Je,useDeferredValue:Je,useTransition:Je,useSyncExternalStore:Je,useId:Je,useHostTransitionStatus:Je,useFormState:Je,useActionState:Je,useOptimistic:Je,useMemoCache:Je,useCacheRefresh:Je};wn.useEffectEvent=Je;var Ko={readContext:pt,use:wi,useCallback:function(e,t){return zt().memoizedState=[e,t===void 0?null:t],e},useContext:pt,useEffect:Do,useImperativeHandle:function(e,t,l){l=l!=null?l.concat([e]):null,Ri(4194308,4,wo.bind(null,t,e),l)},useLayoutEffect:function(e,t){return Ri(4194308,4,e,t)},useInsertionEffect:function(e,t){Ri(4,2,e,t)},useMemo:function(e,t){var l=zt();t=t===void 0?null:t;var a=e();if(ga){fe(!0);try{e()}finally{fe(!1)}}return l.memoizedState=[a,t],a},useReducer:function(e,t,l){var a=zt();if(l!==void 0){var n=l(t);if(ga){fe(!0);try{l(t)}finally{fe(!1)}}}else n=t;return a.memoizedState=a.baseState=n,e={pending:null,lanes:0,dispatch:null,lastRenderedReducer:e,lastRenderedState:n},a.queue=e,e=e.dispatch=jh.bind(null,ce,e),[a.memoizedState,e]},useRef:function(e){var t=zt();return e={current:e},t.memoizedState=e},useState:function(e){e=zc(e);var t=e.queue,l=ko.bind(null,ce,t);return t.dispatch=l,[e.memoizedState,l]},useDebugValue:Ec,useDeferredValue:function(e,t){var l=zt();return Nc(l,e,t)},useTransition:function(){var e=zc(!1);return e=qo.bind(null,ce,e.queue,!0,!1),zt().memoizedState=e,[!1,e]},useSyncExternalStore:function(e,t,l){var a=ce,n=zt();if(xe){if(l===void 0)throw Error(r(407));l=l()}else{if(l=t(),Be===null)throw Error(r(349));(ve&127)!==0||ho(a,t,l)}n.memoizedState=l;var i={value:l,getSnapshot:t};return n.queue=i,Do(go.bind(null,a,i,e),[e]),a.flags|=2048,Ja(9,{destroy:void 0},yo.bind(null,a,i,l,t),null),l},useId:function(){var e=zt(),t=Be.identifierPrefix;if(xe){var l=nl,a=al;l=(a&~(1<<32-pe(a)-1)).toString(32)+l,t="_"+t+"R_"+l,l=Oi++,0<\/script>",i=i.removeChild(i.firstChild);break;case"select":i=typeof a.is=="string"?u.createElement("select",{is:a.is}):u.createElement("select"),a.multiple?i.multiple=!0:a.size&&(i.size=a.size);break;default:i=typeof a.is=="string"?u.createElement(n,{is:a.is}):u.createElement(n)}}i[yt]=t,i[Mt]=a;e:for(u=t.child;u!==null;){if(u.tag===5||u.tag===6)i.appendChild(u.stateNode);else if(u.tag!==4&&u.tag!==27&&u.child!==null){u.child.return=u,u=u.child;continue}if(u===t)break e;for(;u.sibling===null;){if(u.return===null||u.return===t)break e;u=u.return}u.sibling.return=u.return,u=u.sibling}t.stateNode=i;e:switch(bt(i,n,a),n){case"button":case"input":case"select":case"textarea":a=!!a.autoFocus;break e;case"img":a=!0;break e;default:a=!1}a&&Sl(t)}}return qe(t),Zc(t,t.type,e===null?null:e.memoizedProps,t.pendingProps,l),null;case 6:if(e&&t.stateNode!=null)e.memoizedProps!==a&&Sl(t);else{if(typeof a!="string"&&t.stateNode===null)throw Error(r(166));if(e=ae.current,qa(t)){if(e=t.stateNode,l=t.memoizedProps,a=null,n=gt,n!==null)switch(n.tag){case 27:case 5:a=n.memoizedProps}e[yt]=t,e=!!(e.nodeValue===l||a!==null&&a.suppressHydrationWarning===!0||dd(e.nodeValue,l)),e||Ul(t,!0)}else e=nu(e).createTextNode(a),e[yt]=t,t.stateNode=e}return qe(t),null;case 31:if(l=t.memoizedState,e===null||e.memoizedState!==null){if(a=qa(t),l!==null){if(e===null){if(!a)throw Error(r(318));if(e=t.memoizedState,e=e!==null?e.dehydrated:null,!e)throw Error(r(557));e[yt]=t}else fa(),(t.flags&128)===0&&(t.memoizedState=null),t.flags|=4;qe(t),e=!1}else l=tc(),e!==null&&e.memoizedState!==null&&(e.memoizedState.hydrationErrors=l),e=!0;if(!e)return t.flags&256?(Gt(t),t):(Gt(t),null);if((t.flags&128)!==0)throw Error(r(558))}return qe(t),null;case 13:if(a=t.memoizedState,e===null||e.memoizedState!==null&&e.memoizedState.dehydrated!==null){if(n=qa(t),a!==null&&a.dehydrated!==null){if(e===null){if(!n)throw Error(r(318));if(n=t.memoizedState,n=n!==null?n.dehydrated:null,!n)throw Error(r(317));n[yt]=t}else fa(),(t.flags&128)===0&&(t.memoizedState=null),t.flags|=4;qe(t),n=!1}else n=tc(),e!==null&&e.memoizedState!==null&&(e.memoizedState.hydrationErrors=n),n=!0;if(!n)return t.flags&256?(Gt(t),t):(Gt(t),null)}return Gt(t),(t.flags&128)!==0?(t.lanes=l,t):(l=a!==null,e=e!==null&&e.memoizedState!==null,l&&(a=t.child,n=null,a.alternate!==null&&a.alternate.memoizedState!==null&&a.alternate.memoizedState.cachePool!==null&&(n=a.alternate.memoizedState.cachePool.pool),i=null,a.memoizedState!==null&&a.memoizedState.cachePool!==null&&(i=a.memoizedState.cachePool.pool),i!==n&&(a.flags|=2048)),l!==e&&l&&(t.child.flags|=8192),Qi(t,t.updateQueue),qe(t),null);case 4:return Ee(),e===null&&ms(t.stateNode.containerInfo),qe(t),null;case 10:return gl(t.type),qe(t),null;case 19:if(j(Fe),a=t.memoizedState,a===null)return qe(t),null;if(n=(t.flags&128)!==0,i=a.rendering,i===null)if(n)Rn(a,!1);else{if($e!==0||e!==null&&(e.flags&128)!==0)for(e=t.child;e!==null;){if(i=Di(e),i!==null){for(t.flags|=128,Rn(a,!1),e=i.updateQueue,t.updateQueue=e,Qi(t,e),t.subtreeFlags=0,e=l,l=t.child;l!==null;)Qf(l,e),l=l.sibling;return w(Fe,Fe.current&1|2),xe&&hl(t,a.treeForkCount),t.child}e=e.sibling}a.tail!==null&&ut()>Ji&&(t.flags|=128,n=!0,Rn(a,!1),t.lanes=4194304)}else{if(!n)if(e=Di(i),e!==null){if(t.flags|=128,n=!0,e=e.updateQueue,t.updateQueue=e,Qi(t,e),Rn(a,!0),a.tail===null&&a.tailMode==="hidden"&&!i.alternate&&!xe)return qe(t),null}else 2*ut()-a.renderingStartTime>Ji&&l!==536870912&&(t.flags|=128,n=!0,Rn(a,!1),t.lanes=4194304);a.isBackwards?(i.sibling=t.child,t.child=i):(e=a.last,e!==null?e.sibling=i:t.child=i,a.last=i)}return a.tail!==null?(e=a.tail,a.rendering=e,a.tail=e.sibling,a.renderingStartTime=ut(),e.sibling=null,l=Fe.current,w(Fe,n?l&1|2:l&1),xe&&hl(t,a.treeForkCount),e):(qe(t),null);case 22:case 23:return Gt(t),hc(),a=t.memoizedState!==null,e!==null?e.memoizedState!==null!==a&&(t.flags|=8192):a&&(t.flags|=8192),a?(l&536870912)!==0&&(t.flags&128)===0&&(qe(t),t.subtreeFlags&6&&(t.flags|=8192)):qe(t),l=t.updateQueue,l!==null&&Qi(t,l.retryQueue),l=null,e!==null&&e.memoizedState!==null&&e.memoizedState.cachePool!==null&&(l=e.memoizedState.cachePool.pool),a=null,t.memoizedState!==null&&t.memoizedState.cachePool!==null&&(a=t.memoizedState.cachePool.pool),a!==l&&(t.flags|=2048),e!==null&&j(da),null;case 24:return l=null,e!==null&&(l=e.memoizedState.cache),t.memoizedState.cache!==l&&(t.flags|=2048),gl(et),qe(t),null;case 25:return null;case 30:return null}throw Error(r(156,t.tag))}function Nh(e,t){switch(Pu(t),t.tag){case 1:return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 3:return gl(et),Ee(),e=t.flags,(e&65536)!==0&&(e&128)===0?(t.flags=e&-65537|128,t):null;case 26:case 27:case 5:return ot(t),null;case 31:if(t.memoizedState!==null){if(Gt(t),t.alternate===null)throw Error(r(340));fa()}return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 13:if(Gt(t),e=t.memoizedState,e!==null&&e.dehydrated!==null){if(t.alternate===null)throw Error(r(340));fa()}return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 19:return j(Fe),null;case 4:return Ee(),null;case 10:return gl(t.type),null;case 22:case 23:return Gt(t),hc(),e!==null&&j(da),e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 24:return gl(et),null;case 25:return null;default:return null}}function pr(e,t){switch(Pu(t),t.tag){case 3:gl(et),Ee();break;case 26:case 27:case 5:ot(t);break;case 4:Ee();break;case 31:t.memoizedState!==null&&Gt(t);break;case 13:Gt(t);break;case 19:j(Fe);break;case 10:gl(t.type);break;case 22:case 23:Gt(t),hc(),e!==null&&j(da);break;case 24:gl(et)}}function Hn(e,t){try{var l=t.updateQueue,a=l!==null?l.lastEffect:null;if(a!==null){var n=a.next;l=n;do{if((l.tag&e)===e){a=void 0;var i=l.create,u=l.inst;a=i(),u.destroy=a}l=l.next}while(l!==n)}}catch(s){De(t,t.return,s)}}function Ll(e,t,l){try{var a=t.updateQueue,n=a!==null?a.lastEffect:null;if(n!==null){var i=n.next;a=i;do{if((a.tag&e)===e){var u=a.inst,s=u.destroy;if(s!==void 0){u.destroy=void 0,n=t;var o=l,p=s;try{p()}catch(z){De(n,o,z)}}}a=a.next}while(a!==i)}}catch(z){De(t,t.return,z)}}function vr(e){var t=e.updateQueue;if(t!==null){var l=e.stateNode;try{co(t,l)}catch(a){De(e,e.return,a)}}}function br(e,t,l){l.props=pa(e.type,e.memoizedProps),l.state=e.memoizedState;try{l.componentWillUnmount()}catch(a){De(e,t,a)}}function Gn(e,t){try{var l=e.ref;if(l!==null){switch(e.tag){case 26:case 27:case 5:var a=e.stateNode;break;case 30:a=e.stateNode;break;default:a=e.stateNode}typeof l=="function"?e.refCleanup=l(a):l.current=a}}catch(n){De(e,t,n)}}function il(e,t){var l=e.ref,a=e.refCleanup;if(l!==null)if(typeof a=="function")try{a()}catch(n){De(e,t,n)}finally{e.refCleanup=null,e=e.alternate,e!=null&&(e.refCleanup=null)}else if(typeof l=="function")try{l(null)}catch(n){De(e,t,n)}else l.current=null}function Sr(e){var t=e.type,l=e.memoizedProps,a=e.stateNode;try{e:switch(t){case"button":case"input":case"select":case"textarea":l.autoFocus&&a.focus();break e;case"img":l.src?a.src=l.src:l.srcSet&&(a.srcset=l.srcSet)}}catch(n){De(e,e.return,n)}}function Vc(e,t,l){try{var a=e.stateNode;Wh(a,e.type,l,t),a[Mt]=t}catch(n){De(e,e.return,n)}}function xr(e){return e.tag===5||e.tag===3||e.tag===26||e.tag===27&&Kl(e.type)||e.tag===4}function Kc(e){e:for(;;){for(;e.sibling===null;){if(e.return===null||xr(e.return))return null;e=e.return}for(e.sibling.return=e.return,e=e.sibling;e.tag!==5&&e.tag!==6&&e.tag!==18;){if(e.tag===27&&Kl(e.type)||e.flags&2||e.child===null||e.tag===4)continue e;e.child.return=e,e=e.child}if(!(e.flags&2))return e.stateNode}}function Jc(e,t,l){var a=e.tag;if(a===5||a===6)e=e.stateNode,t?(l.nodeType===9?l.body:l.nodeName==="HTML"?l.ownerDocument.body:l).insertBefore(e,t):(t=l.nodeType===9?l.body:l.nodeName==="HTML"?l.ownerDocument.body:l,t.appendChild(e),l=l._reactRootContainer,l!=null||t.onclick!==null||(t.onclick=rl));else if(a!==4&&(a===27&&Kl(e.type)&&(l=e.stateNode,t=null),e=e.child,e!==null))for(Jc(e,t,l),e=e.sibling;e!==null;)Jc(e,t,l),e=e.sibling}function ki(e,t,l){var a=e.tag;if(a===5||a===6)e=e.stateNode,t?l.insertBefore(e,t):l.appendChild(e);else if(a!==4&&(a===27&&Kl(e.type)&&(l=e.stateNode),e=e.child,e!==null))for(ki(e,t,l),e=e.sibling;e!==null;)ki(e,t,l),e=e.sibling}function _r(e){var t=e.stateNode,l=e.memoizedProps;try{for(var a=e.type,n=t.attributes;n.length;)t.removeAttributeNode(n[0]);bt(t,a,l),t[yt]=e,t[Mt]=l}catch(i){De(e,e.return,i)}}var xl=!1,at=!1,$c=!1,jr=typeof WeakSet=="function"?WeakSet:Set,mt=null;function Ah(e,t){if(e=e.containerInfo,gs=ru,e=wf(e),Xu(e)){if("selectionStart"in e)var l={start:e.selectionStart,end:e.selectionEnd};else e:{l=(l=e.ownerDocument)&&l.defaultView||window;var a=l.getSelection&&l.getSelection();if(a&&a.rangeCount!==0){l=a.anchorNode;var n=a.anchorOffset,i=a.focusNode;a=a.focusOffset;try{l.nodeType,i.nodeType}catch{l=null;break e}var u=0,s=-1,o=-1,p=0,z=0,M=e,v=null;t:for(;;){for(var S;M!==l||n!==0&&M.nodeType!==3||(s=u+n),M!==i||a!==0&&M.nodeType!==3||(o=u+a),M.nodeType===3&&(u+=M.nodeValue.length),(S=M.firstChild)!==null;)v=M,M=S;for(;;){if(M===e)break t;if(v===l&&++p===n&&(s=u),v===i&&++z===a&&(o=u),(S=M.nextSibling)!==null)break;M=v,v=M.parentNode}M=S}l=s===-1||o===-1?null:{start:s,end:o}}else l=null}l=l||{start:0,end:0}}else l=null;for(ps={focusedElem:e,selectionRange:l},ru=!1,mt=t;mt!==null;)if(t=mt,e=t.child,(t.subtreeFlags&1028)!==0&&e!==null)e.return=t,mt=e;else for(;mt!==null;){switch(t=mt,i=t.alternate,e=t.flags,t.tag){case 0:if((e&4)!==0&&(e=t.updateQueue,e=e!==null?e.events:null,e!==null))for(l=0;l title"))),bt(i,a,l),i[yt]=e,dt(i),a=i;break e;case"link":var u=Ad("link","href",n).get(a+(l.href||""));if(u){for(var s=0;swe&&(u=we,we=ee,ee=u);var h=Of(s,ee),m=Of(s,we);if(h&&m&&(S.rangeCount!==1||S.anchorNode!==h.node||S.anchorOffset!==h.offset||S.focusNode!==m.node||S.focusOffset!==m.offset)){var g=M.createRange();g.setStart(h.node,h.offset),S.removeAllRanges(),ee>we?(S.addRange(g),S.extend(m.node,m.offset)):(g.setEnd(m.node,m.offset),S.addRange(g))}}}}for(M=[],S=s;S=S.parentNode;)S.nodeType===1&&M.push({element:S,left:S.scrollLeft,top:S.scrollTop});for(typeof s.focus=="function"&&s.focus(),s=0;sl?32:l,x.T=null,l=ls,ls=null;var i=kl,u=Ml;if(st=0,Pa=kl=null,Ml=0,(ze&6)!==0)throw Error(r(331));var s=ze;if(ze|=4,wr(i.current),Cr(i,i.current,u,l),ze=s,kn(0,!1),ne&&typeof ne.onPostCommitFiberRoot=="function")try{ne.onPostCommitFiberRoot(We,i)}catch{}return!0}finally{C.p=n,x.T=a,Ir(e,t)}}function ed(e,t,l){t=Zt(l,t),t=Bc(e.stateNode,t,2),e=Hl(e,t,2),e!==null&&(on(e,2),ul(e))}function De(e,t,l){if(e.tag===3)ed(e,e,l);else for(;t!==null;){if(t.tag===3){ed(t,e,l);break}else if(t.tag===1){var a=t.stateNode;if(typeof t.type.getDerivedStateFromError=="function"||typeof a.componentDidCatch=="function"&&(Ql===null||!Ql.has(a))){e=Zt(l,e),l=tr(2),a=Hl(t,l,2),a!==null&&(lr(l,a,t,e),on(a,2),ul(a));break}}t=t.return}}function us(e,t,l){var a=e.pingCache;if(a===null){a=e.pingCache=new Oh;var n=new Set;a.set(t,n)}else n=a.get(t),n===void 0&&(n=new Set,a.set(t,n));n.has(l)||(Ic=!0,n.add(l),e=Hh.bind(null,e,t,l),t.then(e,e))}function Hh(e,t,l){var a=e.pingCache;a!==null&&a.delete(t),e.pingedLanes|=e.suspendedLanes&l,e.warmLanes&=~l,Be===e&&(ve&l)===l&&($e===4||$e===3&&(ve&62914560)===ve&&300>ut()-Ki?(ze&2)===0&&en(e,0):Pc|=l,Ia===ve&&(Ia=0)),ul(e)}function td(e,t){t===0&&(t=Ks()),e=ca(e,t),e!==null&&(on(e,t),ul(e))}function Gh(e){var t=e.memoizedState,l=0;t!==null&&(l=t.retryLane),td(e,l)}function qh(e,t){var l=0;switch(e.tag){case 31:case 13:var a=e.stateNode,n=e.memoizedState;n!==null&&(l=n.retryLane);break;case 19:a=e.stateNode;break;case 22:a=e.stateNode._retryCache;break;default:throw Error(r(314))}a!==null&&a.delete(t),td(e,l)}function Lh(e,t){return P(e,t)}var eu=null,ln=null,cs=!1,tu=!1,ss=!1,Vl=0;function ul(e){e!==ln&&e.next===null&&(ln===null?eu=ln=e:ln=ln.next=e),tu=!0,cs||(cs=!0,Xh())}function kn(e,t){if(!ss&&tu){ss=!0;do for(var l=!1,a=eu;a!==null;){if(e!==0){var n=a.pendingLanes;if(n===0)var i=0;else{var u=a.suspendedLanes,s=a.pingedLanes;i=(1<<31-pe(42|e)+1)-1,i&=n&~(u&~s),i=i&201326741?i&201326741|1:i?i|2:0}i!==0&&(l=!0,id(a,i))}else i=ve,i=ii(a,a===Be?i:0,a.cancelPendingCommit!==null||a.timeoutHandle!==-1),(i&3)===0||fn(a,i)||(l=!0,id(a,i));a=a.next}while(l);ss=!1}}function Yh(){ld()}function ld(){tu=cs=!1;var e=0;Vl!==0&&Ih()&&(e=Vl);for(var t=ut(),l=null,a=eu;a!==null;){var n=a.next,i=ad(a,t);i===0?(a.next=null,l===null?eu=n:l.next=n,n===null&&(ln=l)):(l=a,(e!==0||(i&3)!==0)&&(tu=!0)),a=n}st!==0&&st!==5||kn(e),Vl!==0&&(Vl=0)}function ad(e,t){for(var l=e.suspendedLanes,a=e.pingedLanes,n=e.expirationTimes,i=e.pendingLanes&-62914561;0s)break;var z=o.transferSize,M=o.initiatorType;z&&md(M)&&(o=o.responseEnd,u+=z*(o"u"?null:document;function Td(e,t,l){var a=an;if(a&&typeof t=="string"&&t){var n=Qt(t);n='link[rel="'+e+'"][href="'+n+'"]',typeof l=="string"&&(n+='[crossorigin="'+l+'"]'),zd.has(n)||(zd.add(n),e={rel:e,crossOrigin:l,href:t},a.querySelector(n)===null&&(t=a.createElement("link"),bt(t,"link",e),dt(t),a.head.appendChild(t)))}}function c0(e){El.D(e),Td("dns-prefetch",e,null)}function s0(e,t){El.C(e,t),Td("preconnect",e,t)}function f0(e,t,l){El.L(e,t,l);var a=an;if(a&&e&&t){var n='link[rel="preload"][as="'+Qt(t)+'"]';t==="image"&&l&&l.imageSrcSet?(n+='[imagesrcset="'+Qt(l.imageSrcSet)+'"]',typeof l.imageSizes=="string"&&(n+='[imagesizes="'+Qt(l.imageSizes)+'"]')):n+='[href="'+Qt(e)+'"]';var i=n;switch(t){case"style":i=nn(e);break;case"script":i=un(e)}Ft.has(i)||(e=O({rel:"preload",href:t==="image"&&l&&l.imageSrcSet?void 0:e,as:t},l),Ft.set(i,e),a.querySelector(n)!==null||t==="style"&&a.querySelector(Jn(i))||t==="script"&&a.querySelector($n(i))||(t=a.createElement("link"),bt(t,"link",e),dt(t),a.head.appendChild(t)))}}function o0(e,t){El.m(e,t);var l=an;if(l&&e){var a=t&&typeof t.as=="string"?t.as:"script",n='link[rel="modulepreload"][as="'+Qt(a)+'"][href="'+Qt(e)+'"]',i=n;switch(a){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":i=un(e)}if(!Ft.has(i)&&(e=O({rel:"modulepreload",href:e},t),Ft.set(i,e),l.querySelector(n)===null)){switch(a){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":if(l.querySelector($n(i)))return}a=l.createElement("link"),bt(a,"link",e),dt(a),l.head.appendChild(a)}}}function r0(e,t,l){El.S(e,t,l);var a=an;if(a&&e){var n=Ma(a).hoistableStyles,i=nn(e);t=t||"default";var u=n.get(i);if(!u){var s={loading:0,preload:null};if(u=a.querySelector(Jn(i)))s.loading=5;else{e=O({rel:"stylesheet",href:e,"data-precedence":t},l),(l=Ft.get(i))&&zs(e,l);var o=u=a.createElement("link");dt(o),bt(o,"link",e),o._p=new Promise(function(p,z){o.onload=p,o.onerror=z}),o.addEventListener("load",function(){s.loading|=1}),o.addEventListener("error",function(){s.loading|=2}),s.loading|=4,uu(u,t,a)}u={type:"stylesheet",instance:u,count:1,state:s},n.set(i,u)}}}function d0(e,t){El.X(e,t);var l=an;if(l&&e){var a=Ma(l).hoistableScripts,n=un(e),i=a.get(n);i||(i=l.querySelector($n(n)),i||(e=O({src:e,async:!0},t),(t=Ft.get(n))&&Ts(e,t),i=l.createElement("script"),dt(i),bt(i,"link",e),l.head.appendChild(i)),i={type:"script",instance:i,count:1,state:null},a.set(n,i))}}function m0(e,t){El.M(e,t);var l=an;if(l&&e){var a=Ma(l).hoistableScripts,n=un(e),i=a.get(n);i||(i=l.querySelector($n(n)),i||(e=O({src:e,async:!0,type:"module"},t),(t=Ft.get(n))&&Ts(e,t),i=l.createElement("script"),dt(i),bt(i,"link",e),l.head.appendChild(i)),i={type:"script",instance:i,count:1,state:null},a.set(n,i))}}function Md(e,t,l,a){var n=(n=ae.current)?iu(n):null;if(!n)throw Error(r(446));switch(e){case"meta":case"title":return null;case"style":return typeof l.precedence=="string"&&typeof l.href=="string"?(t=nn(l.href),l=Ma(n).hoistableStyles,a=l.get(t),a||(a={type:"style",instance:null,count:0,state:null},l.set(t,a)),a):{type:"void",instance:null,count:0,state:null};case"link":if(l.rel==="stylesheet"&&typeof l.href=="string"&&typeof l.precedence=="string"){e=nn(l.href);var i=Ma(n).hoistableStyles,u=i.get(e);if(u||(n=n.ownerDocument||n,u={type:"stylesheet",instance:null,count:0,state:{loading:0,preload:null}},i.set(e,u),(i=n.querySelector(Jn(e)))&&!i._p&&(u.instance=i,u.state.loading=5),Ft.has(e)||(l={rel:"preload",as:"style",href:l.href,crossOrigin:l.crossOrigin,integrity:l.integrity,media:l.media,hrefLang:l.hrefLang,referrerPolicy:l.referrerPolicy},Ft.set(e,l),i||h0(n,e,l,u.state))),t&&a===null)throw Error(r(528,""));return u}if(t&&a!==null)throw Error(r(529,""));return null;case"script":return t=l.async,l=l.src,typeof l=="string"&&t&&typeof t!="function"&&typeof t!="symbol"?(t=un(l),l=Ma(n).hoistableScripts,a=l.get(t),a||(a={type:"script",instance:null,count:0,state:null},l.set(t,a)),a):{type:"void",instance:null,count:0,state:null};default:throw Error(r(444,e))}}function nn(e){return'href="'+Qt(e)+'"'}function Jn(e){return'link[rel="stylesheet"]['+e+"]"}function Ed(e){return O({},e,{"data-precedence":e.precedence,precedence:null})}function h0(e,t,l,a){e.querySelector('link[rel="preload"][as="style"]['+t+"]")?a.loading=1:(t=e.createElement("link"),a.preload=t,t.addEventListener("load",function(){return a.loading|=1}),t.addEventListener("error",function(){return a.loading|=2}),bt(t,"link",l),dt(t),e.head.appendChild(t))}function un(e){return'[src="'+Qt(e)+'"]'}function $n(e){return"script[async]"+e}function Nd(e,t,l){if(t.count++,t.instance===null)switch(t.type){case"style":var a=e.querySelector('style[data-href~="'+Qt(l.href)+'"]');if(a)return t.instance=a,dt(a),a;var n=O({},l,{"data-href":l.href,"data-precedence":l.precedence,href:null,precedence:null});return a=(e.ownerDocument||e).createElement("style"),dt(a),bt(a,"style",n),uu(a,l.precedence,e),t.instance=a;case"stylesheet":n=nn(l.href);var i=e.querySelector(Jn(n));if(i)return t.state.loading|=4,t.instance=i,dt(i),i;a=Ed(l),(n=Ft.get(n))&&zs(a,n),i=(e.ownerDocument||e).createElement("link"),dt(i);var u=i;return u._p=new Promise(function(s,o){u.onload=s,u.onerror=o}),bt(i,"link",a),t.state.loading|=4,uu(i,l.precedence,e),t.instance=i;case"script":return i=un(l.src),(n=e.querySelector($n(i)))?(t.instance=n,dt(n),n):(a=l,(n=Ft.get(i))&&(a=O({},l),Ts(a,n)),e=e.ownerDocument||e,n=e.createElement("script"),dt(n),bt(n,"link",a),e.head.appendChild(n),t.instance=n);case"void":return null;default:throw Error(r(443,t.type))}else t.type==="stylesheet"&&(t.state.loading&4)===0&&(a=t.instance,t.state.loading|=4,uu(a,l.precedence,e));return t.instance}function uu(e,t,l){for(var a=l.querySelectorAll('link[rel="stylesheet"][data-precedence],style[data-precedence]'),n=a.length?a[a.length-1]:null,i=n,u=0;u title"):null)}function y0(e,t,l){if(l===1||t.itemProp!=null)return!1;switch(e){case"meta":case"title":return!0;case"style":if(typeof t.precedence!="string"||typeof t.href!="string"||t.href==="")break;return!0;case"link":if(typeof t.rel!="string"||typeof t.href!="string"||t.href===""||t.onLoad||t.onError)break;return t.rel==="stylesheet"?(e=t.disabled,typeof t.precedence=="string"&&e==null):!0;case"script":if(t.async&&typeof t.async!="function"&&typeof t.async!="symbol"&&!t.onLoad&&!t.onError&&t.src&&typeof t.src=="string")return!0}return!1}function Cd(e){return!(e.type==="stylesheet"&&(e.state.loading&3)===0)}function g0(e,t,l,a){if(l.type==="stylesheet"&&(typeof a.media!="string"||matchMedia(a.media).matches!==!1)&&(l.state.loading&4)===0){if(l.instance===null){var n=nn(a.href),i=t.querySelector(Jn(n));if(i){t=i._p,t!==null&&typeof t=="object"&&typeof t.then=="function"&&(e.count++,e=su.bind(e),t.then(e,e)),l.state.loading|=4,l.instance=i,dt(i);return}i=t.ownerDocument||t,a=Ed(a),(n=Ft.get(n))&&zs(a,n),i=i.createElement("link"),dt(i);var u=i;u._p=new Promise(function(s,o){u.onload=s,u.onerror=o}),bt(i,"link",a),l.instance=i}e.stylesheets===null&&(e.stylesheets=new Map),e.stylesheets.set(l,t),(t=l.state.preload)&&(l.state.loading&3)===0&&(e.count++,l=su.bind(e),t.addEventListener("load",l),t.addEventListener("error",l))}}var Ms=0;function p0(e,t){return e.stylesheets&&e.count===0&&ou(e,e.stylesheets),0Ms?50:800)+t);return e.unsuspend=l,function(){e.unsuspend=null,clearTimeout(a),clearTimeout(n)}}:null}function su(){if(this.count--,this.count===0&&(this.imgCount===0||!this.waitingForImages)){if(this.stylesheets)ou(this,this.stylesheets);else if(this.unsuspend){var e=this.unsuspend;this.unsuspend=null,e()}}}var fu=null;function ou(e,t){e.stylesheets=null,e.unsuspend!==null&&(e.count++,fu=new Map,t.forEach(v0,e),fu=null,su.call(e))}function v0(e,t){if(!(t.state.loading&4)){var l=fu.get(e);if(l)var a=l.get(null);else{l=new Map,fu.set(e,l);for(var n=e.querySelectorAll("link[data-precedence],style[data-precedence]"),i=0;i"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(f)}catch(b){console.error(b)}}return f(),Bs.exports=B0(),Bs.exports}var H0=R0();const G0=sm(H0);const fm=(...f)=>f.filter((b,E,r)=>!!b&&b.trim()!==""&&r.indexOf(b)===E).join(" ").trim();const q0=f=>f.replace(/([a-z0-9])([A-Z])/g,"$1-$2").toLowerCase();const L0=f=>f.replace(/^([A-Z])|[\s-_]+(\w)/g,(b,E,r)=>r?r.toUpperCase():E.toLowerCase());const tm=f=>{const b=L0(f);return b.charAt(0).toUpperCase()+b.slice(1)};var qs={xmlns:"http://www.w3.org/2000/svg",width:24,height:24,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"};const Y0=f=>{for(const b in f)if(b.startsWith("aria-")||b==="role"||b==="title")return!0;return!1},X0=U.createContext({}),Q0=()=>U.useContext(X0),k0=U.forwardRef(({color:f,size:b,strokeWidth:E,absoluteStrokeWidth:r,className:_="",children:N,iconNode:G,...H},B)=>{const{size:y=24,strokeWidth:A=2,absoluteStrokeWidth:O=!1,color:L="currentColor",className:Z=""}=Q0()??{},V=r??O?Number(E??A)*24/Number(b??y):E??A;return U.createElement("svg",{ref:B,...qs,width:b??y??qs.width,height:b??y??qs.height,stroke:f??L,strokeWidth:V,className:fm("lucide",Z,_),...!N&&!Y0(H)&&{"aria-hidden":"true"},...H},[...G.map(([W,ue])=>U.createElement(W,ue)),...Array.isArray(N)?N:[N]])});const Ze=(f,b)=>{const E=U.forwardRef(({className:r,..._},N)=>U.createElement(k0,{ref:N,iconNode:b,className:fm(`lucide-${q0(tm(f))}`,`lucide-${f}`,r),..._}));return E.displayName=tm(f),E};const Z0=[["path",{d:"M20 6 9 17l-5-5",key:"1gmf2c"}]],Ls=Ze("check",Z0);const V0=[["path",{d:"M12 13v8l-4-4",key:"1f5nwf"}],["path",{d:"m12 21 4-4",key:"1lfcce"}],["path",{d:"M4.393 15.269A7 7 0 1 1 15.71 8h1.79a4.5 4.5 0 0 1 2.436 8.284",key:"ui1hmy"}]],lm=Ze("cloud-download",V0);const K0=[["rect",{width:"14",height:"14",x:"8",y:"8",rx:"2",ry:"2",key:"17jyea"}],["path",{d:"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2",key:"zix9uf"}]],J0=Ze("copy",K0);const $0=[["path",{d:"M12 20v2",key:"1lh1kg"}],["path",{d:"M12 2v2",key:"tus03m"}],["path",{d:"M17 20v2",key:"1rnc9c"}],["path",{d:"M17 2v2",key:"11trls"}],["path",{d:"M2 12h2",key:"1t8f8n"}],["path",{d:"M2 17h2",key:"7oei6x"}],["path",{d:"M2 7h2",key:"asdhe0"}],["path",{d:"M20 12h2",key:"1q8mjw"}],["path",{d:"M20 17h2",key:"1fpfkl"}],["path",{d:"M20 7h2",key:"1o8tra"}],["path",{d:"M7 20v2",key:"4gnj0m"}],["path",{d:"M7 2v2",key:"1i4yhu"}],["rect",{x:"4",y:"4",width:"16",height:"16",rx:"2",key:"1vbyd7"}],["rect",{x:"8",y:"8",width:"8",height:"8",rx:"1",key:"z9xiuo"}]],om=Ze("cpu",$0);const W0=[["path",{d:"M6 2v14a2 2 0 0 0 2 2h14",key:"ron5a4"}],["path",{d:"M18 22V8a2 2 0 0 0-2-2H2",key:"7s9ehn"}]],F0=Ze("crop",W0);const I0=[["ellipse",{cx:"12",cy:"5",rx:"9",ry:"3",key:"msslwz"}],["path",{d:"M3 5V19A9 3 0 0 0 21 19V5",key:"1wlel7"}],["path",{d:"M3 12A9 3 0 0 0 21 12",key:"mv7ke4"}]],Ys=Ze("database",I0);const P0=[["path",{d:"M12 15V3",key:"m9g1x1"}],["path",{d:"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4",key:"ih7n3h"}],["path",{d:"m7 10 5 5 5-5",key:"brsn70"}]],am=Ze("download",P0);const ey=[["path",{d:"M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z",key:"1kt360"}],["path",{d:"M12 10v6",key:"1bos4e"}],["path",{d:"m15 13-3 3-3-3",key:"6j2sf0"}]],ty=Ze("folder-down",ey);const ly=[["path",{d:"m6 14 1.5-2.9A2 2 0 0 1 9.24 10H20a2 2 0 0 1 1.94 2.5l-1.54 6a2 2 0 0 1-1.95 1.5H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h3.9a2 2 0 0 1 1.69.9l.81 1.2a2 2 0 0 0 1.67.9H18a2 2 0 0 1 2 2v2",key:"usdka0"}]],nm=Ze("folder-open",ly);const ay=[["path",{d:"M10 16h.01",key:"1bzywj"}],["path",{d:"M2.212 11.577a2 2 0 0 0-.212.896V18a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-5.527a2 2 0 0 0-.212-.896L18.55 5.11A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z",key:"18tbho"}],["path",{d:"M21.946 12.013H2.054",key:"zqlbp7"}],["path",{d:"M6 16h.01",key:"1pmjb7"}]],bu=Ze("hard-drive",ay);const ny=[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",ry:"2",key:"1m3agn"}],["circle",{cx:"9",cy:"9",r:"2",key:"af1f0g"}],["path",{d:"m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21",key:"1xmnt7"}]],iy=Ze("image",ny);const uy=[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["path",{d:"M12 16v-4",key:"1dtifu"}],["path",{d:"M12 8h.01",key:"e9boi3"}]],cy=Ze("info",uy);const sy=[["path",{d:"m16 6 4 14",key:"ji33uf"}],["path",{d:"M12 6v14",key:"1n7gus"}],["path",{d:"M8 8v12",key:"1gg7y9"}],["path",{d:"M4 4v16",key:"6qkkli"}]],fy=Ze("library",sy);const oy=[["path",{d:"M20.985 12.486a9 9 0 1 1-9.473-9.472c.405-.022.617.46.402.803a6 6 0 0 0 8.268 8.268c.344-.215.825-.004.803.401",key:"kfwtm"}]],ry=Ze("moon",oy);const dy=[["path",{d:"M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8",key:"v9h5vc"}],["path",{d:"M21 3v5h-5",key:"1q7to0"}],["path",{d:"M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16",key:"3uifl3"}],["path",{d:"M8 16H3v5",key:"1cv678"}]],ea=Ze("refresh-cw",dy);const my=[["path",{d:"M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z",key:"oel41y"}]],hy=Ze("shield",my);const yy=[["path",{d:"M10 8h4",key:"1sr2af"}],["path",{d:"M12 21v-9",key:"17s77i"}],["path",{d:"M12 8V3",key:"13r4qs"}],["path",{d:"M17 16h4",key:"h1uq16"}],["path",{d:"M19 12V3",key:"o1uvq1"}],["path",{d:"M19 21v-5",key:"qua636"}],["path",{d:"M3 14h4",key:"bcjad9"}],["path",{d:"M5 10V3",key:"cb8scm"}],["path",{d:"M5 21v-7",key:"1w1uti"}]],Zs=Ze("sliders-vertical",yy);const gy=[["path",{d:"M11.017 2.814a1 1 0 0 1 1.966 0l1.051 5.558a2 2 0 0 0 1.594 1.594l5.558 1.051a1 1 0 0 1 0 1.966l-5.558 1.051a2 2 0 0 0-1.594 1.594l-1.051 5.558a1 1 0 0 1-1.966 0l-1.051-5.558a2 2 0 0 0-1.594-1.594l-5.558-1.051a1 1 0 0 1 0-1.966l5.558-1.051a2 2 0 0 0 1.594-1.594z",key:"1s2grr"}],["path",{d:"M20 2v4",key:"1rf3ol"}],["path",{d:"M22 4h-4",key:"gwowj6"}],["circle",{cx:"4",cy:"20",r:"2",key:"6kqj1y"}]],vu=Ze("sparkles",gy);const py=[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",key:"afitv7"}]],Xs=Ze("square",py);const vy=[["circle",{cx:"12",cy:"12",r:"4",key:"4exip2"}],["path",{d:"M12 2v2",key:"tus03m"}],["path",{d:"M12 20v2",key:"1lh1kg"}],["path",{d:"m4.93 4.93 1.41 1.41",key:"149t6j"}],["path",{d:"m17.66 17.66 1.41 1.41",key:"ptbguv"}],["path",{d:"M2 12h2",key:"1t8f8n"}],["path",{d:"M20 12h2",key:"1q8mjw"}],["path",{d:"m6.34 17.66-1.41 1.41",key:"1m8zz5"}],["path",{d:"m19.07 4.93-1.41 1.41",key:"1shlcs"}]],by=Ze("sun",vy);const Sy=[["path",{d:"M12 19h8",key:"baeox8"}],["path",{d:"m4 17 6-6-6-6",key:"1yngyt"}]],xy=Ze("terminal",Sy);const _y=[["path",{d:"M10 11v6",key:"nco0om"}],["path",{d:"M14 11v6",key:"outv1u"}],["path",{d:"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6",key:"miytrc"}],["path",{d:"M3 6h18",key:"d0wm0j"}],["path",{d:"M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2",key:"e791ji"}]],li=Ze("trash-2",_y);const jy=[["path",{d:"m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3",key:"wmoenq"}],["path",{d:"M12 9v4",key:"juzpu7"}],["path",{d:"M12 17h.01",key:"p32p05"}]],zy=Ze("triangle-alert",jy);function Ty({activeTab:f,setActiveTab:b,specs:E}){return c.jsxs("div",{className:"sidebar",children:[c.jsxs("div",{children:[c.jsxs("div",{className:"sidebar-logo",children:[c.jsx(hy,{className:"sidebar-logo-icon"}),c.jsx("span",{className:"sidebar-logo-text",children:"Local AI Studio"})]}),c.jsxs("div",{className:"nav-list",children:[c.jsxs("div",{className:`nav-item ${f==="generator"?"active":""}`,onClick:()=>b("generator"),children:[c.jsx(iy,{size:20}),c.jsx("span",{children:"Image Generator"})]}),c.jsxs("div",{className:`nav-item ${f==="models"?"active":""}`,onClick:()=>b("models"),children:[c.jsx(ty,{size:20}),c.jsx("span",{children:"Model Manager"})]}),c.jsxs("div",{className:`nav-item ${f==="constraints"?"active":""}`,onClick:()=>b("constraints"),children:[c.jsx(Zs,{size:20}),c.jsx("span",{children:"Image Constraints"})]})]})]}),c.jsxs("div",{className:"sidebar-footer",children:[c.jsxs("div",{className:"sidebar-specs-header",children:[c.jsx(xy,{size:12}),c.jsx("span",{children:"Host Specifications"})]}),c.jsxs("div",{className:"sidebar-specs-item",title:E.cpu_name,children:["CPU: ",E.cpu_name]}),c.jsxs("div",{className:"sidebar-specs-item",title:E.gpu_name,children:["GPU: ",E.gpu_name]}),c.jsxs("div",{className:"sidebar-specs-item",children:["Memory: ",E.ram_total_gb.toFixed(0)," GB RAM (",E.cpu_cores_physical," Cores)"]}),c.jsxs("div",{className:"sidebar-specs-os",children:["OS: ",E.os_name]})]})]})}const My=U.memo(Ty);function Ey({telemetry:f,serverRunning:b,activeModel:E,onStopServer:r,isStoppingServer:_=!1,theme:N,setTheme:G}){const H=A=>{const O=Number(A);return Number.isFinite(O)&&O>0?O.toFixed(O>=10?0:1):"--"},B=()=>b?"Server Active":"Local Mode",y=()=>b?"status-indicator busy":"status-indicator offline";return c.jsxs("div",{className:"top-status-bar",children:[c.jsxs("div",{className:"current-model-info",children:[c.jsx("div",{className:y()}),c.jsx("span",{style:{fontWeight:600,fontSize:"0.95rem"},children:B()}),E&&c.jsxs(c.Fragment,{children:[c.jsx("span",{style:{color:"var(--md-sys-color-outline-variant)"},children:"|"}),c.jsx("span",{style:{color:"var(--md-sys-color-primary)",fontWeight:700},children:E})]})]}),c.jsxs("div",{className:"telemetry-group",children:[c.jsx("button",{className:"theme-toggle-btn",onClick:()=>G(N==="dark"?"light":"dark"),title:`Switch to ${N==="dark"?"light":"dark"} theme`,children:N==="dark"?c.jsx(by,{size:18}):c.jsx(ry,{size:18})}),b&&c.jsxs("button",{className:"m3-btn m3-btn-error",style:{height:"34px",padding:"0 14px"},onClick:r,disabled:_,title:"Stop local model server",children:[_?c.jsx(ea,{className:"progress-spinner",size:14}):c.jsx(Xs,{size:14}),c.jsx("span",{children:_?"Stopping":"Stop Server"})]}),c.jsxs("div",{className:"telemetry-chip",title:"CPU Utilization",children:[c.jsx(om,{className:"telemetry-chip-icon",style:{color:"var(--md-sys-color-primary)"}}),c.jsxs("span",{children:["CPU: ",Number.isFinite(Number(f.cpu_usage))?f.cpu_usage:"--","%"]})]}),c.jsxs("div",{className:"telemetry-chip",title:"System Memory Usage",children:[c.jsx(bu,{className:"telemetry-chip-icon",style:{color:"var(--md-sys-color-secondary)"}}),c.jsxs("span",{children:["RAM: ",H(f.ram_used_gb)," / ",H(f.ram_total_gb)," GB"]})]}),f.vram_total_gb>0&&c.jsxs("div",{className:"telemetry-chip",title:`${f.gpu_name} VRAM`,children:[c.jsx(Ys,{className:"telemetry-chip-icon",style:{color:"var(--md-sys-color-tertiary)"}}),c.jsxs("span",{children:["VRAM: ",H(f.vram_used_gb)," / ",H(f.vram_total_gb)," GB"]})]})]})]})}const Ny=U.memo(Ey),Ay="modulepreload",Dy=function(f){return"/"+f},im={},Cy=function(b,E,r){let _=Promise.resolve();if(E&&E.length>0){let B=function(y){return Promise.all(y.map(A=>Promise.resolve(A).then(O=>({status:"fulfilled",value:O}),O=>({status:"rejected",reason:O}))))};document.getElementsByTagName("link");const G=document.querySelector("meta[property=csp-nonce]"),H=G?.nonce||G?.getAttribute("nonce");_=B(E.map(y=>{if(y=Dy(y),y in im)return;im[y]=!0;const A=y.endsWith(".css"),O=A?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${y}"]${O}`))return;const L=document.createElement("link");if(L.rel=A?"stylesheet":Ay,A||(L.as="script"),L.crossOrigin="",L.href=y,H&&L.setAttribute("nonce",H),document.head.appendChild(L),A)return new Promise((Z,V)=>{L.addEventListener("load",Z),L.addEventListener("error",()=>V(new Error(`Unable to preload CSS for ${y}`)))})}))}function N(G){const H=new Event("vite:preloadError",{cancelable:!0});if(H.payload=G,window.dispatchEvent(H),!H.defaultPrevented)throw G}return _.then(G=>{for(const H of G||[])H.status==="rejected"&&N(H.reason);return b().catch(N)})};function f1(f,b=!1){return window.__TAURI_INTERNALS__.transformCallback(f,b)}async function Sa(f,b={},E){return window.__TAURI_INTERNALS__.invoke(f,b,E)}const la=()=>typeof window<"u"&&window.__TAURI_INTERNALS__!==void 0;let Pl=null,Su=null;const Oy="polish-setup-v1",ta=()=>typeof window<"u"&&(window.location.hostname==="localhost"||window.location.hostname==="127.0.0.1");async function rm(){if(ta())try{const f=await Nl(),b=Number(f?.port);if(Number.isInteger(b)&&b>0)return Su=b,b}catch{}return Su||8080}async function dm(){return`http://127.0.0.1:${await rm()}`}function ai(f){const b=Number(f)||0;if(b<=0)return"0 B";const E=["B","KB","MB","GB","TB"],r=Math.min(E.length-1,Math.floor(Math.log(b)/Math.log(1024)));return`${(b/1024**r).toFixed(r===0?0:1)} ${E[r]}`}function ni(f){return typeof f=="string"?{filename:f,sizeBytes:0,size:"Unknown"}:{filename:f?.filename||f?.name||"",sizeBytes:Number(f?.sizeBytes||0),size:f?.size||(f?.sizeBytes?ai(f.sizeBytes):"Unknown")}}async function sn(f,b="The local server returned an invalid response."){const E=await f.text();let r={};try{r=JSON.parse(E||"{}")}catch{const N=E.trim().startsWith("0&&(Su=Number(G.port)),console.log("Backend restart:",G.message),G.message}catch(_){if(console.warn("Could not reach management API:",_.message),ta())throw _;return"Backend management unavailable"}}async function Vs(){if(la())return await Sa("stop_server");try{await fetch("/api/stop-backend",{method:"POST"})}catch{}return"Backend stopped"}async function Nl(){try{return await(await fetch("/api/backend-status")).json()}catch{return{ready:!1,settings:{}}}}async function Yy(){try{return(await(await fetch("/api/outputs")).json()).outputs||[]}catch{return[]}}async function Xy(f,b){const E=await fetch("/api/save-output",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({image:f,metadata:b})});return(await sn(E,"The local server returned an invalid save response.")).output}async function Qy(f){const b=await fetch("/api/delete-outputs",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({outputs:f})});return await sn(b,"The local server returned an invalid delete response.")}async function ky(){try{return((await(await fetch("/api/models")).json()).models||[]).map(ni)}catch{return[]}}async function Zy(f,b,E,r,_,N,G){console.log("Initiating image generation:",{prompt:f,negativePrompt:b,constraints:E,activeModelName:r});const H=Date.now(),B=await dm(),y={prompt:f,negative_prompt:b||"",width:E.width||512,height:E.height||512,steps:E.steps||20,cfg_scale:E.cfgScale||7,seed:E.seed===-1?Math.floor(Math.random()*1e6):E.seed,sampler:E.sampler||"euler_a",image:null,denoising_strength:E.denoisingStrength||.7},A=async()=>{const L=y.steps;for(let te=1;te<=L;te++){if(G&&G.aborted)throw new DOMException("The user aborted a request.","AbortError");await new Promise(Se=>setTimeout(Se,3e3/L)),N&&N(Math.round(te/L*100))}const Z=f.toLowerCase(),V=Math.abs(y.seed)||Math.floor(Math.random()*1e3);let W="#3B82F6",ue="#8B5CF6",F="",Ce="Abstract Generation";Z.includes("moon")||Z.includes("space")||Z.includes("astronomy")||Z.includes("sky")?(W="#1E293B",ue="#0F172A",Ce="Luminous Moon in Starry Sky",F=` + + + + + + + + + + + + `):Z.includes("cat")||Z.includes("kitten")||Z.includes("feline")?(W="#4F46E5",ue="#7C3AED",Ce="Stylized Cat Portrait",F=` + + + + + + + + + + + + + + + + `):Z.includes("dog")||Z.includes("puppy")||Z.includes("canine")?(W="#D97706",ue="#B45309",Ce="Friendly Dog Portrait",F=` + + + + + + + + + + + + + `):Z.includes("city")||Z.includes("cyberpunk")||Z.includes("tokyo")||Z.includes("neon")?(W="#111827",ue="#311042",Ce="Neon Cyberpunk Skyline",F=` + + + + + + + + + + + + + `):Z.includes("car")||Z.includes("vehicle")||Z.includes("supercar")?(W="#DC2626",ue="#991B1B",Ce="Futuristic Concept Car",F=` + + + + + + + + + + + + + `):(W="#06B6D4",ue="#0891B2",Ce="Abstract Creative Concept",F=` + + + + `);const Te=` + + + + + + + + + + + + + + + + + ${F} + + + + + + + ${Ce} + Seed: ${V} • Steps: ${y.steps} • Scale: ${y.cfg_scale} + + `,Le=`data:image/svg+xml;base64,${btoa(unescape(encodeURIComponent(Te)))}`,Me=parseFloat(((Date.now()-H)/1e3).toFixed(1));return{image:Le,seed:y.seed,duration_sec:Me}},O={prompt:y.prompt,negative_prompt:y.negative_prompt||"",n:1,size:`${y.width}x${y.height}`,response_format:"b64_json",steps:y.steps,cfg_scale:y.cfg_scale,seed:y.seed,sample_method:y.sampler};try{const L=await fetch(`${B}/v1/images/generations`,{method:"POST",headers:{"Content-Type":"application/json"},signal:G,body:JSON.stringify(O)});if(L.ok){const Z=await L.json(),V=Z?.data?.[0]?.b64_json??Z?.images?.[0];if(V){const W=parseFloat(((Date.now()-H)/1e3).toFixed(1));return{image:`data:image/png;base64,${V}`,seed:Z.data?.[0]?.seed??y.seed,duration_sec:W}}}else{let Z=`Generation failed (HTTP ${L.status})`;try{const V=await L.json();(V?.detail||V?.error?.message)&&(Z=V.detail||V.error.message)}catch{}throw new Error(Z)}}catch(L){if(L.name==="AbortError"||L.message.startsWith("Generation failed"))throw L;console.warn("Could not reach local server. Falling back to simulation mode.",L)}return await A()}async function Vy(f,b,E){if(f instanceof File){const H=f;if(!ta())throw new Error("File import requires the local image generator server.");return await Ky(H,b,E),{response:"Model imported successfully"}}if(la()){const{listen:H}=await Cy(async()=>{const{listen:y}=await import("./event-DtK1umGE.js");return{listen:y}},[]);let B=null;b&&(B=await H("import-progress",y=>{b(y.payload)}));try{return{response:await Sa("import_model_file",{sourcePath:f}),unlisten:B}}catch(y){throw B&&B(),y}}const r=f.split(/[\\/]/).pop()||"imported_model.gguf";console.log(`Web Mode: Simulating copying ${r} to USB models folder`);const _=40;for(let H=1;H<=_;H++){if(E?.aborted)throw new DOMException("The user aborted a request.","AbortError");await new Promise(O=>setTimeout(O,150));const B=H/_*100,y=40+Math.sin(H)*5+Math.random()*2,A=(_-H)*.15;b&&b({filename:r,progress:B,speed_mb_s:y,eta_secs:A,status:"Copying to USB..."})}const N=localStorage.getItem("imported-models"),G=N?JSON.parse(N):[];return G.includes(r)||(G.push({filename:r,sizeBytes:0,size:"Unknown"}),localStorage.setItem("imported-models",JSON.stringify(G))),{response:"Model imported successfully"}}function Ky(f,b,E){return new Promise((r,_)=>{const N=new XMLHttpRequest,G=Date.now();let H=!1;N.open("POST",`/api/import-model?filename=${encodeURIComponent(f.name)}`),N.setRequestHeader("Content-Type","application/octet-stream");const B=()=>{H=!0,N.abort()};E&&(E.aborted?B():E.addEventListener("abort",B,{once:!0})),N.upload.onprogress=y=>{if(!y.lengthComputable||!b)return;const A=Math.max(.1,(Date.now()-G)/1e3),O=y.loaded/A,L=Math.max(0,y.total-y.loaded);b({filename:f.name,progress:y.loaded/y.total*100,speed_mb_s:O/(1024*1024),eta_secs:L/Math.max(1,O),status:"Copying to models folder..."})},N.onload=()=>{let y={};try{y=JSON.parse(N.responseText||"{}")}catch{}N.status>=200&&N.status<300&&y.ok!==!1?(b&&b({filename:f.name,progress:100,speed_mb_s:0,eta_secs:0,status:"Import complete"}),r(y)):_(new Error(y.error||`Import failed (HTTP ${N.status})`))},N.onerror=()=>_(new Error("Import failed while uploading the file.")),N.onabort=()=>_(new DOMException(H?"Import cancelled by user.":"Import aborted.","AbortError")),N.send(f)})}async function Jy(f){if(la())return await Sa("delete_model_file",{filename:f});if(typeof window<"u"&&(window.location.hostname==="localhost"||window.location.hostname==="127.0.0.1"))try{const _=await fetch("/api/delete-model",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({filename:f})}),N=await _.json();if(!_.ok)throw new Error(N.error||"Failed to delete model file");return N}catch(_){throw console.error("Failed to delete model via local API:",_),_}const E=localStorage.getItem("imported-models");let r=E?JSON.parse(E):[];return r=r.filter(_=>ni(_).filename!==f),localStorage.setItem("imported-models",JSON.stringify(r)),`Simulated deletion of ${f} from browser session`}async function mm(){const f=await dm();try{return(await fetch(`${f}/v1/models`,{method:"GET"})).ok}catch{return!1}}async function $y(f=30){const b=la()||ta()?f:3;for(let E=0;EsetTimeout(_,500))}return!1}async function Wy(f){try{return await(await fetch("/api/download-model",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({url:f})})).json()}catch(b){return console.error("Failed to start model download:",b),{ok:!1,error:b.message}}}async function Fy(){try{return await(await fetch("/api/cancel-download",{method:"POST"})).json()}catch(f){return console.error("Failed to cancel model download:",f),{ok:!1,error:f.message}}}async function um(){try{return await(await fetch("/api/download-progress")).json()}catch(f){return console.error("Failed to get download progress:",f),{active:!1,error:f.message}}}async function Iy(){try{return await(await fetch("/api/generation-progress")).json()}catch(f){return console.error("Failed to get generation progress:",f),{active:!1,error:f.message}}}const Py=U.memo(({img:f,idx:b,isSelected:E,onClick:r})=>{const _=N=>{r(b,N)};return c.jsxs("div",{className:`gallery-item ${E?"selected":""}`,onClick:_,title:`Prompt: ${f.prompt} +Seed: ${f.seed}${f.duration_sec?` +Time: ${f.duration_sec.toFixed(1)}s`:""}`,children:[c.jsx("img",{src:f.url,className:"gallery-thumb",alt:"Thumbnail",loading:"lazy",decoding:"async"}),E&&c.jsx("div",{className:"gallery-select-badge",children:c.jsx(Ls,{size:14})})]})});function e1({prompt:f,setPrompt:b,negativePrompt:E,setNegativePrompt:r,constraints:_,setConstraints:N,activeModel:G,generatedImages:H,setGeneratedImages:B,isGenerating:y,setIsGenerating:A,generationProgress:O,setGenerationProgress:L,setActiveTab:Z,showAlert:V=async({message:ue})=>window.alert(ue),showConfirm:W=async({message:ue})=>window.confirm(ue)}){const[ue,F]=U.useState(null),[Ce,Te]=U.useState(null),[Qe,Le]=U.useState(null),[Me,te]=U.useState(!1),[Se,ft]=U.useState(0),[_t,ye]=U.useState(0),[Ve,nt]=U.useState(0),[Ke,Ye]=U.useState(""),[x,C]=U.useState(!1),[K,ge]=U.useState(!1),[re,d]=U.useState(!1),[j,w]=U.useState(null),[q,J]=U.useState(null),[ae,de]=U.useState(!1),[ke,Ee]=U.useState([]),it=U.useRef(null),ot=U.useRef(null),ht=U.useRef(!1),cl=async()=>{if(!f.trim())return;J(null),d(!0),w(null);let Y=!1;try{const ne=await Nl();if(ne&&ne.settings){const fe=ne.settings,pe=fe.model?fe.model.split(/[\\/]/).pop():null,Ne=G?G.split(/[\\/]/).pop():null;(pe!==Ne||parseInt(fe.steps)!==parseInt(_.steps)||Math.abs(parseFloat(fe.cfgScale)-parseFloat(_.cfgScale))>.05||fe.sampler!==_.sampler||parseInt(fe.threads)!==parseInt(_.threads)||!!fe.useGpu!=(_.useGpu!==!1)||(fe.backendType||(fe.useGpu===!1?"cpu":"auto"))!==(_.backendType||(_.useGpu===!1?"cpu":"auto")))&&(Y=!0)}else Y=!0}catch{Y=!0}if(Y)try{console.log("Settings out of sync, restarting backend..."),await Qs(G,_);let ne=!1,fe=null;for(let pe=0;pe<240;pe++){const Ne=await Nl();if(Ne.loading&&w({progress:Ne.loading.progress||0,phase:Ne.loading.phase||"Loading model...",speed:Ne.loading.speed||"",current:Ne.loading.current||0,total:Ne.loading.total||0,backendMode:Ne.loading.backendMode||Ne.settings?.backendMode||"",device:Ne.loading.device||Ne.settings?.backendDevice||""}),Ne.ready){ne=!0;break}if(Ne.error){fe=Ne.error;break}if(!Ne.running&&pe>3){fe="The backend process terminated immediately on startup.";break}await new Promise(ct=>setTimeout(ct,500))}if(!ne)throw new Error(fe||"Backend server failed to start after applying configuration changes.")}catch(ne){console.error("Failed to restart backend:",ne),J(ne.message||"Failed to sync settings with backend."),d(!1);return}d(!1),w(null),it.current&&clearInterval(it.current),A(!0),L(0),ft(0),nt(0),Ye(""),ht.current=!1,C(!1),de(!1),Le(null),F(null);const le=(_.width>=1024?140:35)*.04,He=_.width>=1024?140:35,Pe=(_.backendType||(_.useGpu===!1?"cpu":"auto"))!=="cpu";let jt=Pe?le:He,ll=!1,xa=0,_a=0,We=0;ye(Math.round(_.steps*jt)),it.current=setInterval(async()=>{We++,ft(We);try{const ne=await Iy();if(ne&&ne.active){const fe=ne.decoding||!1;de(fe);const pe=fe?ne.steps||_.steps||20:ne.step||0,Ne=ne.steps||_.steps||20,ct=fe?"":ne.speed||"";(fe||ne.steps>0)&&(ht.current=!0,nt(pe)),Ye(fe?"decoding":ct);let Re=0;fe?Re=99:Ne>0&&(Re=Math.round(pe/Ne*100)),Re=Math.min(99,Re),fe||ne.steps>0?L(Re):L(St=>Math.max(St,Re));let rt=0;if(fe)rt=3;else{const St=parseFloat(ct);if(!isNaN(St)&&St>0){const wt=Math.max(0,Ne-pe);ct.includes("it/s")?rt=wt/St:ct.includes("s/it")&&(rt=wt*St)}else{const wt=Pe?le:He;rt=Math.max(0,(Ne-pe)*wt)}}if(Pe&&!ll){const St=ct.includes("it/s")&&numericSpeed<.2,wt=ct.includes("s/it")&&numericSpeed>5;(St||wt)&&(ll=!0,C(!0))}ye(Math.round(rt))}else L(fe=>Math.min(15,fe+1)),ye(fe=>Math.max(1,fe-1))}catch(ne){console.warn("Failed to get generation progress, running simulation fallback:",ne),Pe&&!ll&&We>_.steps*le*1.3&&(ll=!0,C(!0),jt=He,xa=We,_a=Math.min(95,Math.round(We/(_.steps*le)*100)));let fe=Math.min(_.steps-1,Math.floor(We/jt)),pe=_.steps*jt;if(We>=pe){const Re=Math.ceil(We/Math.max(.5,fe));jt=Math.max(jt+15,Re+15),pe=_.steps*jt,fe=Math.min(_.steps-1,Math.floor(We/jt))}const Ne=Math.max(1,pe-We);ye(Math.round(Ne));let ct=0;if(ll){const Re=99-_a,rt=pe-xa;if(rt>0){const St=Math.min(1,(We-xa)/rt);if(St<.85)ct=Math.round(_a+St*Re);else{const wt=(We-(xa+rt*.85))/(jt*2),fl=1-Math.exp(-wt);ct=Math.min(99,Math.round(_a+.85*Re+.14*Re*fl))}}else ct=99}else if(WeMath.max(Re,ct))}},1e3);try{ot.current=new AbortController;const ne=await Zy(f,E,_,G,null,Re=>L(rt=>Math.max(rt,Re)),ot.current.signal);it.current&&clearInterval(it.current),L(100),nt(_.steps),ye(0),Ye("");const fe={prompt:f,negativePrompt:E,seed:ne.seed,steps:_.steps,cfgScale:_.cfgScale,width:_.width,height:_.height,sampler:_.sampler,model:G,duration_sec:ne.duration_sec,timestamp:new Date().toLocaleTimeString()};let pe=null,Ne=null;try{if(pe=await Xy(ne.image,fe),Ne=pe.url,!Ne)throw new Error("The local server saved the image but did not return a file URL.")}catch(Re){throw console.error("Generated image could not be saved:",Re),new Error(`Image generated but could not be saved to USB: ${Re.message||Re}`)}F(Ne),Te(ne.seed),Le(ne.duration_sec);const ct={...fe,...pe||{},url:Ne};B(Re=>[ct,...Re])}catch(ne){ne.name==="AbortError"?console.log("Generation request was aborted by the user"):(console.error("Generation failed:",ne),J(ne.message||"Generation failed. Please try again.")),it.current&&clearInterval(it.current)}finally{A(!1),ot.current=null}},Ut=async()=>{if(await W({title:"Stop Generation?",message:"The current image generation will be cancelled and the local model server may restart.",confirmLabel:"Stop",danger:!0})){it.current&&clearInterval(it.current),ge(!0),ot.current&&ot.current.abort();try{console.log("Cancelling: Stopping server to kill generation threads..."),await Vs(),nt(0),Ye(""),de(!1),ht.current=!1,G&&(console.log("Cancelling: Restarting server for future generations..."),await Qs(G,_),await $y()||console.warn("Server failed to restart properly."))}catch(Y){console.error("Failed to restart server on cancellation:",Y)}finally{ge(!1),A(!1),L(0),ye(0)}}},k=async()=>{if(ue)try{if(ue.startsWith("data:image")){const le=await(await fetch(ue)).blob();await navigator.clipboard.write([new ClipboardItem({[le.type]:le})])}else{const Y=new Image;Y.crossOrigin="anonymous",Y.src=ue,Y.onload=async()=>{const le=document.createElement("canvas");le.width=Y.width,le.height=Y.height,le.getContext("2d").drawImage(Y,0,0),le.toBlob(async Pe=>{await navigator.clipboard.write([new ClipboardItem({[Pe.type]:Pe})])},"image/png")}}te(!0),setTimeout(()=>te(!1),2e3)}catch(Y){console.error("Failed to copy image:",Y)}},se=()=>{if(!ue)return;const Y=document.createElement("a");Y.href=ue,Y.download=`diffusion-${Ce||Date.now()}.png`,document.body.appendChild(Y),Y.click(),document.body.removeChild(Y)},D=(Y,le=`diffusion-${Date.now()}.png`)=>{if(!Y)return;const He=document.createElement("a");He.href=Y,He.download=le,document.body.appendChild(He),He.click(),document.body.removeChild(He)},R=U.useCallback(Y=>{b(Y.prompt),r(Y.negativePrompt),N(le=>({...le,steps:Y.steps,cfgScale:Y.cfgScale,width:Y.width,height:Y.height,sampler:Y.sampler,seed:Y.seed})),F(Y.url),Te(Y.seed),Le(Y.duration_sec??Y.durationSec??null)},[b,r,N]),I=U.useCallback((Y,le)=>{const He=le.ctrlKey||le.metaKey||le.shiftKey;Ee(Pe=>He?Pe.includes(Y)?Pe.filter(jt=>jt!==Y):[...Pe,Y]:[Y]),H[Y]&&R(H[Y])},[H,R]),P=ke.map(Y=>H[Y]).filter(Boolean),Tt=()=>{Ee([])},It=()=>{P[0]&&R(P[0])},sl=()=>{P.forEach((Y,le)=>{const He=Y.seed??Date.now();D(Y.url,`diffusion-${He}-${le+1}.png`)})},ut=async()=>{if(P.length===0)return;const Y=P.length;if(await W({title:"Delete Selected Outputs?",message:`Delete ${Y} selected output${Y===1?"":"s"} from USB? This removes the image and metadata files.`,confirmLabel:"Delete",danger:!0}))try{await Qy(P);const He=new Set(ke);B(Pe=>Pe.filter((jt,ll)=>!He.has(ll))),Ee([]),P.some(Pe=>Pe.url===ue)&&(F(null),Te(null),Le(null))}catch(He){console.error("Failed to delete selected outputs:",He),V({title:"Delete Failed",message:He.message||String(He),danger:!0})}};return c.jsxs("div",{className:"workspace-area",children:[c.jsxs("div",{className:"workspace-title-section",children:[c.jsx("h2",{className:"workspace-title",children:"Generator Dashboard"}),c.jsx("p",{className:"workspace-subtitle",children:"Create high-fidelity images completely locally on your external drive."})]}),c.jsxs("div",{className:"generator-layout",children:[c.jsx("div",{children:c.jsxs("div",{className:"m3-card",children:[c.jsxs("h3",{className:"m3-card-title",children:[c.jsx(vu,{size:18,style:{color:"var(--md-sys-color-primary)"}}),"Generation Workspace"]}),c.jsxs("div",{className:"m3-field-group",children:[c.jsxs("div",{className:"m3-text-field",children:[c.jsx("label",{className:"m3-text-field-label",children:"Positive Prompt"}),c.jsx("textarea",{className:"m3-textarea",value:f,onChange:Y=>b(Y.target.value),placeholder:"Enter a descriptive prompt (e.g. 'A futuristic city in cyberpunk aesthetic, high details, cinematic lighting')...",disabled:y})]}),c.jsxs("div",{className:"m3-text-field",children:[c.jsx("label",{className:"m3-text-field-label",children:"Negative Prompt (Optional)"}),c.jsx("input",{type:"text",className:"m3-input",value:E,onChange:Y=>r(Y.target.value),placeholder:"Items to avoid (e.g. 'blurry, low quality, deformed hands, texts')...",disabled:y})]}),c.jsxs("div",{className:"m3-text-field",children:[c.jsx("label",{className:"m3-text-field-label",children:"Active Image Constraints"}),c.jsxs("div",{className:"chips-container",children:[c.jsxs("div",{className:"status-chip",onClick:()=>Z("constraints"),children:[c.jsx(Zs,{size:14}),c.jsxs("span",{children:["Resolution: ",_.width,"x",_.height]})]}),c.jsxs("div",{className:"status-chip",onClick:()=>Z("constraints"),children:[c.jsx(ea,{size:14}),c.jsxs("span",{children:["Steps: ",_.steps]})]}),c.jsxs("div",{className:"status-chip",onClick:()=>Z("constraints"),children:[c.jsx(vu,{size:14}),c.jsxs("span",{children:["Sampler: ",_.sampler]})]}),c.jsx("div",{className:"status-chip",onClick:()=>Z("constraints"),children:c.jsxs("span",{children:["Seed: ",_.seed===-1?"Random":_.seed]})})]})]}),c.jsxs("button",{className:"m3-btn m3-btn-filled",style:{height:"48px",marginTop:"8px"},onClick:cl,disabled:y||!f.trim()||!G,children:[c.jsx(vu,{size:18}),c.jsx("span",{children:G?"Generate Local Image":"Select Model to Generate"})]})]})]})}),c.jsxs("div",{className:"m3-card output-panel",children:[c.jsx("div",{className:"output-image-container",children:y||K||re?c.jsx("div",{className:"progress-overlay",children:re?c.jsxs("div",{style:{display:"flex",flexDirection:"column",alignItems:"center",gap:"16px",padding:"20px"},children:[c.jsx("div",{className:"progress-spinner"}),c.jsx("div",{className:"progress-text",style:{fontSize:"1.1rem",fontWeight:700,textAlign:"center"},children:"Syncing Settings & Initializing..."}),j?c.jsxs("div",{style:{width:"min(360px, 90%)"},children:[c.jsxs("div",{style:{display:"flex",justifyContent:"space-between",gap:"12px",fontSize:"0.82rem",fontWeight:700,marginBottom:"6px"},children:[c.jsxs("span",{children:[j.phase,j.speed?` (${j.speed})`:""]}),c.jsx("span",{children:j.total>0?`Loaded ${j.current} / ${j.total} tensors`:`${Math.round(j.progress)}%`})]}),c.jsx("div",{className:"progress-bar-container",style:{margin:0},children:c.jsx("div",{className:"progress-bar-fill",style:{width:`${Math.min(100,Math.max(0,j.progress))}%`,transition:"width 0.25s ease"}})}),(j.backendMode||j.device)&&c.jsxs("div",{style:{fontSize:"0.78rem",opacity:.8,textAlign:"center",marginTop:"8px"},children:["Loading on ",j.backendMode||"backend",j.device?` • ${j.device}`:""]})]}):c.jsx("p",{style:{fontSize:"0.85rem",opacity:.8,textAlign:"center",maxWidth:"280px",margin:0},children:"Adjusting inference settings and restarting the local model server."})]}):K?c.jsxs("div",{style:{display:"flex",flexDirection:"column",alignItems:"center",gap:"16px",padding:"20px"},children:[c.jsx("div",{className:"progress-spinner"}),c.jsx("div",{className:"progress-text",style:{fontSize:"1.1rem",fontWeight:700,textAlign:"center"},children:"Cancelling Generation..."}),c.jsx("p",{style:{fontSize:"0.85rem",opacity:.8,textAlign:"center",maxWidth:"280px",margin:0},children:"Stopping CPU/GPU execution threads and reloading model weights. Please wait a moment."})]}):c.jsxs(c.Fragment,{children:[c.jsx("div",{className:"progress-spinner"}),c.jsx("div",{className:"progress-text",style:{fontSize:"1.1rem",fontWeight:700},children:ae?"Decoding Latents...":"Generating Locally..."}),x&&c.jsx("div",{style:{fontSize:"0.8rem",color:"var(--md-sys-color-primary)",fontWeight:600,background:"var(--md-sys-color-primary-container)",padding:"4px 12px",borderRadius:"12px",margin:"4px 0 8px 0",animation:"pulse 2s infinite"},children:"⚠️ CPU Fallback Detected (Running Slower)"}),c.jsxs("div",{style:{display:"grid",gridTemplateColumns:"1fr 1fr",gap:"16px",width:"80%",margin:"8px 0 0 0",fontSize:"0.85rem",opacity:.9},children:[c.jsxs("div",{style:{textAlign:"left"},children:[c.jsx("strong",{children:"Step:"})," ",Ve," / ",_.steps," (",Math.max(0,_.steps-Ve)," left)"]}),c.jsxs("div",{style:{textAlign:"right"},children:[c.jsx("strong",{children:"Elapsed:"})," ",Se,"s",Ke&&` (${Ke==="decoding"?"decoding":Ke})`]})]}),c.jsx("div",{className:"progress-bar-container",style:{margin:"4px 0 10px 0"},children:c.jsx("div",{className:"progress-bar-fill",style:{width:`${O}%`,transition:"width 1s linear"}})}),c.jsxs("div",{style:{fontSize:"0.85rem",opacity:.8,display:"flex",gap:"8px",alignItems:"center"},children:[c.jsxs("span",{children:["Progress: ",O,"%"]}),c.jsx("span",{children:"•"}),c.jsxs("span",{children:["Est. remaining: ",_t,"s"]})]}),c.jsx("button",{className:"m3-btn m3-btn-error",style:{marginTop:"16px",height:"36px",padding:"0 24px"},onClick:Ut,children:"Stop Generating"})]})}):ue?c.jsx("img",{src:ue,className:"output-image",alt:"Generated Output"}):q?c.jsxs("div",{style:{textAlign:"center",padding:"24px",color:"var(--md-sys-color-error)",display:"flex",flexDirection:"column",alignItems:"center",gap:"16px"},children:[c.jsx("div",{style:{background:"rgba(239, 68, 68, 0.1)",padding:"16px",borderRadius:"50%",display:"flex",alignItems:"center",justifyContent:"center"},children:c.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",width:"48",height:"48",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:"2",children:c.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"})})}),c.jsx("h3",{style:{margin:0,fontSize:"1.2rem",fontWeight:"bold"},children:"Generation Failed"}),c.jsx("p",{style:{margin:0,fontSize:"0.95rem",opacity:.9,maxWidth:"320px",lineHeight:"1.4"},children:q}),c.jsxs("div",{style:{marginTop:"8px",fontSize:"0.85rem",opacity:.8,color:"var(--md-sys-color-on-surface-variant)"},children:["Hint: Try lowering the resolution in the ",c.jsx("strong",{children:"Image Constraints"})," settings (e.g., to 512x512)."]})]}):c.jsxs("div",{style:{textAlign:"center"},children:[c.jsx(vu,{className:"output-placeholder-icon"}),c.jsxs("p",{className:"output-placeholder-text",children:["Your generated image will appear here.",c.jsx("br",{}),"Enter a prompt on the left and click Generate."]})]})}),ue&&!y&&c.jsxs(c.Fragment,{children:[c.jsxs("div",{style:{width:"100%",display:"flex",justifyContent:"space-between",marginTop:"12px",fontSize:"0.8rem",color:"var(--md-sys-color-outline)"},children:[c.jsxs("span",{children:["Seed: ",Ce]}),Qe&&c.jsxs("span",{children:["Inference Time: ",Qe.toFixed(1),"s"]})]}),c.jsxs("div",{className:"image-actions",children:[c.jsxs("button",{className:"m3-btn m3-btn-tonal",onClick:k,children:[Me?c.jsx(Ls,{size:16}):c.jsx(J0,{size:16}),c.jsx("span",{children:Me?"Copied":"Copy"})]}),c.jsxs("button",{className:"m3-btn m3-btn-outlined",onClick:se,children:[c.jsx(am,{size:16}),c.jsx("span",{children:"Save to USB"})]})]})]})]})]}),c.jsxs("div",{className:"gallery-section",children:[c.jsxs("div",{className:"gallery-header",children:[c.jsx("h3",{className:"m3-card-title",style:{marginBottom:0},children:"Recent Outputs Gallery"}),P.length>0&&c.jsxs("div",{className:"gallery-selection-actions",children:[c.jsxs("span",{className:"gallery-selection-count",children:[P.length," selected"]}),c.jsxs("button",{className:"m3-btn m3-btn-tonal",onClick:It,children:[c.jsx(Ls,{size:14}),c.jsx("span",{children:"Use"})]}),c.jsxs("button",{className:"m3-btn m3-btn-outlined",onClick:sl,children:[c.jsx(am,{size:14}),c.jsx("span",{children:"Download"})]}),c.jsxs("button",{className:"m3-btn m3-btn-error",onClick:ut,children:[c.jsx(li,{size:14}),c.jsx("span",{children:"Delete"})]}),c.jsx("button",{className:"m3-btn m3-btn-outlined",onClick:Tt,children:"Clear"})]})]}),H.length===0?c.jsx("div",{className:"m3-card gallery-empty",children:"No images generated in this session yet. Everything will be saved directly on your external drive."}):c.jsxs(c.Fragment,{children:[c.jsx("div",{className:"gallery-hint",children:"Click to select one image. Ctrl-click or Shift-click to select multiple."}),c.jsx("div",{className:"gallery-grid",children:H.map((Y,le)=>c.jsx(Py,{img:Y,idx:le,isSelected:ke.includes(le),onClick:I},Y.image||le))})]})]})]})}const t1=U.memo(e1),l1=[{group:"SDXL - Best Quality",items:[{name:"Juggernaut XL v9 Lightning",filename:"Juggernaut_RunDiffusionPhoto2_Lightning_4Steps.safetensors",format:"Safetensors",approxSize:"6.6 GB",resolution:"1024x1024",notes:"Photorealistic SDXL model tuned for 4-8 step Lightning generation.",url:"https://huggingface.co/RunDiffusion/Juggernaut-XL-Lightning/resolve/main/Juggernaut_RunDiffusionPhoto2_Lightning_4Steps.safetensors"},{name:"DreamShaper XL Lightning",filename:"DreamShaperXL_Lightning.safetensors",format:"Safetensors",approxSize:"6.6 GB",resolution:"1024x1024",notes:"All-around SDXL model for fantasy art, renders, illustration, and stylized images.",url:"https://huggingface.co/Lykon/dreamshaper-xl-lightning/resolve/main/DreamShaperXL_Lightning.safetensors"},{name:"SDXL Base 1.0 Q4_0 GGUF",filename:"stable-diffusion-xl-base-1.0-Q4_0.gguf",format:"GGUF",approxSize:"3.8 GB",resolution:"1024x1024",notes:"Quantized SDXL base model for lower VRAM or CPU-friendly generation.",url:"https://huggingface.co/hum-ma/SDXL-models-GGUF/resolve/7e15380138e7069ca3aaef5bf0401c3406e3a593/stable-diffusion-xl-base-1.0-Q4_0.gguf"}]},{group:"SD 1.5 - Ultra Fast / Low VRAM",items:[{name:"DreamShaper 8",filename:"DreamShaper_8_pruned.safetensors",format:"Safetensors",approxSize:"2.1 GB",resolution:"512x512",notes:"General-purpose SD 1.5 model for illustration, anime, and semi-realistic portraits.",url:"https://huggingface.co/Lykon/DreamShaper/resolve/main/DreamShaper_8_pruned.safetensors"},{name:"CyberRealistic V8",filename:"CyberRealistic_V8_FP16.safetensors",format:"Safetensors",approxSize:"2.1 GB",resolution:"512x512",notes:"High-fidelity realism and photorealism in the SD 1.5 ecosystem.",url:"https://huggingface.co/cyberdelia/CyberRealistic/resolve/main/CyberRealistic_V8_FP16.safetensors"},{name:"ReV Animated v1.2.2",filename:"rev-animated-v1-2-2.safetensors",format:"Safetensors",approxSize:"2.1 GB",resolution:"512x512",notes:"Semi-realistic, 2.5D, anime, fantasy, and stylized digital art.",url:"https://huggingface.co/danbrown/RevAnimated-v1-2-2/resolve/main/rev-animated-v1-2-2.safetensors"}]}];function a1({activeModel:f,setActiveModel:b,serverRunning:E,setServerRunning:r,constraints:_,showAlert:N=async({message:H})=>window.alert(H),showConfirm:G=async({message:H})=>window.confirm(H)}){const[H,B]=U.useState([]),[y,A]=U.useState(null),[O,L]=U.useState(0),[Z,V]=U.useState(""),[W,ue]=U.useState(null),[F,Ce]=U.useState(null),[Te,Qe]=U.useState(null),[Le,Me]=U.useState({filename:"",speed:"0.0",eta:0,status:""}),[te,Se]=U.useState(""),[ft,_t]=U.useState(null),[ye,Ve]=U.useState(!1),[nt,Ke]=U.useState({progress:0,phase:""}),[Ye,x]=U.useState(null),[C,K]=U.useState({backendMode:"",backendBinary:"",backendDevice:""}),ge=H.map(D=>ni(D).filename),re=W!==null||ye;U.useEffect(()=>{w(),d()},[]),U.useEffect(()=>{if(!E&&!W){K({backendMode:"",backendBinary:"",backendDevice:""});return}let D=!1;const R=async()=>{try{const P=await Nl();if(D)return;K({backendMode:P.settings?.backendMode||P.loading?.backendMode||"",backendBinary:P.settings?.backendBinary||P.loading?.backendBinary||"",backendDevice:P.settings?.backendDevice||P.loading?.device||""})}catch{}};R();const I=setInterval(R,2e3);return()=>{D=!0,clearInterval(I)}},[E,W]);const d=async()=>{try{const D=await um();D.active&&D.filename&&j(D.filename)}catch(D){console.error("Check active download failed:",D)}},j=D=>{A(D);const R=setInterval(async()=>{try{const I=await um();I.active?(L(I.progress===-1?0:I.progress),V(`${I.speed} • ETA ${I.eta}s`)):(clearInterval(R),A(null),I.error?String(I.error).toLowerCase().includes("cancelled")||N({title:"Download Failed",message:I.error,danger:!0}):w())}catch(I){console.error("Polling error:",I)}},1e3)},w=async()=>{try{const D=await Ly();B(D.map(ni).filter(R=>R.filename))}catch(D){console.error(D)}},q=async(D,R)=>{if(y||ge.includes(R)&&!await G({title:"Overwrite Model?",message:`"${R}" is already downloaded. Do you want to download and overwrite it?`,confirmLabel:"Overwrite"}))return;const I=typeof window<"u"&&window.__TAURI_INTERNALS__!==void 0,P=typeof window<"u"&&(window.location.hostname==="localhost"||window.location.hostname==="127.0.0.1");if(!I&&!P){N({title:"Server Required",message:"Model download requires the local image generator server.",danger:!0});return}try{const Tt=await Wy(D);Tt.ok?j(R):N({title:"Download Failed",message:Tt.error||"Unknown error",danger:!0})}catch(Tt){N({title:"Download Error",message:Tt.message,danger:!0})}},J=async D=>{if(D.preventDefault(),!te.trim())return;let R="model.gguf";try{const I=new URL(te.trim());if(I.protocol!=="http:"&&I.protocol!=="https:")throw new Error("URL protocol must be http or https");if(R=I.pathname.split("/").pop()||"",!R)throw new Error("Could not extract filename from URL");const P=R.toLowerCase();if(!P.endsWith(".gguf")&&!P.endsWith(".safetensors")&&!P.endsWith(".ckpt"))throw new Error("URL must point to a .gguf, .safetensors, or .ckpt weights file")}catch(I){N({title:"Invalid URL",message:I.message,danger:!0});return}await q(te.trim(),R),Se("")},ae=D=>{q(D.url,D.filename)},de=async()=>{await Fy(),A(null),L(0),V(""),await w()},ke=async D=>{if(f&&f!==D&&E){x(D);return}await Ee(D)},Ee=async D=>{const R=typeof window<"u"&&window.__TAURI_INTERNALS__!==void 0,I=typeof window<"u"&&(window.location.hostname==="localhost"||window.location.hostname==="127.0.0.1"),Tt=(await Nl())?.port||8080;if(!R&&!I){const It=await mm(),sl=`.\\backend\\win\\vulkan\\sd-vulkan.exe --listen-port ${Tt} --model .\\models\\${D} --threads 8`;It?await G({title:"Web Browser Mode",message:`To load "${D}" on the active GPU server, restart your terminal backend with: + +${sl} + +Update the UI status anyway?`,confirmLabel:"Update UI"})&&(b(D),r(!0)):await G({title:"Backend Not Running",message:`C++ backend server is not running on port ${Tt}. + +To run locally, start: + +${sl} + +Proceed in Simulation Mode instead?`,confirmLabel:"Proceed"})&&(b(D),r(!1));return}ue(D),Ce({progress:0,phase:"Starting backend...",speed:"",current:0,total:0,model:D,backendMode:"",backendBinary:"",device:""});try{const It=await Qs(D,_);console.log(It);let sl=!1,ut=null;for(let Y=0;Y<240;Y++){const le=await Nl();if(le.loading&&Ce({progress:le.loading.progress||0,phase:le.loading.phase||"Loading model...",speed:le.loading.speed||"",current:le.loading.current||0,total:le.loading.total||0,model:le.loading.model||D,backendMode:le.loading.backendMode||le.settings?.backendMode||"",backendBinary:le.loading.backendBinary||le.settings?.backendBinary||"",device:le.loading.device||le.settings?.backendDevice||""}),le.ready){sl=!0;break}if(le.error){ut=le.error;break}if(!le.running&&Y>3){ut="The backend process terminated immediately on startup.";break}await new Promise(He=>setTimeout(He,500))}if(sl)Ce(Y=>({...Y||{},progress:100,phase:"Model ready",speed:"",current:Y?.current||0,total:Y?.total||0,model:D})),b(D),r(!0);else throw new Error(ut||`Model server failed to respond on port ${Tt}.`)}catch(It){console.error("Failed to load model:",It),N({title:"Model Load Failed",message:It.message||String(It),danger:!0})}finally{setTimeout(()=>Ce(null),800),ue(null)}},it=async()=>{const D=Ye;x(null),await ot(),D&&await Ee(D)},ot=async()=>{if(ye)return;Ve(!0),Ke({progress:10,phase:"Stopping backend process..."});const D=setInterval(async()=>{try{const R=await Nl();R.unloading?.active?Ke({progress:R.unloading.progress||50,phase:R.unloading.phase||"Unloading model..."}):Ke(I=>({progress:Math.min(95,I.progress+10),phase:I.phase||"Unloading model..."}))}catch{}},300);try{await Vs(),Ke({progress:100,phase:"Model unloaded"}),b(null),x(null),r(!1)}catch(R){console.error(R),N({title:"Unload Failed",message:R.message||String(R),danger:!0})}finally{clearInterval(D),setTimeout(()=>{Ve(!1),Ke({progress:0,phase:""})},500)}},ht=async D=>{if(await G({title:"Delete Model?",message:`Delete "${D}" from your drive?`,confirmLabel:"Delete",danger:!0}))try{await Jy(D),await w(),f===D&&await ot()}catch(R){console.error("Failed to delete model:",R),N({title:"Delete Failed",message:R.message||String(R),danger:!0})}},cl=async(D,R)=>{const I=new AbortController;_t(I),Qe(0),Me({filename:R,speed:"0.0",eta:0,status:"Initiating file copy..."});try{await Vy(D,P=>{Qe(Math.round(P.progress)),Me({filename:P.filename,speed:P.speed_mb_s.toFixed(1),eta:Math.round(P.eta_secs),status:P.status})},I.signal),await w()}catch(P){console.error("Import failed:",P),P.name!=="AbortError"&&N({title:"Import Failed",message:P.message||String(P),danger:!0})}finally{Qe(null),_t(null)}},Ut=()=>{ft&&ft.abort()},k=D=>{const R=D.target.files[0];R&&cl(R,R.name),D.target.value=""},se=!!y;return c.jsxs("div",{className:"workspace-area",children:[c.jsxs("div",{className:"workspace-title-section",children:[c.jsx("h2",{className:"workspace-title",children:"Model Manager"}),c.jsx("p",{className:"workspace-subtitle",children:"Manage local files and download recommended weights directly to your local models folder."})]}),f&&c.jsx("div",{className:"m3-card",style:{borderLeft:"4px solid var(--md-sys-color-primary)",background:"var(--md-sys-color-primary-container)",color:"var(--md-sys-color-on-primary-container)"},children:c.jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center"},children:[c.jsxs("div",{children:[c.jsxs("h4",{style:{fontWeight:700},children:["Active Model: ",f]}),c.jsx("p",{style:{fontSize:"0.85rem",marginTop:"2px",opacity:.9},children:"The local C++ stable-diffusion server is running. Real-time telemetry is displaying performance status in the top bar."}),(C.backendMode||C.backendDevice||C.backendBinary)&&c.jsxs("div",{style:{display:"flex",flexWrap:"wrap",gap:"8px",marginTop:"10px"},children:[C.backendMode&&c.jsxs("span",{className:"status-chip",style:{cursor:"default"},children:[c.jsx(bu,{size:14}),c.jsxs("span",{children:["Loaded on ",C.backendMode]})]}),C.backendDevice&&c.jsx("span",{className:"status-chip",style:{cursor:"default"},children:c.jsx("span",{children:C.backendDevice})}),C.backendBinary&&c.jsx("span",{className:"status-chip",style:{cursor:"default"},children:c.jsx("span",{children:C.backendBinary})})]})]}),c.jsxs("button",{className:"m3-btn m3-btn-error",onClick:ot,disabled:ye||W!==null,children:[ye?c.jsx(ea,{className:"progress-spinner",size:16}):c.jsx(li,{size:16}),c.jsx("span",{children:ye?"Unloading":"Unload Server"})]})]})}),ye&&c.jsxs("div",{className:"m3-card",style:{borderLeft:"4px solid var(--md-sys-color-error)",marginTop:"16px"},children:[c.jsx("h4",{style:{fontWeight:700,marginBottom:"8px"},children:"Unloading Model"}),c.jsxs("div",{className:"model-progress-section",style:{margin:"8px 0 0 0"},children:[c.jsxs("div",{className:"model-progress-label",children:[c.jsx("span",{children:nt.phase||"Unloading model..."}),c.jsxs("span",{children:[Math.round(nt.progress),"%"]})]}),c.jsx("div",{className:"model-progress-bar",children:c.jsx("div",{className:"model-progress-fill",style:{width:`${Math.min(100,Math.max(0,nt.progress))}%`,transition:"width 0.25s ease"}})})]})]}),F&&c.jsxs("div",{className:"m3-card",style:{borderLeft:"4px solid var(--md-sys-color-secondary)",marginTop:"16px"},children:[c.jsxs("h4",{style:{fontWeight:700,marginBottom:"8px"},children:["Loading Model: ",F.model||W]}),(F.backendMode||F.backendBinary||F.device)&&c.jsxs("div",{style:{display:"flex",flexWrap:"wrap",gap:"8px",marginBottom:"10px"},children:[F.backendMode&&c.jsxs("span",{className:"status-chip",style:{cursor:"default"},children:[c.jsx(bu,{size:14}),c.jsxs("span",{children:["Loading on ",F.backendMode]})]}),F.device&&c.jsx("span",{className:"status-chip",style:{cursor:"default"},children:c.jsx("span",{children:F.device})}),F.backendBinary&&c.jsx("span",{className:"status-chip",style:{cursor:"default"},children:c.jsx("span",{children:F.backendBinary})})]}),c.jsxs("div",{className:"model-progress-section",style:{margin:"8px 0 0 0"},children:[c.jsxs("div",{className:"model-progress-label",children:[c.jsxs("span",{children:[F.phase,F.speed?` (${F.speed})`:""]}),c.jsx("span",{children:F.total>0?`Loaded ${F.current} / ${F.total} tensors`:`${Math.round(F.progress)}%`})]}),c.jsx("div",{className:"model-progress-bar",children:c.jsx("div",{className:"model-progress-fill",style:{width:`${Math.min(100,Math.max(0,F.progress))}%`,transition:"width 0.25s ease"}})})]})]}),c.jsxs("div",{className:"m3-card",style:{marginTop:"24px"},children:[c.jsxs("h3",{className:"m3-card-title",children:[c.jsx(Ys,{size:18,style:{color:"var(--md-sys-color-primary)"}}),"Local Models (",H.length,")"]}),H.length===0?c.jsx("p",{style:{fontSize:"0.9rem",color:"var(--md-sys-color-outline)",textAlign:"center",padding:"16px 0"},children:"No models detected in app/models/. Download from the library below or import a file."}):c.jsx("div",{style:{display:"flex",flexDirection:"column",gap:"10px"},children:H.map(D=>{const R=D.filename,I=f===R;return c.jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center",padding:"12px 16px",background:I?"var(--md-sys-color-primary-container)":"var(--md-sys-color-surface-variant)",color:I?"var(--md-sys-color-on-primary-container)":"var(--md-sys-color-on-surface-variant)",borderRadius:"var(--md-shape-corner-medium)",border:"1px solid var(--md-sys-color-outline-variant)"},children:[c.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:"2px"},children:[c.jsx("span",{style:{fontWeight:600,fontSize:"0.95rem"},children:R}),c.jsxs("span",{style:{fontSize:"0.75rem",opacity:.8},children:["Local Weights File • ",D.size||ai(D.sizeBytes)]})]}),c.jsx("div",{style:{display:"flex",gap:"8px"},children:I?c.jsxs("button",{className:"m3-btn m3-btn-error",style:{height:"36px",padding:"0 16px"},onClick:ot,disabled:ye,children:[ye?c.jsx(ea,{className:"progress-spinner",size:14}):c.jsx(li,{size:14}),c.jsx("span",{children:ye?"Unloading":"Unload"})]}):c.jsxs(c.Fragment,{children:[c.jsxs("button",{className:"m3-btn m3-btn-filled",style:{height:"36px",padding:"0 16px"},onClick:()=>ke(R),disabled:re,children:[W===R?c.jsx(ea,{className:"progress-spinner",size:14}):c.jsx(Ys,{size:14}),c.jsx("span",{children:W===R?"Loading":"Load"})]}),c.jsx("button",{className:"m3-btn m3-btn-error",style:{height:"36px",width:"36px",padding:0,minWidth:"36px"},onClick:()=>ht(R),disabled:re,title:"Delete from models folder",children:c.jsx(li,{size:14})})]})})]},R)})})]}),c.jsx("div",{className:"workspace-title-section",style:{marginTop:"32px",marginBottom:"16px"},children:c.jsxs("h3",{className:"m3-card-title",children:[c.jsx(fy,{size:20,style:{color:"var(--md-sys-color-primary)"}}),"Model Library"]})}),c.jsx("div",{style:{display:"flex",flexDirection:"column",gap:"16px"},children:l1.map(D=>c.jsxs("div",{className:"m3-card",style:{margin:0},children:[c.jsx("h4",{style:{fontWeight:700,marginBottom:"12px"},children:D.group}),c.jsx("div",{style:{display:"grid",gridTemplateColumns:"repeat(auto-fit, minmax(280px, 1fr))",gap:"12px"},children:D.items.map(R=>{const I=ge.includes(R.filename),P=y===R.filename;return c.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:"10px",padding:"14px",background:"var(--md-sys-color-surface-variant)",border:"1px solid var(--md-sys-color-outline-variant)",borderRadius:"var(--md-shape-corner-medium)"},children:[c.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:"4px"},children:[c.jsx("span",{style:{fontWeight:700},children:R.name}),c.jsxs("span",{style:{fontSize:"0.75rem",color:"var(--md-sys-color-outline)"},children:[R.format," • approx. ",R.approxSize," • ",R.resolution]})]}),c.jsx("p",{style:{fontSize:"0.78rem",color:"var(--md-sys-color-on-surface-variant)",lineHeight:1.35,margin:0},children:R.notes}),P&&c.jsxs("div",{className:"model-progress-section",style:{marginTop:"2px"},children:[c.jsxs("div",{className:"model-progress-label",children:[c.jsxs("span",{style:{display:"inline-flex",alignItems:"center",gap:"8px"},children:[c.jsx("span",{className:"loading-dot"}),"Downloading"]}),c.jsx("span",{children:O>0?`${O}%`:"Preparing"})]}),c.jsx("div",{className:"model-progress-bar",children:c.jsx("div",{className:"model-progress-fill",style:{width:`${Math.min(100,Math.max(0,O))}%`,transition:"width 0.2s ease"}})}),Z&&c.jsx("div",{style:{fontSize:"0.7rem",color:"var(--md-sys-color-outline)",marginTop:"4px"},children:Z})]}),c.jsxs("button",{className:I?"m3-btn m3-btn-tonal":"m3-btn m3-btn-filled",style:{height:"36px",marginTop:"auto"},onClick:()=>ae(R),disabled:I||y!==null,children:[I?c.jsx(bu,{size:14}):P?c.jsx(ea,{className:"progress-spinner",size:14}):c.jsx(lm,{size:14}),c.jsx("span",{children:I?"Downloaded":P?"Downloading":"Download"})]})]},R.filename)})})]},D.group))}),c.jsx("div",{className:"workspace-title-section",style:{marginTop:"32px",marginBottom:"16px"},children:c.jsxs("h3",{className:"m3-card-title",children:[c.jsx(nm,{size:20,style:{color:"var(--md-sys-color-primary)"}}),"Local Model Import"]})}),Te!==null&&c.jsxs("div",{className:"m3-card",style:{borderLeft:"4px solid var(--md-sys-color-primary)",marginTop:"24px"},children:[c.jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center",gap:"12px"},children:[c.jsxs("h4",{style:{fontWeight:600},children:["Copying Model to local folder: ",Le.filename]}),c.jsxs("button",{className:"m3-btn m3-btn-error",style:{height:"34px",padding:"0 14px"},onClick:Ut,children:[c.jsx(Xs,{size:14}),c.jsx("span",{children:"Stop Import"})]})]}),c.jsxs("div",{className:"model-progress-section",style:{margin:"12px 0 6px 0"},children:[c.jsxs("div",{className:"model-progress-label",children:[c.jsxs("span",{children:[Le.status," (",Le.speed," MB/s)"]}),c.jsxs("span",{children:[Te,"% (",Le.eta,"s remaining)"]})]}),c.jsx("div",{className:"model-progress-bar",children:c.jsx("div",{className:"model-progress-fill",style:{width:`${Te}%`,transition:"width 0.15s ease"}})})]})]}),c.jsxs("div",{style:{display:"grid",gridTemplateColumns:"repeat(auto-fit, minmax(300px, 1fr))",gap:"16px",marginTop:"16px"},children:[c.jsxs("label",{className:"import-box",style:{margin:0,height:"100%",justifyContent:"center"},children:[c.jsx("input",{type:"file",style:{display:"none"},accept:".gguf,.safetensors,.ckpt",onChange:k,disabled:Te!==null}),c.jsx(nm,{className:"import-icon"}),c.jsx("span",{style:{fontWeight:600},children:"Choose weights file"}),c.jsx("span",{style:{fontSize:"0.75rem",color:"var(--md-sys-color-outline)",textAlign:"center"},children:"Select `.gguf`, `.safetensors` or `.ckpt` weights."})]}),c.jsxs("div",{className:"m3-card",style:{display:"flex",flexDirection:"column",justifyContent:"center",margin:0,padding:"20px"},children:[c.jsxs("h4",{style:{fontWeight:600,marginBottom:"8px",display:"flex",alignItems:"center",gap:"8px"},children:[c.jsx(lm,{size:16}),"Download Model from URL"]}),c.jsx("p",{style:{fontSize:"0.75rem",color:"var(--md-sys-color-outline)",marginBottom:"12px"},children:"Download any GGUF or Safetensors model from Hugging Face or other sites directly to your models folder."}),se?c.jsxs("div",{className:"model-progress-section",style:{marginTop:"0px"},children:[c.jsxs("div",{className:"model-progress-label",children:[c.jsx("span",{style:{fontSize:"0.75rem",whiteSpace:"nowrap",overflow:"hidden",textOverflow:"ellipsis",maxWidth:"200px"},title:y,children:y}),c.jsxs("span",{children:[O,"%"]})]}),c.jsx("div",{className:"model-progress-bar",style:{margin:"4px 0"},children:c.jsx("div",{className:"model-progress-fill",style:{width:`${O}%`,transition:"width 0.15s ease"}})}),c.jsx("div",{style:{fontSize:"0.7rem",color:"var(--md-sys-color-outline)",marginTop:"2px"},children:Z}),c.jsxs("button",{className:"m3-btn m3-btn-error",style:{height:"34px",padding:"0 14px",marginTop:"10px"},onClick:de,children:[c.jsx(Xs,{size:14}),c.jsx("span",{children:"Stop Download"})]})]}):c.jsxs("form",{onSubmit:J,style:{display:"flex",gap:"8px"},children:[c.jsx("input",{type:"text",className:"m3-input",style:{flex:1,height:"40px"},placeholder:"e.g. https://huggingface.co/...",value:te,onChange:D=>Se(D.target.value),disabled:y!==null}),c.jsx("button",{type:"submit",className:"m3-btn m3-btn-filled",style:{height:"40px"},disabled:y!==null,children:"Download"})]})]})]}),Ye&&c.jsx("div",{style:{position:"fixed",inset:0,zIndex:50,background:"rgba(0,0,0,0.55)",display:"flex",alignItems:"center",justifyContent:"center",padding:"24px"},children:c.jsxs("div",{className:"m3-card",style:{maxWidth:"460px",width:"100%",margin:0,border:"1px solid var(--md-sys-color-outline-variant)"},children:[c.jsxs("div",{style:{display:"flex",alignItems:"center",gap:"10px",marginBottom:"10px"},children:[c.jsx(zy,{size:22,style:{color:"var(--md-sys-color-error)"}}),c.jsx("h3",{style:{fontSize:"1.05rem",fontWeight:700},children:"Unload Current Model?"})]}),c.jsxs("p",{style:{fontSize:"0.9rem",color:"var(--md-sys-color-on-surface-variant)",lineHeight:1.45,marginBottom:"16px"},children:['"',f,'" is already loaded. Unload it before loading "',Ye,'".']}),c.jsxs("div",{style:{display:"flex",justifyContent:"flex-end",gap:"10px"},children:[c.jsx("button",{className:"m3-btn m3-btn-outlined",onClick:()=>x(null),disabled:ye,children:"Cancel"}),c.jsxs("button",{className:"m3-btn m3-btn-error",onClick:ot,disabled:ye,children:[c.jsx(li,{size:14}),c.jsx("span",{children:"Unload Only"})]}),c.jsxs("button",{className:"m3-btn m3-btn-filled",onClick:it,disabled:ye,children:[ye?c.jsx(ea,{className:"progress-spinner",size:14}):c.jsx(ea,{size:14}),c.jsx("span",{children:"Unload and Load"})]})]})]})})]})}const n1=U.memo(a1),cm=[{id:"1:1",label:"1:1 Square",width:512,height:512,sdxl_width:1024,sdxl_height:1024,desc:"Social posts & avatars"},{id:"4:3",label:"4:3 Photo",width:640,height:480,sdxl_width:1152,sdxl_height:864,desc:"Classic photo look"},{id:"16:9",label:"16:9 Landscape",width:768,height:432,sdxl_width:1216,sdxl_height:684,desc:"Widescreen landscape"},{id:"9:16",label:"9:16 Portrait",width:432,height:768,sdxl_width:684,sdxl_height:1216,desc:"Tall phone screen"}],i1=f=>{if(!f)return!0;const b=f.toLowerCase();return!(b.includes("flux")||b.includes("schnell")||b.includes("sdxl")||b.includes("lightning")||b.includes("turbo")||b.includes("sd3"))};function u1({constraints:f,setConstraints:b,activeModel:E,specs:r,backendOptions:_}){const N=E?i1(E):!1,G=_?.options?.length?_.options:[{id:"cpu",label:"CPU",available:!0}],H=(A,O)=>{b(L=>({...L,[A]:O}))},B=(A,O)=>{const L=O==="sdxl"&&!N,Z=cm.find(V=>V.id===A);if(Z){let V=L?Z.sdxl_width:Z.width,W=L?Z.sdxl_height:Z.height;N&&(V>W?(W=Math.round(W*512/V),V=512):(V=Math.round(V*512/W),W=512),V=Math.round(V/64)*64,W=Math.round(W/64)*64),H("width",V),H("height",W)}},y=A=>{b(O=>({...O,backendType:A,useGpu:A!=="cpu"}))};return c.jsxs("div",{className:"workspace-area",children:[c.jsxs("div",{className:"workspace-title-section",children:[c.jsx("h2",{className:"workspace-title",children:"Image Constraints"}),c.jsx("p",{className:"workspace-subtitle",children:"Configure size, quality, and performance controls for image generation."})]}),c.jsxs("div",{className:"generator-layout",children:[c.jsxs("div",{children:[c.jsxs("div",{className:"m3-card",children:[c.jsxs("h3",{className:"m3-card-title",children:[c.jsx(F0,{size:18,style:{color:"var(--md-sys-color-primary)"}}),"1. Picture Size & Shape"]}),N&&c.jsxs("div",{style:{background:"rgba(251, 191, 36, 0.1)",border:"1px solid rgb(251, 191, 36)",color:"var(--md-sys-color-on-surface)",padding:"12px",borderRadius:"8px",marginBottom:"16px",fontSize:"0.85rem",display:"flex",gap:"8px",alignItems:"flex-start"},children:[c.jsx(cy,{size:16,style:{color:"rgb(251, 191, 36)",flexShrink:0,marginTop:"2px"}}),c.jsxs("div",{children:[c.jsx("strong",{children:"Low-VRAM Protection Active:"})," Capped at 512x512 for the loaded SD 1.x model (",c.jsx("code",{children:E}),"). Generating at larger sizes (like 1024x1024) is disabled to prevent out-of-memory crashes on your ",r&&r.gpu_name&&!r.gpu_name.includes("Loading")?r.gpu_name:"graphics processor","."]})]}),c.jsxs("div",{className:"m3-field-group",children:[c.jsxs("div",{className:"m3-text-field",children:[c.jsx("label",{className:"m3-text-field-label",children:"AI Generation Engine Optimization"}),c.jsxs("div",{className:"m3-segmented-button",children:[N?c.jsx("div",{className:"m3-segment-item disabled",style:{opacity:.5,cursor:"not-allowed",textDecoration:"line-through",backgroundColor:"var(--md-sys-color-surface-variant)"},title:"High Quality Mode is disabled for SD 1.x models.",children:"High Quality Mode (1024px)"}):c.jsx("div",{className:`m3-segment-item ${f.width>=1024?"active":""}`,onClick:()=>{H("width",1024),H("height",1024)},children:"High Quality Mode (1024px)"}),c.jsx("div",{className:`m3-segment-item ${f.width<1024||N?"active":""}`,onClick:()=>{H("width",512),H("height",512)},children:"Standard Speed Mode (512px)"})]}),c.jsx("span",{style:{fontSize:"0.75rem",color:"var(--md-sys-color-outline)",marginTop:"4px"},children:N?"*Standard Speed Mode (512px) is forced for SD 1.5 / custom models to ensure stable local generations.":"*Use High Quality (1024px) for Flux or SDXL models. Use Standard (512px) for SD 1.5."})]}),c.jsxs("div",{className:"m3-text-field",children:[c.jsx("label",{className:"m3-text-field-label",children:"Select Shape (Aspect Ratio)"}),c.jsx("div",{style:{display:"grid",gridTemplateColumns:"1fr 1fr",gap:"8px"},children:cm.map(A=>{const O=Math.abs(f.width/f.height-A.width/A.height)<.1;return c.jsxs("button",{className:`m3-btn m3-btn-outlined aspect-ratio-btn ${O?"active":""}`,style:{height:"86px",display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center",padding:"8px",borderRadius:"var(--md-shape-corner-medium)",borderColor:"var(--md-sys-color-outline-variant)"},onClick:()=>B(A.id,N?"sd15":f.width>=1024?"sdxl":"sd15"),children:[c.jsx("div",{className:`aspect-ratio-preview ratio-${A.id.replace(":","-")}`}),c.jsx("span",{style:{fontWeight:600,fontSize:"0.85rem",marginTop:"2px"},children:A.label}),c.jsx("span",{style:{fontSize:"0.68rem",opacity:.7},children:N?`Max: ${A.id==="1:1"?"512x512":A.id==="4:3"?"512x384":A.id==="16:9"?"512x288":"288x512"}`:A.desc})]},A.id)})})]})]})]}),c.jsxs("div",{className:"m3-card",children:[c.jsxs("h3",{className:"m3-card-title",children:[c.jsx(Zs,{size:18,style:{color:"var(--md-sys-color-primary)"}}),"2. Quality, Speed & Logic"]}),c.jsxs("div",{className:"m3-field-group",children:[c.jsxs("div",{className:"m3-slider-group",children:[c.jsxs("div",{className:"m3-slider-header",children:[c.jsx("span",{className:"m3-slider-label",children:"Detail Steps (Inference speed)"}),c.jsxs("span",{className:"m3-slider-value",children:[f.steps," steps"]})]}),c.jsx("input",{type:"range",className:"m3-slider",value:f.steps,onChange:A=>H("steps",parseInt(A.target.value)),min:"1",max:"60"}),c.jsx("span",{style:{fontSize:"0.75rem",color:"var(--md-sys-color-outline)",lineHeight:"1.3"},children:"The number of times the AI cleans up the image. More steps = sharper details, but takes longer."})]}),c.jsxs("div",{className:"m3-text-field",style:{marginTop:"8px"},children:[c.jsx("label",{className:"m3-text-field-label",children:"Image Blueprint (DNA Seed)"}),c.jsxs("div",{style:{display:"flex",gap:"8px"},children:[c.jsx("input",{type:"number",className:"m3-input",value:f.seed,onChange:A=>H("seed",parseInt(A.target.value)||-1),placeholder:"-1 for a brand new image...",style:{flex:1,height:"40px"}}),c.jsx("button",{className:"m3-btn m3-btn-tonal",onClick:()=>H("seed",-1),style:{height:"40px"},children:"Random (-1)"})]})]})]})]})]}),c.jsx("div",{children:c.jsxs("div",{className:"m3-card",children:[c.jsxs("h3",{className:"m3-card-title",children:[c.jsx(om,{size:18,style:{color:"var(--md-sys-color-primary)"}}),"3. System Settings"]}),c.jsxs("div",{className:"m3-field-group",children:[c.jsxs("div",{className:"m3-text-field",children:[c.jsx("label",{className:"m3-text-field-label",children:"Generation Backend"}),c.jsx("div",{className:"m3-segmented-button",children:G.map(A=>c.jsx("div",{className:`m3-segment-item ${f.backendType===A.id||!f.backendType&&A.id==="cpu"?"active":""}`,onClick:()=>y(A.id),title:A.id==="cuda"?"CUDA appears only when an NVIDIA CUDA backend is available.":void 0,children:A.label},A.id))}),c.jsx("span",{style:{fontSize:"0.75rem",color:"var(--md-sys-color-outline)",marginTop:"4px",lineHeight:1.35},children:"CPU is slow but safest. Vulkan works on supported GPUs. CUDA is shown only when NVIDIA CUDA support is available."}),f.backendType==="cuda"&&r?.gpu_name&&String(r.gpu_name).toLowerCase().includes("gtx")&&c.jsxs("div",{style:{marginTop:"12px",padding:"10px 14px",background:"rgba(239, 68, 68, 0.08)",border:"1px dashed rgb(239, 68, 68)",borderRadius:"8px",fontSize:"0.75rem",color:"var(--md-sys-color-on-surface)",lineHeight:"1.45"},children:[c.jsx("strong",{children:"Performance Alert:"})," Your graphics card (",c.jsx("code",{children:r.gpu_name}),") is a GTX-series GPU which lacks hardware ",c.jsx("strong",{children:"Tensor Cores"}),". Running in CUDA mode will be up to 3x slower. We strongly recommend switching to ",c.jsx("strong",{children:"Vulkan GPU"})," for optimal generation speed."]}),_?.unavailable?.length>0&&c.jsx("div",{style:{marginTop:"8px",display:"flex",flexDirection:"column",gap:"4px"},children:_.unavailable.map(A=>c.jsxs("span",{style:{fontSize:"0.75rem",color:"var(--md-sys-color-error)",lineHeight:1.35},children:[A.label," unavailable: ",A.reason]},A.id))})]}),c.jsxs("div",{className:"m3-text-field",style:{marginTop:"20px"},children:[c.jsx("label",{className:"m3-text-field-label",children:"Memory Optimization (GPU VRAM)"}),c.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:"14px",marginTop:"10px"},children:[c.jsxs("label",{style:{display:"flex",alignItems:"flex-start",gap:"10px",cursor:"pointer",fontSize:"0.85rem"},children:[c.jsx("input",{type:"checkbox",checked:f.vaeTiling!==!1,onChange:A=>H("vaeTiling",A.target.checked),style:{width:"16px",height:"16px",marginTop:"3px",accentColor:"var(--md-sys-color-primary)",cursor:"pointer"}}),c.jsxs("div",{children:[c.jsx("strong",{style:{color:"var(--md-sys-color-on-surface)"},children:"Enable VAE Tiling"}),c.jsx("div",{style:{fontSize:"0.75rem",color:"var(--md-sys-color-outline)",marginTop:"2px",lineHeight:1.35},children:"Processes VAE decoding in smaller tiles. Drastically reduces VRAM usage (from 2GB+ down to ~100MB) with no speed loss. Highly recommended for GPUs with 4GB-6GB VRAM."})]})]}),c.jsxs("label",{style:{display:"flex",alignItems:"flex-start",gap:"10px",cursor:"pointer",fontSize:"0.85rem"},children:[c.jsx("input",{type:"checkbox",checked:f.vaeOnCpu===!0,onChange:A=>H("vaeOnCpu",A.target.checked),style:{width:"16px",height:"16px",marginTop:"3px",accentColor:"var(--md-sys-color-primary)",cursor:"pointer"}}),c.jsxs("div",{children:[c.jsx("strong",{style:{color:"var(--md-sys-color-on-surface)"},children:"Run VAE on CPU"}),c.jsx("div",{style:{fontSize:"0.75rem",color:"var(--md-sys-color-outline)",marginTop:"2px",lineHeight:1.35},children:"Offloads the heavy VAE decoder computation from GPU VRAM to system memory (RAM). Saves ~2GB of VRAM, but makes the final decoding stage slightly slower."})]})]})]})]})]})]})})]})]})}const c1=U.memo(u1);function s1(){const f=U.useRef(null),[b,E]=U.useState(null),r=U.useCallback(k=>{const se=f.current;f.current=null,E(null),se&&se(k)},[]),_=U.useCallback(({title:k="Confirm Action",message:se,confirmLabel:D="OK",cancelLabel:R="Cancel",danger:I=!1})=>new Promise(P=>{f.current=P,E({type:"confirm",title:k,message:se,confirmLabel:D,cancelLabel:R,danger:I})}),[]),N=U.useCallback(({title:k="Notice",message:se,confirmLabel:D="OK",danger:R=!1})=>new Promise(I=>{f.current=I,E({type:"alert",title:k,message:se,confirmLabel:D,danger:R})}),[]),[G,H]=U.useState(()=>{const k=localStorage.getItem("theme");return k||(window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light")});U.useEffect(()=>{document.documentElement.setAttribute("data-theme",G),localStorage.setItem("theme",G)},[G]);const[B,y]=U.useState("generator"),[A,O]=U.useState(""),[L,Z]=U.useState(""),[V,W]=U.useState(null),[ue,F]=U.useState(!1),[Ce,Te]=U.useState(!1),[Qe,Le]=U.useState({options:[{id:"cpu",label:"CPU",available:!0}],cudaAvailable:!1,vulkanAvailable:!1,defaultBackendType:"cpu"}),[Me,te]=U.useState(null),[Se,ft]=U.useState([]),[_t,ye]=U.useState(!1),[Ve,nt]=U.useState(!1),[Ke,Ye]=U.useState([]),[x,C]=U.useState(!1),[K,ge]=U.useState(0),[re,d]=U.useState({os_name:"Loading Specs...",cpu_name:"Loading Specs...",cpu_cores_physical:4,cpu_cores_logical:8,ram_total_gb:0,gpu_name:"Loading Specs..."}),[j,w]=U.useState({cpu_usage:0,ram_used_gb:0,ram_total_gb:0,gpu_name:"Detecting...",vram_used_gb:0,vram_total_gb:0}),[q,J]=U.useState({width:1024,height:1024,steps:4,cfgScale:1,sampler:"euler_a",seed:-1,denoisingStrength:.7,useGpu:!0,useTaesd:!0,useFlashAttn:!0,useTiling:!1,vaeTiling:!0,vaeOnCpu:!1,threads:4,backendType:"auto"});U.useEffect(()=>{async function k(){try{const se=await Hy(),D=await qy();Le(D),d(se),J(R=>({...R,threads:se.cpu_cores_physical||4,backendType:R.backendType==="auto"?D.defaultBackendType||"cpu":R.backendType,useGpu:(R.backendType==="auto"?D.defaultBackendType:R.backendType)!=="cpu"}))}catch(se){console.error("Error fetching hardware specs:",se)}}k()},[]);const ae=U.useCallback(async()=>{ye(!0);try{const[k,se]=await Promise.all([Uy(),By().catch(()=>[])]);te(k),ft(se)}finally{ye(!1)}},[]);U.useEffect(()=>{ae()},[ae]);const de=U.useCallback(async()=>{try{const k=await wy();await navigator.clipboard.writeText(JSON.stringify(k,null,2)),nt(!0),setTimeout(()=>nt(!1),1800)}catch(k){N({title:"Diagnostics Failed",message:k.message||String(k),danger:!0})}},[N]),ke=U.useCallback(async()=>{if(Se.length===0)return;const k=Se.reduce((D,R)=>D+Number(R.sizeBytes||0),0);if(await _({title:"Clean Safe Files?",message:`Delete ${Se.length} temporary/cache item${Se.length===1?"":"s"} and free about ${ai(k)}? + +Models and generated outputs are not included.`,confirmLabel:"Clean",danger:!0})){ye(!0);try{await Ry(Se.map(D=>D.id)),await ae()}catch(D){N({title:"Cleanup Failed",message:D.message||String(D),danger:!0})}finally{ye(!1)}}},[Se,ae,N,_]);U.useEffect(()=>{async function k(){const se=await Yy();Ye(se)}k()},[]),U.useEffect(()=>{V?localStorage.setItem("active-model",V):localStorage.removeItem("active-model")},[V]),U.useEffect(()=>{let k=null;async function se(){const D=await Nl();if(!!D.ready){k&&clearInterval(k);const I=localStorage.getItem("active-model");if(I)W(I),F(!0);else{try{if(D&&D.settings&&D.settings.model){const P=D.settings.model.split(/[\\/]/).pop();W(P)}}catch{}F(!0)}}else if(!(typeof window<"u"&&window.__TAURI_INTERNALS__!==void 0)){const P=localStorage.getItem("active-model");P&&(W(P),F(!1))}}return se(),k=setInterval(se,2e3),()=>{k&&clearInterval(k)}},[]),U.useEffect(()=>{async function k(){try{const D=await Gy();w(R=>R.cpu_usage===D.cpu_usage&&R.ram_used_gb===D.ram_used_gb&&R.ram_total_gb===D.ram_total_gb&&R.gpu_name===D.gpu_name&&R.vram_used_gb===D.vram_used_gb&&R.vram_total_gb===D.vram_total_gb?R:D)}catch{}}k();const se=setInterval(k,1500);return()=>clearInterval(se)},[]),U.useEffect(()=>{if(V){const k=V.toLowerCase();k.includes("flux")||k.includes("schnell")?J(se=>({...se,steps:4,cfgScale:1,width:1024,height:1024})):k.includes("lightning")||k.includes("turbo")?J(se=>({...se,steps:4,cfgScale:1.5,width:1024,height:1024})):k.includes("sd15")?J(se=>({...se,steps:25,cfgScale:7,width:512,height:512})):k.includes("sd35")?J(se=>({...se,steps:20,cfgScale:4.5,width:1024,height:1024})):J(se=>({...se,steps:20,cfgScale:7,width:512,height:512}))}},[V]);const Ee=U.useMemo(()=>{switch(B){case"generator":return c.jsx(t1,{prompt:A,setPrompt:O,negativePrompt:L,setNegativePrompt:Z,constraints:q,setConstraints:J,activeModel:V,generatedImages:Ke,setGeneratedImages:Ye,isGenerating:x,setIsGenerating:C,generationProgress:K,setGenerationProgress:ge,setActiveTab:y,showAlert:N,showConfirm:_});case"models":return c.jsx(n1,{activeModel:V,setActiveModel:W,serverRunning:ue,setServerRunning:F,constraints:q,showAlert:N,showConfirm:_});case"constraints":return c.jsx(c1,{constraints:q,setConstraints:J,activeModel:V,specs:re,backendOptions:Qe});default:return null}},[B,A,L,q,V,Ke,x,K,ue,re,Qe,N,_]),it=U.useMemo(()=>c.jsx(My,{activeTab:B,setActiveTab:y,specs:re}),[B,re]),ot=U.useCallback(async()=>{if(!(!ue||Ce)){Te(!0);try{await Vs(),F(!1),W(null)}catch(k){console.error("Failed to stop server:",k),N({title:"Stop Server Failed",message:k.message||String(k),danger:!0})}finally{Te(!1)}}},[ue,Ce,N]),ht=[...Me?.stale?["Restart Local AI Image Generator so the local server loads the latest API."]:[],...Me?.issues||[]],cl=Se.reduce((k,se)=>k+Number(se.sizeBytes||0),0),Ut=!!(Me&&(ht.length>0||Se.length>0));return c.jsxs("div",{className:"app-container",children:[it,c.jsxs("div",{className:"main-content",children:[c.jsx(Ny,{telemetry:j,serverRunning:ue,activeModel:V,onStopServer:ot,isStoppingServer:Ce,theme:G,setTheme:H}),Ut&&c.jsxs("div",{className:`m3-card readiness-card ${Me?.stale||ht.length>0?"readiness-card-warning":""}`,children:[c.jsxs("div",{className:"readiness-header",children:[c.jsxs("div",{children:[c.jsx("h3",{className:"m3-card-title",style:{marginBottom:"4px"},children:Me?.stale?"Restart Required":ht.length>0?"System Readiness":"Safe Cleanup Available"}),c.jsx("p",{className:"m3-card-subtitle",style:{margin:0},children:Me?.stale?`Running server build: ${Me.build||"unknown"}`:ht.length>0?"Local AI Image Generator found setup items that may need attention.":`${Se.length} temporary item${Se.length===1?"":"s"} can be cleaned (${ai(cl)}).`})]}),c.jsxs("div",{className:"readiness-actions",children:[c.jsx("button",{className:"m3-btn m3-btn-outlined",onClick:ae,disabled:_t,children:_t?"Checking":"Refresh"}),c.jsx("button",{className:"m3-btn m3-btn-tonal",onClick:de,children:Ve?"Copied":"Copy Diagnostics"}),Se.length>0&&c.jsxs("button",{className:"m3-btn m3-btn-error",onClick:ke,disabled:_t,children:["Clean ",ai(cl)]})]})]}),ht.length>0&&c.jsx("div",{className:"readiness-issues",children:ht.slice(0,4).map(k=>c.jsx("span",{children:k},k))}),Se.length>0&&c.jsx("div",{className:"readiness-cleanup-list",children:Se.slice(0,3).map(k=>c.jsxs("span",{title:k.path,children:[k.name," · ",k.size," · ",k.reason]},k.id))})]}),Ee]}),b&&c.jsx("div",{className:"app-dialog-backdrop",role:"presentation",children:c.jsxs("div",{className:"app-dialog",role:"dialog","aria-modal":"true","aria-labelledby":"app-dialog-title",children:[c.jsx("h3",{id:"app-dialog-title",className:"app-dialog-title",children:b.title}),c.jsx("p",{className:"app-dialog-message",children:b.message}),c.jsxs("div",{className:"app-dialog-actions",children:[b.type==="confirm"&&c.jsx("button",{className:"m3-btn m3-btn-outlined",onClick:()=>r(!1),children:b.cancelLabel}),c.jsx("button",{className:`m3-btn ${b.danger?"m3-btn-error":"m3-btn-filled"}`,onClick:()=>r(!0),children:b.confirmLabel})]})]})})]})}G0.createRoot(document.getElementById("root")).render(c.jsx(D0.StrictMode,{children:c.jsx(s1,{})}));export{Sa as i,f1 as t}; diff --git a/app/dist/index.html b/app/dist/index.html index 4d279bd..93483d5 100644 --- a/app/dist/index.html +++ b/app/dist/index.html @@ -8,7 +8,7 @@ Local AI Image Generator - + diff --git a/app/frontend/src/components/Generator.jsx b/app/frontend/src/components/Generator.jsx index 7584d7f..83d2be1 100644 --- a/app/frontend/src/components/Generator.jsx +++ b/app/frontend/src/components/Generator.jsx @@ -1,5 +1,5 @@ import React, { memo, useState, useRef, useCallback } from "react"; -import { Sparkles, Download, Copy, RefreshCw, Check, Sliders, Layers, Trash2 } from "lucide-react"; +import { Sparkles, Download, Copy, RefreshCw, Check, Sliders, Trash2 } from "lucide-react"; import { generateImage, startServer, stopServer, waitForServerReady, getBackendStatus, getGenerationProgress, saveGeneratedOutput, deleteGeneratedOutputs } from "../services/api"; const GalleryItem = memo(({ img, idx, isSelected, onClick }) => { @@ -600,10 +600,6 @@ function Generator({ Steps: {constraints.steps} -
setActiveTab("constraints")}> - - CFG: {constraints.cfgScale.toFixed(1)} -
setActiveTab("constraints")}> Sampler: {constraints.sampler} diff --git a/app/frontend/src/components/ImageConstraints.jsx b/app/frontend/src/components/ImageConstraints.jsx index 53ffb90..8633db3 100644 --- a/app/frontend/src/components/ImageConstraints.jsx +++ b/app/frontend/src/components/ImageConstraints.jsx @@ -209,26 +209,6 @@ function ImageConstraints({ constraints, setConstraints, activeModel, specs, bac
- {/* CFG Scale Slider */} -
-
- Prompt Strictness (Instruction obedience) - {constraints.cfgScale.toFixed(1)} -
- updateConstraint("cfgScale", parseFloat(e.target.value))} - min="1" - max="15" - step="0.5" - /> - - How closely the AI follows your text prompt. Lower = more creative. Higher = more strict. - -
- {/* Random Seed DNA */}
diff --git a/app/frontend/src/components/ModelManager.jsx b/app/frontend/src/components/ModelManager.jsx index d451a39..dd3f93d 100644 --- a/app/frontend/src/components/ModelManager.jsx +++ b/app/frontend/src/components/ModelManager.jsx @@ -250,10 +250,12 @@ function ModelManager({ activeModel, setActiveModel, serverRunning, setServerRun const performLoadModel = async (modelId) => { const isTauriDesktop = typeof window !== "undefined" && window.__TAURI_INTERNALS__ !== undefined; const isLocalServerMode = typeof window !== "undefined" && (window.location.hostname === "localhost" || window.location.hostname === "127.0.0.1"); + const backendStatus = await getBackendStatus(); + const backendPort = backendStatus?.port || 8080; if (!isTauriDesktop && !isLocalServerMode) { const isAlreadyRunning = await pingServer(); - const cmd = `.\\backend\\win\\vulkan\\sd-vulkan.exe --listen-port 8080 --model .\\models\\${modelId} --threads 8`; + const cmd = `.\\backend\\win\\vulkan\\sd-vulkan.exe --listen-port ${backendPort} --model .\\models\\${modelId} --threads 8`; if (isAlreadyRunning) { if (await showConfirm({ title: "Web Browser Mode", message: `To load "${modelId}" on the active GPU server, restart your terminal backend with:\n\n${cmd}\n\nUpdate the UI status anyway?`, confirmLabel: "Update UI" })) { @@ -261,7 +263,7 @@ function ModelManager({ activeModel, setActiveModel, serverRunning, setServerRun setServerRunning(true); } } else { - if (await showConfirm({ title: "Backend Not Running", message: `C++ backend server is not running on port 8080.\n\nTo run locally, start:\n\n${cmd}\n\nProceed in Simulation Mode instead?`, confirmLabel: "Proceed" })) { + if (await showConfirm({ title: "Backend Not Running", message: `C++ backend server is not running on port ${backendPort}.\n\nTo run locally, start:\n\n${cmd}\n\nProceed in Simulation Mode instead?`, confirmLabel: "Proceed" })) { setActiveModel(modelId); setServerRunning(false); } @@ -330,7 +332,7 @@ function ModelManager({ activeModel, setActiveModel, serverRunning, setServerRun setActiveModel(modelId); setServerRunning(true); } else { - throw new Error(crashError || "Model server failed to respond on port 8080."); + throw new Error(crashError || `Model server failed to respond on port ${backendPort}.`); } } catch (e) { console.error("Failed to load model:", e); diff --git a/app/frontend/src/services/api.js b/app/frontend/src/services/api.js index 2d9343f..95eac92 100644 --- a/app/frontend/src/services/api.js +++ b/app/frontend/src/services/api.js @@ -8,12 +8,32 @@ export const isTauri = () => { // Cached hardware specs let cachedSpecs = null; +let cachedBackendPort = null; export const EXPECTED_SERVER_BUILD = "polish-setup-v1"; const isLocalServerMode = () => { return typeof window !== "undefined" && (window.location.hostname === "localhost" || window.location.hostname === "127.0.0.1"); }; +async function getBackendPort() { + if (isLocalServerMode()) { + try { + const status = await getBackendStatus(); + const port = Number(status?.port); + if (Number.isInteger(port) && port > 0) { + cachedBackendPort = port; + return port; + } + } catch (_) {} + } + if (cachedBackendPort) return cachedBackendPort; + return 8080; +} + +async function getBackendBaseUrl() { + return `http://127.0.0.1:${await getBackendPort()}`; +} + export function formatBytes(bytes) { const value = Number(bytes) || 0; if (value <= 0) return "0 B"; @@ -208,10 +228,11 @@ export async function listLocalModels() { // In web/portable mode this calls serve.cjs management API which restarts the // sd-vulkan.exe process with --steps, --cfg-scale, --sampling-method flags. export async function startServer(modelPath, constraints) { + const backendPort = await getBackendPort(); if (isTauri()) { const launchParams = { model_path: modelPath, - port: 8080, + port: backendPort, use_gpu: constraints.useGpu !== false, backend_type: constraints.backendType || (constraints.useGpu === false ? "cpu" : "auto"), threads: constraints.threads || 8, @@ -242,6 +263,9 @@ export async function startServer(modelPath, constraints) { if (!res.ok || data.ok === false) { throw new Error(data.error || `Backend restart failed (HTTP ${res.status})`); } + if (Number.isInteger(Number(data.port)) && Number(data.port) > 0) { + cachedBackendPort = Number(data.port); + } console.log("Backend restart:", data.message); return data.message; } catch (e) { @@ -320,8 +344,7 @@ export async function generateImage(prompt, negativePrompt, constraints, activeM console.log("Initiating image generation:", { prompt, negativePrompt, constraints, activeModelName }); const startTime = Date.now(); - const port = 8080; - const baseUrl = `http://127.0.0.1:${port}`; + const baseUrl = await getBackendBaseUrl(); // Prepare payload based on standard stable-diffusion.cpp REST endpoint schemas const payload = { @@ -738,8 +761,7 @@ export async function deleteModel(filename) { // Ping the server to check if it is active and responding export async function pingServer() { - const port = 8080; - const baseUrl = `http://127.0.0.1:${port}`; + const baseUrl = await getBackendBaseUrl(); try { const response = await fetch(`${baseUrl}/v1/models`, { method: "GET" }); return response.ok; diff --git a/scripts/serve.cjs b/scripts/serve.cjs index f868b52..1772fcb 100644 --- a/scripts/serve.cjs +++ b/scripts/serve.cjs @@ -11,8 +11,14 @@ const os = require("os"); const path = require("path"); const { spawn, spawnSync, execSync, exec } = require("child_process"); -const PORT_FRONTEND = process.env.PORT ? parseInt(process.env.PORT) : 1420; -const PORT_BACKEND = 8080; +function readPort(value, fallback) { + const port = parseInt(value, 10); + return Number.isInteger(port) && port > 0 && port < 65536 ? port : fallback; +} + +const PORT_FRONTEND = readPort(process.env.PORT || process.env.FRONTEND_PORT, 1420); +const PREFERRED_BACKEND_PORT = readPort(process.env.BACKEND_PORT || process.env.SD_BACKEND_PORT, 8080); +let PORT_BACKEND = PREFERRED_BACKEND_PORT; const MAX_JSON_BODY_BYTES = 64 * 1024 * 1024; const SERVER_BUILD = "polish-setup-v1"; const ROOT = path.join(__dirname, ".."); @@ -310,6 +316,21 @@ function checkPort(port) { }); } +async function findAvailableBackendPort() { + const preferred = await checkPort(PREFERRED_BACKEND_PORT); + if (preferred.available) return PREFERRED_BACKEND_PORT; + + for (let port = 28088; port <= 28120; port += 1) { + const candidate = await checkPort(port); + if (candidate.available) { + console.log(` [backend] Preferred port ${PREFERRED_BACKEND_PORT} is busy; using ${port} instead.`); + return port; + } + } + + throw new Error(`No free backend port found. Tried ${PREFERRED_BACKEND_PORT} and 28088-28120.`); +} + function getSetupPaths() { const appDir = path.join(ROOT, "app"); if (osPlatform === "win32") { @@ -382,7 +403,9 @@ async function getHealth() { backend: { ...(await checkPort(PORT_BACKEND)), expectedInUse: backendProc !== null }, }; ports.frontend.ok = !ports.frontend.available; - ports.backend.ok = backendProc !== null ? !ports.backend.available : ports.backend.available; + ports.backend.preferred = PREFERRED_BACKEND_PORT; + ports.backend.selected = PORT_BACKEND; + ports.backend.ok = true; const issues = checks .filter((check) => !check.ok && !["CUDA backend", "Vulkan backend", "Linux backend", "Mac backend"].includes(check.label)) @@ -390,8 +413,6 @@ async function getHealth() { if (!backendInstalled) { issues.push(`No ${osPlatform === "win32" ? "Windows" : osPlatform === "darwin" ? "macOS" : "Linux"} backend binary is installed.`); } - if (!ports.backend.ok) issues.push(`Port ${PORT_BACKEND} is already in use by another process.`); - return { ok: criticalOk && ports.backend.ok, build: SERVER_BUILD, @@ -657,7 +678,7 @@ function killBackend() { }); } -function startBackend(settings = {}) { +async function startBackend(settings = {}) { backendError = null; currentSettings = { ...currentSettings, ...settings }; if (!currentSettings.model) currentSettings.model = getDefaultModel(); @@ -666,6 +687,8 @@ function startBackend(settings = {}) { return; } + PORT_BACKEND = await findAvailableBackendPort(); + const resolvedBackendType = resolveBackendType(currentSettings.useGpu, currentSettings.backendType); currentSettings.backendType = resolvedBackendType; currentSettings.useGpu = resolvedBackendType !== "cpu"; @@ -1305,6 +1328,8 @@ const server = http.createServer(async (req, res) => { return json(res, 200, { ready: backendReady, running: backendProc !== null, + port: PORT_BACKEND, + preferredPort: PREFERRED_BACKEND_PORT, error: backendError, loading: backendLoadState, unloading: backendUnloadState, @@ -1359,8 +1384,13 @@ const server = http.createServer(async (req, res) => { } if (typeof body.vae_tiling === "boolean") newSettings.vaeTiling = body.vae_tiling; if (typeof body.vae_on_cpu === "boolean") newSettings.vaeOnCpu = body.vae_on_cpu; - startBackend(newSettings); - return json(res, 200, { ok: true, message: "Backend restarting...", settings: currentSettings }); + try { + await startBackend(newSettings); + return json(res, 200, { ok: true, message: "Backend restarting...", settings: currentSettings, port: PORT_BACKEND }); + } catch (err) { + backendError = err.message || String(err); + return json(res, 500, { ok: false, error: backendError, port: PORT_BACKEND }); + } } // POST /api/stop-backend diff --git a/start.bat b/start.bat index dad78e9..342bcad 100644 --- a/start.bat +++ b/start.bat @@ -10,6 +10,7 @@ set SETUP=%~dp0scripts\setup.ps1 set CUDA_BACKEND=%APP%\backend\win\cuda\sd-cuda.exe set VULKAN_BACKEND=%APP%\backend\win\vulkan\sd-vulkan.exe set SERVE=%~dp0scripts\serve.cjs +if "%FRONTEND_PORT%"=="" set FRONTEND_PORT=1420 set SETUP_REASON= set SETUP_MODE=Repair @@ -49,9 +50,8 @@ echo. echo Press any key to continue, or Ctrl+C to cancel. pause >nul -:: Clear old local server processes before setup so app/tools/node-win can be replaced -for /f "tokens=5" %%a in ('netstat -aon 2^>nul ^| findstr ":8080 "') do taskkill /f /pid %%a >nul 2>nul -for /f "tokens=5" %%a in ('netstat -aon 2^>nul ^| findstr ":1420 "') do taskkill /f /pid %%a >nul 2>nul +:: Clear old frontend server process before setup so app/tools/node-win can be replaced +for /f "tokens=5" %%a in ('netstat -aon 2^>nul ^| findstr ":%FRONTEND_PORT% "') do taskkill /f /pid %%a >nul 2>nul powershell -ExecutionPolicy Bypass -File "%SETUP%" if errorlevel 1 ( @@ -73,10 +73,9 @@ echo LOCAL AI IMAGE GENERATOR ^| Launching... echo ============================================================ echo. -:: Kill anything on our ports -echo Clearing ports 8080 and 1420... -for /f "tokens=5" %%a in ('netstat -aon 2^>nul ^| findstr ":8080 "') do taskkill /f /pid %%a >nul 2>nul -for /f "tokens=5" %%a in ('netstat -aon 2^>nul ^| findstr ":1420 "') do taskkill /f /pid %%a >nul 2>nul +:: Clear only the frontend port. The backend auto-selects a free port. +echo Clearing frontend port %FRONTEND_PORT%... +for /f "tokens=5" %%a in ('netstat -aon 2^>nul ^| findstr ":%FRONTEND_PORT% "') do taskkill /f /pid %%a >nul 2>nul :: Start frontend server + backend manager (serve.cjs manages sd-vulkan.exe) echo Starting Local AI Image Generator... @@ -86,14 +85,14 @@ start "SD-Server" /min "%NODE%" "%SERVE%" timeout /t 2 >nul :: Open browser -echo Opening browser at http://localhost:1420 -start http://localhost:1420 +echo Opening browser at http://localhost:%FRONTEND_PORT% +start http://localhost:%FRONTEND_PORT% echo. echo ============================================================ echo Running! -echo Web UI: http://localhost:1420 -echo GPU API: http://127.0.0.1:8080 +echo Web UI: http://localhost:%FRONTEND_PORT% +echo GPU API: Auto-selected by the app (starts at 8080) echo. echo Close this window to stop all services. echo ============================================================ @@ -103,4 +102,4 @@ pause >nul :: Cleanup on exit echo Shutting down... taskkill /fi "WINDOWTITLE eq SD-Server*" /f >nul 2>nul -echo Done. Goodbye! \ No newline at end of file +echo Done. Goodbye!