From 25b9a5c965addd16665a5ad632cc8ea68bb8087b Mon Sep 17 00:00:00 2001 From: Tech Jarves Date: Tue, 9 Jun 2026 10:55:47 +0000 Subject: [PATCH] add linux --- PLAN.md | 192 ++++++++++ README.md | 97 +++++- .../{event-DeDJUvqC.js => event-Df1n27Ua.js} | 2 +- app/dist/assets/index-CG3WZqfX.js | 23 ++ app/dist/assets/index-jXnaCwmK.js | 121 ------- app/dist/index.html | 34 +- app/frontend/package-lock.json | 224 ++++++------ app/frontend/src/services/api.js | 179 +--------- scripts/build_from_source.sh | 130 +++++++ scripts/reset.sh | 59 ++++ scripts/serve.cjs | 184 ++++++++-- scripts/setup.sh | 327 ++++++++++++++++++ start.sh | 134 +++++++ 13 files changed, 1255 insertions(+), 451 deletions(-) create mode 100644 PLAN.md rename app/dist/assets/{event-DeDJUvqC.js => event-Df1n27Ua.js} (94%) create mode 100644 app/dist/assets/index-CG3WZqfX.js delete mode 100644 app/dist/assets/index-jXnaCwmK.js create mode 100755 scripts/build_from_source.sh create mode 100755 scripts/reset.sh create mode 100755 scripts/setup.sh create mode 100755 start.sh diff --git a/PLAN.md b/PLAN.md new file mode 100644 index 0000000..401a6e6 --- /dev/null +++ b/PLAN.md @@ -0,0 +1,192 @@ +# Linux Port Plan for Local AI Image Generator + +> **Plan location**: This plan will be copied to the project root as `PLAN.md` upon approval, per user request. + +> **Implementation Update (post-verification)** +> +> During end-to-end testing, the third-party Linux CUDA binary (`leaxer-ai/leaxer-stable-diffusion`) was found to **segfault during generation** after successfully loading the model. As a result, Linux CUDA support was **removed** from the implementation. Linux NVIDIA GPUs now use the **Vulkan** backend. The setup script also gained a glibc version check, because the official leejet Linux binaries require **glibc 2.38+** (Ubuntu 24.04). The frontend's misleading "mock SVG" fallback was replaced with a real error message when the backend crashes. See the updated README for build-from-source instructions. + +## 1. What This Project Does + +**Local AI Image Generator** is a zero-configuration, portable desktop environment for running Stable Diffusion (Safetensors / GGUF / CKPT) completely offline. The Windows flow is: + +1. **Entry Point**: `start.bat` double-click launcher. +2. **Setup**: `scripts/setup.ps1` auto-downloads portable Node.js for Windows, detects the GPU vendor, downloads the matching stable-diffusion.cpp backend (CUDA for NVIDIA, Vulkan for AMD/Intel), installs npm dependencies, and builds the Vite+React frontend into `app/dist/`. +3. **Runtime**: `scripts/serve.cjs` (a Node.js HTTP server) serves the static frontend on `localhost:1420`, manages the backend process lifecycle, proxies generation requests, handles model downloads/imports, tracks telemetry, and manages the gallery. +4. **All sandboxed**: Everything lives under the project folder (`app/tools/`, `app/backend/`, `app/models/`, `app/outputs/`). No global PATH changes, no system installers. + +## 2. Research Findings + +### 2.1 stable-diffusion.cpp Linux Binaries + +We researched the upstream project (`leejet/stable-diffusion.cpp`) and third-party builders. The following Linux x86_64 binaries are available: + +| Backend | Source | Availability | Approx. Size | Notes | +|---|---|---|---|---| +| **CPU** | leejet official releases | ✅ Available | ~20–30 MB | Generic x86_64 CPU binary | +| **Vulkan** | leejet official releases | ✅ Available | ~100 MB | Cross-vendor GPU (AMD, Intel, NVIDIA) | +| **ROCm** | leejet official releases | ✅ Available | ~1.2 GB | AMD GPU; requires host ROCm kernel driver | +| **CUDA** | leejet official releases | ❌ **Not published** | N/A | See section 2.2 | +| **CUDA** | leaxer-ai/leaxer-stable-diffusion (third-party) | ❌ **Rejected** | ~115 MB | Loads models but **segfaults during generation**; removed from setup. | + +**Critical Finding**: Upstream does **not** publish Linux CUDA binaries. There is an open feature request ([leejet/stable-diffusion.cpp#1291](https://github.com/leejet/stable-diffusion.cpp/issues/1291)) but no official support yet. + +### 2.2 Linux CUDA Feasibility Analysis + +We evaluated the third-party `leaxer-ai/leaxer-stable-diffusion` Linux CUDA binary: +- The binary downloads successfully and is a valid ELF executable. +- It loads models and initializes CUDA without errors. +- **However, it segfaults as soon as image generation starts** (reproduced on NVIDIA L4 with `TXT2IMG`). +- Because the binary is non-functional for its intended purpose, the project does **not** download or use it. + +**Decision**: Linux CUDA support is **disabled** until a reliable prebuilt binary becomes available (either from upstream leejet or a verified third-party builder). Linux NVIDIA systems fall back to the **Vulkan** backend, which uses the same GPU via the NVIDIA Vulkan driver. + +Users who need native CUDA performance on Linux can build `stable-diffusion.cpp` from source with `-DSD_CUDA=ON` and copy the resulting binary into `app/backend/linux/cuda/`; see README for instructions. + +### 2.3 Portable Node.js for Linux +- Node.js distributes `node-v22.12.0-linux-x64.tar.xz` (matching the Windows LTS version already used). +- Fully portable: extract with `tar` and run `bin/node` / `bin/npm` directly. + +### 2.4 Zero-Dependency GPU Detection on Linux +To avoid requiring `lspci`, `lshw`, or other host packages, we can parse PCI vendor IDs directly from sysfs: +- Read `/sys/bus/pci/devices/*/vendor` +- **NVIDIA**: `0x10de` +- **AMD**: `0x1002` +- **Intel**: `0x8086` +This is pure file I/O and works in any Linux environment with sysfs. + +### 2.5 Extraction Strategy (No Host `unzip` Required) +- Node.js `.tar.xz` → extracted with `tar` (universally available on Linux). +- Backend `.zip` files → extracted using Node.js after bootstrapping (e.g., via `adm-zip` or a small inline script), or fall back to `python3 -m zipfile` if needed. +- NVIDIA CUDA redist `.tar.xz` → extracted with `tar`. + +## 3. Implementation Approach: Maximum Performance (All Four Backends) + +Based on your feedback, the recommended approach is to support **CPU + Vulkan + ROCm + CUDA** on Linux. + +### 3.1 Backend Selection Matrix + +| Vendor | Primary Backend | Fallback Backend | Source | +|---|---|---|---| +| NVIDIA | CUDA (best perf) | Vulkan | CUDA = leaxer third-party; Vulkan = leejet official | +| AMD | ROCm (best perf) | Vulkan | ROCm = leejet official; Vulkan = leejet official | +| Intel | Vulkan | CPU | Vulkan = leejet official | +| No GPU / Unknown | CPU | — | CPU = leejet official | + +### 3.2 Backend Directory Layout (Linux) + +``` +app/backend/ +├── win/ +│ ├── cuda/sd-cuda.exe +│ └── vulkan/sd-vulkan.exe +└── linux/ + ├── cpu/sd-cpu + ├── vulkan/sd-vulkan + ├── rocm/sd-rocm + libstable-diffusion.so + └── cuda/sd-cuda + libstable-diffusion.so + libcudart.so.12 + libcublas.so.12 + libcublasLt.so.12 +``` + +## 4. Files to Create / Modify + +### New Files +1. **`start.sh`** — Bash entry point equivalent to `start.bat`. + - Checks for portable Node.js and frontend build. + - Runs `scripts/setup.sh` if anything is missing. + - Starts `scripts/serve.cjs` with the portable Node.js binary. + - Opens browser (`xdg-open`) or prints URL. + - Handles graceful shutdown (traps SIGINT/SIGTERM to kill backend). + +2. **`scripts/setup.sh`** — Bash setup equivalent to `setup.ps1`. + - Downloads portable Node.js Linux tarball with `curl` + progress bar. + - Extracts with `tar`. + - Detects GPU via sysfs PCI vendor IDs. + - Downloads appropriate backends: + - **CPU + Vulkan** for everyone (baseline). + - **ROCm** if AMD GPU detected. + - **CUDA** if NVIDIA GPU detected (optional, due to large download). + - Downloads NVIDIA CUDA redist libraries if CUDA is selected. + - Extracts all archives using `tar` / Node.js / Python fallback. + - Renames binaries to predictable names. + - Runs `npm install` and `npm run build` using portable npm. + +3. **`scripts/reset.sh`** — Bash reset equivalent to `reset.ps1`. + - Deletes `app/tools/`, `app/backend/`, `app/dist/`, `app/frontend/node_modules/` while preserving `app/models/` and `app/outputs/`. + +### Modified Files +4. **`scripts/serve.cjs`** — Enhance Linux support. + - **Add Linux backend paths**: + ```js + linuxCpu: path.join(ROOT, "app", "backend", "linux", "cpu", "sd-cpu"), + linuxVulkan: path.join(ROOT, "app", "backend", "linux", "vulkan", "sd-vulkan"), + linuxRocm: path.join(ROOT, "app", "backend", "linux", "rocm", "sd-rocm"), + linuxCuda: path.join(ROOT, "app", "backend", "linux", "cuda", "sd-cuda"), + ``` + - **Add Linux GPU detection** via sysfs (`/sys/bus/pci/devices/*/vendor`). + - **Update `getBackendOptions()`**: For Linux, return `cpu`, `vulkan`, `rocm` (if binary exists), and `cuda` (if binary + libraries exist). + - **Update `selectBackendPath()`**: Choose Linux backend based on resolved type; set `LD_LIBRARY_PATH` for CUDA/ROCm subprocesses so they find bundled `.so` files. + - **Update `getHealth()` / `getSetupPaths()`**: Include Linux backend checks. + - **Update `getGpuInfo()` / `hasNvidiaGpu()`**: Add Linux sysfs parsing. + - **CUDA VRAM polling**: Keep existing `nvidia-smi` approach; on Linux it works if drivers are installed. + +5. **`README.md`** — Add Linux section with compatibility matrix, `./start.sh` usage, and known limitations. + +## 5. Download Sources + +| Component | URL Pattern | +|---|---| +| Portable Node.js | `https://nodejs.org/dist/v22.12.0/node-v22.12.0-linux-x64.tar.xz` | +| CPU Backend | `https://github.com/leejet/stable-diffusion.cpp/releases/download/master-XXX/sd-master-XXX-bin-Linux-Ubuntu-24.04-x86_64.zip` | +| Vulkan Backend | `https://github.com/leejet/stable-diffusion.cpp/releases/download/master-XXX/sd-master-XXX-bin-Linux-Ubuntu-24.04-x86_64-vulkan.zip` | +| ROCm Backend | `https://github.com/leejet/stable-diffusion.cpp/releases/download/master-XXX/sd-master-XXX-bin-Linux-Ubuntu-24.04-x86_64-rocm-7.13.0.zip` | +| CUDA Binary (third-party) | `https://github.com/leaxer-ai/leaxer-stable-diffusion/releases/download/v0.1.0/sd-x86_64-unknown-linux-gnu-cuda` | +| CUDA Server (third-party) | `https://github.com/leaxer-ai/leaxer-stable-diffusion/releases/download/v0.1.0/sd-server-x86_64-unknown-linux-gnu-cuda` | +| CUDA Runtime (NVIDIA redist) | `https://developer.download.nvidia.com/compute/cuda/redist/cuda_cudart/linux-x86_64/cuda_cudart-linux-x86_64-12.X.YZ-archive.tar.xz` | +| cuBLAS (NVIDIA redist) | `https://developer.download.nvidia.com/compute/cuda/redist/libcublas/linux-x86_64/libcublas-linux-x86_64-12.X.YZ-archive.tar.xz` | + +## 6. Setup Modes + +To respect users with limited bandwidth or no NVIDIA hardware, `setup.sh` should support two modes: + +1. **Quick Setup (default)** — Downloads CPU + Vulkan only. + - Works on all Linux systems. + - NVIDIA users get Vulkan acceleration (good, but not best). + - ~120–150 MB total download. + +2. **Maximum Performance Setup** — Downloads CPU + Vulkan + ROCm + CUDA. + - Best performance for each vendor. + - ~1.5 GB total download (mostly ROCm + cuBLAS). + - User can opt-in via `./start.sh --max-perf` or `./scripts/setup.sh --max-perf`. + +## 7. Self-Contained Checklist + +| Host Dependency | How We Eliminate It | +|---|---| +| Node.js installed globally | Download portable `node-v22.12.0-linux-x64.tar.xz` into `app/tools/node-linux/` | +| npm installed globally | Use portable npm from the tarball | +| `unzip` command | Extract ZIPs using Node.js or Python `zipfile` | +| `lspci` / `lshw` | Parse `/sys/bus/pci/devices/*/vendor` directly | +| C++ compiler / CUDA toolkit | Use pre-built binaries only | +| System package manager (apt/yum) | Never used | +| CUDA runtime libs | Bundle NVIDIA redistributable `.so` files | + +**One unavoidable host dependency remains**: the NVIDIA kernel driver (`libcuda.so.1`) for CUDA mode. Without it, CUDA cannot run. The app will detect this and automatically fall back to Vulkan for NVIDIA. + +## 8. Known Limitations + +1. **Third-party CUDA binary**: The Linux CUDA build comes from `leaxer-ai/leaxer-stable-diffusion`, which has only one release (v0.1.0) and may become stale. We should pin to a specific version and periodically evaluate alternatives. +2. **Large ROCm download**: The official ROCm backend ZIP is ~1.2 GB, which is a significant one-time download. +3. **Large cuBLAS download**: NVIDIA's redistributable cuBLAS package is ~400–500 MB. +4. **NVIDIA driver requirement for CUDA**: `libcuda.so.1` must be present on the host (provided by the NVIDIA proprietary driver). If missing, CUDA mode falls back to Vulkan. +5. **ROCm host driver requirement**: ROCm requires a compatible AMD GPU and ROCm kernel driver. If unavailable, ROCm falls back to Vulkan. +6. **glibc compatibility**: Official Linux binaries are built on Ubuntu 24.04. They may fail on very old distributions (e.g., CentOS 7, Ubuntu 18.04) due to glibc version mismatches. + +## 9. Recommended Implementation Order + +1. Create `start.sh`, `scripts/setup.sh`, and `scripts/reset.sh` with CPU + Vulkan support first. +2. Update `scripts/serve.cjs` with Linux paths, sysfs GPU detection, and backend selection. +3. Add ROCm download path (behind `--max-perf` flag). +4. Add CUDA download path using leaxer binary + NVIDIA redist libraries (behind `--max-perf` flag). +5. Add fallback logic so that if ROCm/CUDA fails to initialize, the app automatically switches to Vulkan. +6. Update `README.md` with Linux instructions and performance notes. +7. Test on Linux machines with NVIDIA (CUDA/Vulkan), AMD (ROCm/Vulkan), Intel (Vulkan), and CPU-only configurations. diff --git a/README.md b/README.md index f02ba37..fa75ae6 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # 🖼️ Local AI Image Generator -### An easy, zero-setup Stable Diffusion GUI for Windows. Run GGUF & Safetensors models offline without Python configuration. +### An easy, zero-setup Stable Diffusion GUI for Windows and Linux. Run GGUF & Safetensors models offline without Python configuration. @@ -22,20 +22,29 @@ --- ## 📖 Overview -**Local AI Image Generator** is a zero-configuration, portable desktop environment for running Stable Diffusion (Safetensors/GGUF/CKPT) offline on Windows. Double-clicking `start.bat` automatically handles dependency setup, GPU backend matching (CUDA/Vulkan), and launches a high-performance local web workspace. +**Local AI Image Generator** is a zero-configuration, portable desktop environment for running Stable Diffusion (Safetensors/GGUF/CKPT) offline on Windows and Linux. Double-clicking `start.bat` (Windows) or running `./start.sh` (Linux) automatically handles dependency setup, GPU backend matching, and launches a high-performance local web workspace. --- ## ⚡ Quick Start + +### Windows 1. **Launch:** Double-click **`start.bat`** (downloads portable Node.js and pre-compiled GPU backend binaries on first run). 2. **Add Models:** Drop `.safetensors`, `.gguf`, or `.ckpt` weights into `app/models/` (or download them via the **Model Manager** tab in the UI). 3. **Generate:** Open `http://localhost:1420` in your browser, select your model, and write a prompt. +### Linux +1. **Check compatibility:** Prebuilt Linux backends are built on Ubuntu 24.04 and require **glibc 2.38+**. Run `ldd --version` to verify. +2. **Launch:** Open a terminal in the project folder and run **`./start.sh`** (downloads portable Node.js and pre-compiled GPU backend binaries on first run). + - For maximum AMD GPU performance, use **`./start.sh --max-perf`** on first setup (adds the ROCm backend). +3. **Add Models:** Drop `.safetensors`, `.gguf`, or `.ckpt` weights into `app/models/` (or download them via the **Model Manager** tab in the UI). +4. **Generate:** Open `http://localhost:1420` in your browser, select your model, and write a prompt. + --- ## ✨ Features * **100% Offline & Private:** Inference runs completely locally on your hardware. -* **Auto-Detected GPU Acceleration:** Configures **CUDA** for Nvidia cards, and **Vulkan** for AMD or Intel Arc GPUs. +* **Auto-Detected GPU Acceleration:** Configures **CUDA** for Nvidia cards, **ROCm** for AMD cards, and **Vulkan** for AMD/Intel/NVIDIA fallback. * **Zero System Footprint:** Node.js is sandboxed inside the folder. No global environment paths are altered. * **Integrated Model Manager:** Paste a Hugging Face URL to download weights directly, or drag-and-drop local weight files to import them. * **Real-time Telemetry:** Monitor RAM, VRAM, CPU, and GPU load directly in the UI. @@ -46,13 +55,17 @@ ## 📁 Repository Structure ``` local-ai-image-generator/ -├── start.bat # Main double-click entrypoint +├── start.bat # Main double-click entrypoint (Windows) +├── start.sh # Main terminal entrypoint (Linux) +├── PLAN.md # Linux port implementation plan ├── LICENSE # MIT Open Source license ├── .gitignore ├── README.md ├── scripts/ -│ ├── setup.ps1 # Automated GPU-detect and environment installer -│ ├── reset.ps1 # Cleans runtime environments (keeps models & outputs) +│ ├── setup.ps1 # Automated GPU-detect and environment installer (Windows) +│ ├── setup.sh # Automated GPU-detect and environment installer (Linux) +│ ├── reset.ps1 # Cleans runtime environments (Windows) +│ ├── reset.sh # Cleans runtime environments (Linux) │ └── serve.cjs # UI web server and backend lifecycle manager └── app/ ├── frontend/ # UI source code (Vite + React) @@ -64,6 +77,8 @@ local-ai-image-generator/ ## 🖥️ GPU Compatibility Matrix +### Windows + | GPU Vendor | Tech | Status | Notes | | :--- | :--- | :--- | :--- | | **Nvidia** | CUDA | ✅ Native | Maps `sd-cuda.exe` with Nvidia SDK 12 optimizations. | @@ -71,6 +86,23 @@ local-ai-image-generator/ | **Intel Arc** | Vulkan | ✅ Native | Maps `sd-vulkan.exe` for Intel hardware. | | **Integrated / None** | CPU | ⚠️ Fallback | Runs on logical CPU threads (slow). | +### Linux + +| GPU Vendor | Primary | Fallback | Notes | +| :--- | :--- | :--- | :--- | +| **NVIDIA** | Vulkan | CPU | No reliable prebuilt Linux CUDA binary is currently available. NVIDIA GPUs use Vulkan. | +| **AMD Radeon** | ROCm | Vulkan | ROCm provides best AMD performance when host ROCm drivers are available. | +| **Intel Arc / integrated** | Vulkan | CPU | Cross-vendor Vulkan support. | +| **Integrated / None** | CPU | — | Runs on logical CPU threads (slow). | + +**System requirements:** +- **glibc 2.38 or newer** is required for the prebuilt Linux backends (Ubuntu 24.04, Fedora 40+, etc.). +- The setup script will warn you if your glibc is older. You can still run setup, but the prebuilt backends will not start. + +**Linux setup modes:** +- **Default (`./start.sh`)**: Downloads CPU + Vulkan backends (~120–150 MB). +- **Maximum Performance (`./start.sh --max-perf`)**: Also downloads the ROCm backend. Total download ~1.3 GB. + --- ## ⏱️ Performance Benchmarks @@ -78,6 +110,7 @@ local-ai-image-generator/ Typical generation times for an image with **20 steps** (e.g. 512x512 resolution; actual times can vary depending on specific hardware specifications, clock speeds, and system load): * **CUDA GPU (Nvidia RTX):** ~10 seconds. +* **ROCm GPU (AMD RDNA2/RDNA3):** ~15–30 seconds. * **Vulkan GPU (AMD / Intel Arc):** ~89 seconds. * **GTX Vulkan Fallback (Nvidia GTX):** ~30 seconds (Vulkan runs significantly faster on legacy GTX series cards since they lack Tensor Cores). * **CPU (Fallback):** ~150 - 300+ seconds (highly dependent on processor core count, speed, and AVX instruction sets). @@ -85,8 +118,58 @@ 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). +* **Reset Environment:** If a build fails or you want to clear dependencies, run `scripts/reset.ps1` (Windows) or `scripts/reset.sh` (Linux). (This preserves your models and generated images). * **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. +* **Linux backends fail to start with `GLIBC_2.38' not found`:** The prebuilt binaries require glibc 2.38+ (Ubuntu 24.04). Upgrade your distribution or build stable-diffusion.cpp from source (see below). +* **Linux ROCm not loading:** Make sure your AMD GPU and kernel are compatible with ROCm 7.13. The app will automatically fall back to Vulkan if ROCm cannot initialize. +* **Generation shows "server is not responding or crashed":** The backend process exited. Check the terminal where you ran `./start.sh` for the exact error (common causes are glibc mismatch, missing Vulkan drivers, or out-of-memory). + +--- + +## 🔨 Building Linux Backends From Source + +If your distribution has an older glibc than 2.38, or you want a CUDA backend on Linux, you can build `stable-diffusion.cpp` directly on your machine. The resulting binary will be linked against your system's glibc and will not have the compatibility issues of the prebuilt releases. + +### Requirements +- `git`, `cmake`, `make` (or `ninja`), and a C++17 compiler (`g++` / `clang++`). +- For **CUDA**: the NVIDIA CUDA toolkit (`nvcc`) must be on your `PATH`. +- For **Vulkan**: the Vulkan SDK / loader and a compatible driver. +- For **ROCm**: AMD ROCm development libraries. + +### Build commands + +```bash +# 1. Clone upstream +git clone https://github.com/leejet/stable-diffusion.cpp.git +cd stable-diffusion.cpp +mkdir build && cd build + +# 2. Configure for your backend (pick ONE) +# CPU only +cmake .. -DSD_BUILD_SHARED_LIBS=ON -DCMAKE_BUILD_TYPE=Release + +# CUDA +cmake .. -DSD_CUDA=ON -DSD_BUILD_SHARED_LIBS=ON -DCMAKE_BUILD_TYPE=Release + +# Vulkan +cmake .. -DSD_VULKAN=ON -DSD_BUILD_SHARED_LIBS=ON -DCMAKE_BUILD_TYPE=Release + +# ROCm +cmake .. -DSD_HIPBLAS=ON -DSD_BUILD_SHARED_LIBS=ON -DCMAKE_BUILD_TYPE=Release + +# 3. Build +cmake --build . --config Release -j$(nproc) + +# 4. Copy the binaries into this project +cp bin/sd* /path/to/Local-AI-Image-Generator/app/backend/linux// +``` + +After copying, rename the server binary to match what `scripts/serve.cjs` expects: +- CPU: `sd` → `sd-cpu` +- Vulkan: `sd` → `sd-vulkan` +- ROCm: `sd` → `sd-rocm` + +Then restart the app with `./start.sh`. --- diff --git a/app/dist/assets/event-DeDJUvqC.js b/app/dist/assets/event-Df1n27Ua.js similarity index 94% rename from app/dist/assets/event-DeDJUvqC.js rename to app/dist/assets/event-Df1n27Ua.js index 30180c4..4628874 100644 --- a/app/dist/assets/event-DeDJUvqC.js +++ b/app/dist/assets/event-Df1n27Ua.js @@ -1 +1 @@ -import{i as D,t as i}from"./index-jXnaCwmK.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}; +import{i as D,t as i}from"./index-CG3WZqfX.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-CG3WZqfX.js b/app/dist/assets/index-CG3WZqfX.js new file mode 100644 index 0000000..8b288ae --- /dev/null +++ b/app/dist/assets/index-CG3WZqfX.js @@ -0,0 +1,23 @@ +(function(){const b=document.createElement("link").relList;if(b&&b.supports&&b.supports("modulepreload"))return;for(const x of document.querySelectorAll('link[rel="modulepreload"]'))r(x);new MutationObserver(x=>{for(const E of x)if(E.type==="childList")for(const q of E.addedNodes)q.tagName==="LINK"&&q.rel==="modulepreload"&&r(q)}).observe(document,{childList:!0,subtree:!0});function N(x){const E={};return x.integrity&&(E.integrity=x.integrity),x.referrerPolicy&&(E.referrerPolicy=x.referrerPolicy),x.crossOrigin==="use-credentials"?E.credentials="include":x.crossOrigin==="anonymous"?E.credentials="omit":E.credentials="same-origin",E}function r(x){if(x.ep)return;x.ep=!0;const E=N(x);fetch(x.href,E)}})();function fm(f){return f&&f.__esModule&&Object.prototype.hasOwnProperty.call(f,"default")?f.default:f}var Rs={exports:{}},ai={};var Zd;function Ny(){if(Zd)return ai;Zd=1;var f=Symbol.for("react.transitional.element"),b=Symbol.for("react.fragment");function N(r,x,E){var q=null;if(E!==void 0&&(q=""+E),x.key!==void 0&&(q=""+x.key),"key"in x){E={};for(var H in x)H!=="key"&&(E[H]=x[H])}else E=x;return x=E.ref,{$$typeof:f,type:r,key:q,ref:x!==void 0?x:null,props:E}}return ai.Fragment=b,ai.jsx=N,ai.jsxs=N,ai}var Kd;function Ey(){return Kd||(Kd=1,Rs.exports=Ny()),Rs.exports}var c=Ey(),Bs={exports:{}},le={};var Jd;function Ay(){if(Jd)return le;Jd=1;var f=Symbol.for("react.transitional.element"),b=Symbol.for("react.portal"),N=Symbol.for("react.fragment"),r=Symbol.for("react.strict_mode"),x=Symbol.for("react.profiler"),E=Symbol.for("react.consumer"),q=Symbol.for("react.context"),H=Symbol.for("react.forward_ref"),w=Symbol.for("react.suspense"),h=Symbol.for("react.memo"),A=Symbol.for("react.lazy"),O=Symbol.for("react.activity"),Q=Symbol.iterator;function P(d){return d===null||typeof d!="object"?null:(d=Q&&d[Q]||d["@@iterator"],typeof d=="function"?d:null)}var J={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},$=Object.assign,fe={};function te(d,j,R){this.props=d,this.context=j,this.refs=fe,this.updater=R||J}te.prototype.isReactComponent={},te.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")},te.prototype.forceUpdate=function(d){this.updater.enqueueForceUpdate(this,d,"forceUpdate")};function lt(){}lt.prototype=te.prototype;function Ae(d,j,R){this.props=d,this.context=j,this.refs=fe,this.updater=R||J}var ke=Ae.prototype=new lt;ke.constructor=Ae,$(ke,te.prototype),ke.isPureReactComponent=!0;var Ve=Array.isArray;function De(){}var ee={H:null,A:null,T:null,S:null},Se=Object.prototype.hasOwnProperty;function ot(d,j,R){var G=R.ref;return{$$typeof:f,type:d,key:j,ref:G!==void 0?G:null,props:R}}function Mt(d,j){return ot(d.type,j,d.props)}function de(d){return typeof d=="object"&&d!==null&&d.$$typeof===f}function Ze(d){var j={"=":"=0",":":"=2"};return"$"+d.replace(/[=:]/g,function(R){return j[R]})}var ct=/\/+/g;function Ke(d,j){return typeof d=="object"&&d!==null&&d.key!=null?Ze(""+d.key):j.toString(36)}function Le(d){switch(d.status){case"fulfilled":return d.value;case"rejected":throw d.reason;default:switch(typeof d.status=="string"?d.then(De,De):(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 _(d,j,R,G,V){var I=typeof d;(I==="undefined"||I==="boolean")&&(d=null);var se=!1;if(d===null)se=!0;else switch(I){case"bigint":case"string":case"number":se=!0;break;case"object":switch(d.$$typeof){case f:case b:se=!0;break;case A:return se=d._init,_(se(d._payload),j,R,G,V)}}if(se)return V=V(d),se=G===""?"."+Ke(d,0):G,Ve(V)?(R="",se!=null&&(R=se.replace(ct,"$&/")+"/"),_(V,j,R,"",function(yt){return yt})):V!=null&&(de(V)&&(V=Mt(V,R+(V.key==null||d&&d.key===V.key?"":(""+V.key).replace(ct,"$&/")+"/")+se)),j.push(V)),1;se=0;var Qe=G===""?".":G+":";if(Ve(d))for(var Me=0;Me>>1,ce=_[me];if(0>>1;mex(R,Z))Gx(V,R)?(_[me]=V,_[G]=Z,me=G):(_[me]=R,_[j]=Z,me=j);else if(Gx(V,Z))_[me]=V,_[G]=Z,me=G;else break e}}return C}function x(_,C){var Z=_.sortIndex-C.sortIndex;return Z!==0?Z:_.id-C.id}if(f.unstable_now=void 0,typeof performance=="object"&&typeof performance.now=="function"){var E=performance;f.unstable_now=function(){return E.now()}}else{var q=Date,H=q.now();f.unstable_now=function(){return q.now()-H}}var w=[],h=[],A=1,O=null,Q=3,P=!1,J=!1,$=!1,fe=!1,te=typeof setTimeout=="function"?setTimeout:null,lt=typeof clearTimeout=="function"?clearTimeout:null,Ae=typeof setImmediate<"u"?setImmediate:null;function ke(_){for(var C=N(h);C!==null;){if(C.callback===null)r(h);else if(C.startTime<=_)r(h),C.sortIndex=C.expirationTime,b(w,C);else break;C=N(h)}}function Ve(_){if($=!1,ke(_),!J)if(N(w)!==null)J=!0,De||(De=!0,Ze());else{var C=N(h);C!==null&&Le(Ve,C.startTime-_)}}var De=!1,ee=-1,Se=5,ot=-1;function Mt(){return fe?!0:!(f.unstable_now()-ot_&&Mt());){var me=O.callback;if(typeof me=="function"){O.callback=null,Q=O.priorityLevel;var ce=me(O.expirationTime<=_);if(_=f.unstable_now(),typeof ce=="function"){O.callback=ce,ke(_),C=!0;break t}O===N(w)&&r(w),ke(_)}else r(w);O=N(w)}if(O!==null)C=!0;else{var d=N(h);d!==null&&Le(Ve,d.startTime-_),C=!1}}break e}finally{O=null,Q=Z,P=!1}C=void 0}}finally{C?Ze():De=!1}}}var Ze;if(typeof Ae=="function")Ze=function(){Ae(de)};else if(typeof MessageChannel<"u"){var ct=new MessageChannel,Ke=ct.port2;ct.port1.onmessage=de,Ze=function(){Ke.postMessage(null)}}else Ze=function(){te(de,0)};function Le(_,C){ee=te(function(){_(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(_){_.callback=null},f.unstable_forceFrameRate=function(_){0>_||125<_?console.error("forceFrameRate takes a positive int between 0 and 125, forcing frame rates higher than 125 fps is not supported"):Se=0<_?Math.floor(1e3/_):5},f.unstable_getCurrentPriorityLevel=function(){return Q},f.unstable_next=function(_){switch(Q){case 1:case 2:case 3:var C=3;break;default:C=Q}var Z=Q;Q=C;try{return _()}finally{Q=Z}},f.unstable_requestPaint=function(){fe=!0},f.unstable_runWithPriority=function(_,C){switch(_){case 1:case 2:case 3:case 4:case 5:break;default:_=3}var Z=Q;Q=_;try{return C()}finally{Q=Z}},f.unstable_scheduleCallback=function(_,C,Z){var me=f.unstable_now();switch(typeof Z=="object"&&Z!==null?(Z=Z.delay,Z=typeof Z=="number"&&0me?(_.sortIndex=Z,b(h,_),N(w)===null&&_===N(h)&&($?(lt(ee),ee=-1):$=!0,Le(Ve,Z-me))):(_.sortIndex=ce,b(w,_),J||P||(J=!0,De||(De=!0,Ze()))),_},f.unstable_shouldYield=Mt,f.unstable_wrapCallback=function(_){var C=Q;return function(){var Z=Q;Q=C;try{return _.apply(this,arguments)}finally{Q=Z}}}})(qs)),qs}var Fd;function Oy(){return Fd||(Fd=1,Gs.exports=Cy()),Gs.exports}var Ls={exports:{}},Tt={};var Id;function Uy(){if(Id)return Tt;Id=1;var f=Zs();function b(w){var h="https://react.dev/errors/"+w;if(1"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(f)}catch(b){console.error(b)}}return f(),Ls.exports=Uy(),Ls.exports}var em;function Ry(){if(em)return ni;em=1;var f=Oy(),b=Zs(),N=wy();function r(e){var t="https://react.dev/errors/"+e;if(1ce||(e.current=me[ce],me[ce]=null,ce--)}function R(e,t){ce++,me[ce]=e.current,e.current=t}var G=d(null),V=d(null),I=d(null),se=d(null);function Qe(e,t){switch(R(I,t),R(V,e),R(G,null),t.nodeType){case 9:case 11:e=(e=t.documentElement)&&(e=e.namespaceURI)?yd(e):0;break;default:if(e=t.tagName,t=t.namespaceURI)t=yd(t),e=gd(t,e);else switch(e){case"svg":e=1;break;case"math":e=2;break;default:e=0}}j(G),R(G,e)}function Me(){j(G),j(V),j(I)}function yt(e){e.memoizedState!==null&&R(se,e);var t=G.current,l=gd(t,e.type);t!==l&&(R(V,e),R(G,l))}function Nt(e){V.current===e&&(j(G),j(V)),se.current===e&&(j(se),Pn._currentValue=Z)}var Je,Ht;function zt(e){if(Je===void 0)try{throw Error()}catch(l){var t=l.stack.trim().match(/\n( *(at )?)/);Je=t&&t[1]||"",Ht=-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:"")?zt(l):""}function D(e,t){switch(e.tag){case 26:case 27:case 5:return zt(e.type);case 16:return zt("Lazy");case 13:return e.child!==t&&t!==null?zt("Suspense Fallback"):zt("Suspense");case 19:return zt("SuspenseList");case 0:case 15:return ie(e.type,!1);case 11:return ie(e.type.render,!1);case 1:return ie(e.type,!0);case 31:return zt("Activity");default:return""}}function B(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 W=Object.prototype.hasOwnProperty,ae=f.unstable_scheduleCallback,At=f.unstable_cancelCallback,Gt=f.unstable_shouldYield,dl=f.unstable_requestPaint,we=f.unstable_now,al=f.unstable_getCurrentPriorityLevel,$e=f.unstable_ImmediatePriority,za=f.unstable_UserBlockingPriority,Ta=f.unstable_NormalPriority,L=f.unstable_LowPriority,he=f.unstable_IdlePriority,Re=f.log,gt=f.unstable_setDisableYieldValue,st=null,Pe=null;function qt(e){if(typeof Re=="function"&>(e),Pe&&typeof Pe.setStrictMode=="function")try{Pe.setStrictMode(st,e)}catch{}}var rt=Math.clz32?Math.clz32:be,pt=Math.log,ve=Math.LN2;function be(e){return e>>>=0,e===0?32:31-(pt(e)/ve|0)|0}var Be=256,xe=262144,We=4194304;function _e(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 dt(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=_e(a):(u&=s,u!==0?n=_e(u):l||(l=s&~e,l!==0&&(n=_e(l))))):(s=a&~i,s!==0?n=_e(s):u!==0?n=_e(u):l||(l=a&~e,l!==0&&(n=_e(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 vt(e,t){return(e.pendingLanes&~(e.suspendedLanes&~e.pingedLanes)&t)===0}function cl(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 ci(){var e=We;return We<<=1,(We&62914560)===0&&(We=4194304),e}function ju(e){for(var t=[],l=0;31>l;l++)t.push(e);return t}function mn(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 Jt(e){return e.replace(xm,function(t){return"\\"+t.charCodeAt(0).toString(16)+" "})}function Au(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=""+Kt(t)):e.value!==""+Kt(t)&&(e.value=""+Kt(t)):u!=="submit"&&u!=="reset"||e.removeAttribute("value"),t!=null?Du(e,u,Kt(t)):l!=null?Du(e,u,Kt(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=""+Kt(s):e.removeAttribute("name")}function sf(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)){Eu(e);return}l=l!=null?""+Kt(l):"",t=t!=null?""+Kt(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),Eu(e)}function Du(e,t,l){t==="number"&&oi(e.ownerDocument)===e||e.defaultValue===""+l||(e.defaultValue=""+l)}function Ca(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"),Ru=!1;if(yl)try{var pn={};Object.defineProperty(pn,"passive",{get:function(){Ru=!0}}),window.addEventListener("test",pn,pn),window.removeEventListener("test",pn,pn)}catch{Ru=!1}var Ul=null,Bu=null,di=null;function yf(){if(di)return di;var e,t=Bu,l=t.length,a,n="value"in Ul?Ul.value:Ul.textContent,i=n.length;for(e=0;e=Sn),xf=" ",_f=!1;function jf(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 zf(e){return e=e.detail,typeof e=="object"&&"data"in e?e.data:null}var Ra=!1;function Fm(e,t){switch(e){case"compositionend":return zf(t);case"keypress":return t.which!==32?null:(_f=!0,xf);case"textInput":return e=t.data,e===xf&&_f?null:e;default:return null}}function Im(e,t){if(Ra)return e==="compositionend"||!Yu&&jf(e,t)?(e=yf(),di=Bu=Ul=null,Ra=!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=Of(l)}}function wf(e,t){return e&&t?e===t?!0:e&&e.nodeType===3?!1:t&&t.nodeType===3?wf(e,t.parentNode):"contains"in e?e.contains(t):e.compareDocumentPosition?!!(e.compareDocumentPosition(t)&16):!1:!1}function Rf(e){e=e!=null&&e.ownerDocument!=null&&e.ownerDocument.defaultView!=null?e.ownerDocument.defaultView:window;for(var t=oi(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=oi(e.document)}return t}function ku(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=yl&&"documentMode"in document&&11>=document.documentMode,Ba=null,Vu=null,zn=null,Zu=!1;function Bf(e,t,l){var a=l.window===l?l.document:l.nodeType===9?l:l.ownerDocument;Zu||Ba==null||Ba!==oi(a)||(a=Ba,"selectionStart"in a&&ku(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}),zn&&jn(zn,a)||(zn=a,a=iu(Vu,"onSelect"),0>=u,n-=u,sl=1<<32-rt(t)+n|l<ue?(ge=X,X=null):ge=X.sibling;var ze=v(y,X,g[ue],T);if(ze===null){X===null&&(X=ge);break}e&&X&&ze.alternate===null&&t(y,X),m=i(ze,m,ue),je===null?K=ze:je.sibling=ze,je=ze,X=ge}if(ue===g.length)return l(y,X),pe&&pl(y,ue),K;if(X===null){for(;ueue?(ge=X,X=null):ge=X.sibling;var ta=v(y,X,ze.value,T);if(ta===null){X===null&&(X=ge);break}e&&X&&ta.alternate===null&&t(y,X),m=i(ta,m,ue),je===null?K=ta:je.sibling=ta,je=ta,X=ge}if(ze.done)return l(y,X),pe&&pl(y,ue),K;if(X===null){for(;!ze.done;ue++,ze=g.next())ze=M(y,ze.value,T),ze!==null&&(m=i(ze,m,ue),je===null?K=ze:je.sibling=ze,je=ze);return pe&&pl(y,ue),K}for(X=a(X);!ze.done;ue++,ze=g.next())ze=S(X,y,ue,ze.value,T),ze!==null&&(e&&ze.alternate!==null&&X.delete(ze.key===null?ue:ze.key),m=i(ze,m,ue),je===null?K=ze:je.sibling=ze,je=ze);return e&&X.forEach(function(My){return t(y,My)}),pe&&pl(y,ue),K}function Ue(y,m,g,T){if(typeof g=="object"&&g!==null&&g.type===$&&g.key===null&&(g=g.props.children),typeof g=="object"&&g!==null){switch(g.$$typeof){case P:e:{for(var K=g.key;m!==null;){if(m.key===K){if(K=g.type,K===$){if(m.tag===7){l(y,m.sibling),T=n(m,g.props.children),T.return=y,y=T;break e}}else if(m.elementType===K||typeof K=="object"&&K!==null&&K.$$typeof===Se&&ga(K)===m.type){l(y,m.sibling),T=n(m,g.props),Dn(T,g),T.return=y,y=T;break e}l(y,m);break}else t(y,m);m=m.sibling}g.type===$?(T=ra(g.props.children,y.mode,T,g.key),T.return=y,y=T):(T=_i(g.type,g.key,g.props,null,y.mode,T),Dn(T,g),T.return=y,y=T)}return u(y);case J:e:{for(K=g.key;m!==null;){if(m.key===K)if(m.tag===4&&m.stateNode.containerInfo===g.containerInfo&&m.stateNode.implementation===g.implementation){l(y,m.sibling),T=n(m,g.children||[]),T.return=y,y=T;break e}else{l(y,m);break}else t(y,m);m=m.sibling}T=Pu(g,y.mode,T),T.return=y,y=T}return u(y);case Se:return g=ga(g),Ue(y,m,g,T)}if(Le(g))return Y(y,m,g,T);if(Ze(g)){if(K=Ze(g),typeof K!="function")throw Error(r(150));return g=K.call(g),F(y,m,g,T)}if(typeof g.then=="function")return Ue(y,m,Ai(g),T);if(g.$$typeof===Ae)return Ue(y,m,Ti(y,g),T);Di(y,g)}return typeof g=="string"&&g!==""||typeof g=="number"||typeof g=="bigint"?(g=""+g,m!==null&&m.tag===6?(l(y,m.sibling),T=n(m,g),T.return=y,y=T):(l(y,m),T=Iu(g,y.mode,T),T.return=y,y=T),u(y)):l(y,m)}return function(y,m,g,T){try{An=0;var K=Ue(y,m,g,T);return Ka=null,K}catch(X){if(X===Za||X===Ni)throw X;var je=Yt(29,X,null,y.mode);return je.lanes=T,je.return=y,je}}}var va=io(!0),uo=io(!1),Gl=!1;function rc(e){e.updateQueue={baseState:e.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,lanes:0,hiddenCallbacks:null},callbacks:null}}function dc(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 ql(e){return{lane:e,tag:0,payload:null,callback:null,next:null}}function Ll(e,t,l){var a=e.updateQueue;if(a===null)return null;if(a=a.shared,(Te&2)!==0){var n=a.pending;return n===null?t.next=t:(t.next=n.next,n.next=t),a.pending=t,t=xi(e),Qf(e,null,l),t}return Si(e,a,t,l),xi(e)}function Cn(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,Ws(e,l)}}function mc(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 hc=!1;function On(){if(hc){var e=Va;if(e!==null)throw e}}function Un(e,t,l,a){hc=!1;var n=e.updateQueue;Gl=!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?(ye&v)===v:(a&v)===v){v!==0&&v===ka&&(hc=!0),z!==null&&(z=z.next={lane:0,tag:s.tag,payload:s.payload,callback:null,next:null});e:{var Y=e,F=s;v=t;var Ue=l;switch(F.tag){case 1:if(Y=F.payload,typeof Y=="function"){M=Y.call(Ue,M,v);break e}M=Y;break e;case 3:Y.flags=Y.flags&-65537|128;case 0:if(Y=F.payload,v=typeof Y=="function"?Y.call(Ue,M,v):Y,v==null)break e;M=O({},M,v);break e;case 2:Gl=!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),Vl|=u,e.lanes=u,e.memoizedState=M}}function co(e,t){if(typeof e!="function")throw Error(r(191,e));e.call(t)}function so(e,t){var l=e.callbacks;if(l!==null)for(e.callbacks=null,e=0;ei?i:8;var u=_.T,s={};_.T=s,Uc(e,!1,t,l);try{var o=n(),p=_.S;if(p!==null&&p(s,o),o!==null&&typeof o=="object"&&typeof o.then=="function"){var z=yh(o,a);Bn(e,t,z,Zt(e))}else Bn(e,t,a,Zt(e))}catch(M){Bn(e,t,{then:function(){},status:"rejected",reason:M},Zt())}finally{C.p=i,u!==null&&s.types!==null&&(u.types=s.types),_.T=u}}function xh(){}function Cc(e,t,l,a){if(e.tag!==5)throw Error(r(476));var n=Yo(e).queue;Lo(e,n,t,Z,l===null?xh:function(){return Xo(e),l(a)})}function Yo(e){var t=e.memoizedState;if(t!==null)return t;t={memoizedState:Z,baseState:Z,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:xl,lastRenderedState:Z},next:null};var l={};return t.next={memoizedState:l,baseState:l,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:xl,lastRenderedState:l},next:null},e.memoizedState=t,e=e.alternate,e!==null&&(e.memoizedState=t),t}function Xo(e){var t=Yo(e);t.next===null&&(t=e.alternate.memoizedState),Bn(e,t.next.queue,{},Zt())}function Oc(){return xt(Pn)}function Qo(){return tt().memoizedState}function ko(){return tt().memoizedState}function _h(e){for(var t=e.return;t!==null;){switch(t.tag){case 24:case 3:var l=Zt();e=ql(l);var a=Ll(t,e,l);a!==null&&(Bt(a,t,l),Cn(a,t,l)),t={cache:cc()},e.payload=t;return}t=t.return}}function jh(e,t,l){var a=Zt();l={lane:a,revertLane:0,gesture:null,action:l,hasEagerState:!1,eagerState:null,next:null},Li(e)?Zo(t,l):(l=Wu(e,t,l,a),l!==null&&(Bt(l,e,a),Ko(l,t,a)))}function Vo(e,t,l){var a=Zt();Bn(e,t,l,a)}function Bn(e,t,l,a){var n={lane:a,revertLane:0,gesture:null,action:l,hasEagerState:!1,eagerState:null,next:null};if(Li(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,Lt(s,u))return Si(e,t,n,0),He===null&&bi(),!1}catch{}if(l=Wu(e,t,n,a),l!==null)return Bt(l,e,a),Ko(l,t,a),!0}return!1}function Uc(e,t,l,a){if(a={lane:2,revertLane:rs(),gesture:null,action:a,hasEagerState:!1,eagerState:null,next:null},Li(e)){if(t)throw Error(r(479))}else t=Wu(e,l,a,2),t!==null&&Bt(t,e,2)}function Li(e){var t=e.alternate;return e===ne||t!==null&&t===ne}function Zo(e,t){$a=Ui=!0;var l=e.pending;l===null?t.next=t:(t.next=l.next,l.next=t),e.pending=t}function Ko(e,t,l){if((l&4194048)!==0){var a=t.lanes;a&=e.pendingLanes,l|=a,t.lanes=l,Ws(e,l)}}var Hn={readContext:xt,use:Bi,useCallback:Fe,useContext:Fe,useEffect:Fe,useImperativeHandle:Fe,useLayoutEffect:Fe,useInsertionEffect:Fe,useMemo:Fe,useReducer:Fe,useRef:Fe,useState:Fe,useDebugValue:Fe,useDeferredValue:Fe,useTransition:Fe,useSyncExternalStore:Fe,useId:Fe,useHostTransitionStatus:Fe,useFormState:Fe,useActionState:Fe,useOptimistic:Fe,useMemoCache:Fe,useCacheRefresh:Fe};Hn.useEffectEvent=Fe;var Jo={readContext:xt,use:Bi,useCallback:function(e,t){return Et().memoizedState=[e,t===void 0?null:t],e},useContext:xt,useEffect:Co,useImperativeHandle:function(e,t,l){l=l!=null?l.concat([e]):null,Gi(4194308,4,Ro.bind(null,t,e),l)},useLayoutEffect:function(e,t){return Gi(4194308,4,e,t)},useInsertionEffect:function(e,t){Gi(4,2,e,t)},useMemo:function(e,t){var l=Et();t=t===void 0?null:t;var a=e();if(ba){qt(!0);try{e()}finally{qt(!1)}}return l.memoizedState=[a,t],a},useReducer:function(e,t,l){var a=Et();if(l!==void 0){var n=l(t);if(ba){qt(!0);try{l(t)}finally{qt(!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,ne,e),[a.memoizedState,e]},useRef:function(e){var t=Et();return e={current:e},t.memoizedState=e},useState:function(e){e=Mc(e);var t=e.queue,l=Vo.bind(null,ne,t);return t.dispatch=l,[e.memoizedState,l]},useDebugValue:Ac,useDeferredValue:function(e,t){var l=Et();return Dc(l,e,t)},useTransition:function(){var e=Mc(!1);return e=Lo.bind(null,ne,e.queue,!0,!1),Et().memoizedState=e,[!1,e]},useSyncExternalStore:function(e,t,l){var a=ne,n=Et();if(pe){if(l===void 0)throw Error(r(407));l=l()}else{if(l=t(),He===null)throw Error(r(349));(ye&127)!==0||yo(a,t,l)}n.memoizedState=l;var i={value:l,getSnapshot:t};return n.queue=i,Co(po.bind(null,a,i,e),[e]),a.flags|=2048,Fa(9,{destroy:void 0},go.bind(null,a,i,l,t),null),l},useId:function(){var e=Et(),t=He.identifierPrefix;if(pe){var l=fl,a=sl;l=(a&~(1<<32-rt(a)-1)).toString(32)+l,t="_"+t+"R_"+l,l=wi++,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[bt]=t,i[Dt]=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(jt(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&&jl(t)}}return qe(t),Kc(t,t.type,e===null?null:e.memoizedProps,t.pendingProps,l),null;case 6:if(e&&t.stateNode!=null)e.memoizedProps!==a&&jl(t);else{if(typeof a!="string"&&t.stateNode===null)throw Error(r(166));if(e=I.current,Xa(t)){if(e=t.stateNode,l=t.memoizedProps,a=null,n=St,n!==null)switch(n.tag){case 27:case 5:a=n.memoizedProps}e[bt]=t,e=!!(e.nodeValue===l||a!==null&&a.suppressHydrationWarning===!0||md(e.nodeValue,l)),e||Bl(t,!0)}else e=uu(e).createTextNode(a),e[bt]=t,t.stateNode=e}return qe(t),null;case 31:if(l=t.memoizedState,e===null||e.memoizedState!==null){if(a=Xa(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[bt]=t}else da(),(t.flags&128)===0&&(t.memoizedState=null),t.flags|=4;qe(t),e=!1}else l=ac(),e!==null&&e.memoizedState!==null&&(e.memoizedState.hydrationErrors=l),e=!0;if(!e)return t.flags&256?(Qt(t),t):(Qt(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=Xa(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[bt]=t}else da(),(t.flags&128)===0&&(t.memoizedState=null),t.flags|=4;qe(t),n=!1}else n=ac(),e!==null&&e.memoizedState!==null&&(e.memoizedState.hydrationErrors=n),n=!0;if(!n)return t.flags&256?(Qt(t),t):(Qt(t),null)}return Qt(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),Vi(t,t.updateQueue),qe(t),null);case 4:return Me(),e===null&&ys(t.stateNode.containerInfo),qe(t),null;case 10:return bl(t.type),qe(t),null;case 19:if(j(et),a=t.memoizedState,a===null)return qe(t),null;if(n=(t.flags&128)!==0,i=a.rendering,i===null)if(n)qn(a,!1);else{if(Ie!==0||e!==null&&(e.flags&128)!==0)for(e=t.child;e!==null;){if(i=Oi(e),i!==null){for(t.flags|=128,qn(a,!1),e=i.updateQueue,t.updateQueue=e,Vi(t,e),t.subtreeFlags=0,e=l,l=t.child;l!==null;)kf(l,e),l=l.sibling;return R(et,et.current&1|2),pe&&pl(t,a.treeForkCount),t.child}e=e.sibling}a.tail!==null&&we()>Wi&&(t.flags|=128,n=!0,qn(a,!1),t.lanes=4194304)}else{if(!n)if(e=Oi(i),e!==null){if(t.flags|=128,n=!0,e=e.updateQueue,t.updateQueue=e,Vi(t,e),qn(a,!0),a.tail===null&&a.tailMode==="hidden"&&!i.alternate&&!pe)return qe(t),null}else 2*we()-a.renderingStartTime>Wi&&l!==536870912&&(t.flags|=128,n=!0,qn(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=we(),e.sibling=null,l=et.current,R(et,n?l&1|2:l&1),pe&&pl(t,a.treeForkCount),e):(qe(t),null);case 22:case 23:return Qt(t),gc(),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&&Vi(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(ya),null;case 24:return l=null,e!==null&&(l=e.memoizedState.cache),t.memoizedState.cache!==l&&(t.flags|=2048),bl(at),qe(t),null;case 25:return null;case 30:return null}throw Error(r(156,t.tag))}function Eh(e,t){switch(tc(t),t.tag){case 1:return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 3:return bl(at),Me(),e=t.flags,(e&65536)!==0&&(e&128)===0?(t.flags=e&-65537|128,t):null;case 26:case 27:case 5:return Nt(t),null;case 31:if(t.memoizedState!==null){if(Qt(t),t.alternate===null)throw Error(r(340));da()}return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 13:if(Qt(t),e=t.memoizedState,e!==null&&e.dehydrated!==null){if(t.alternate===null)throw Error(r(340));da()}return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 19:return j(et),null;case 4:return Me(),null;case 10:return bl(t.type),null;case 22:case 23:return Qt(t),gc(),e!==null&&j(ya),e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 24:return bl(at),null;case 25:return null;default:return null}}function vr(e,t){switch(tc(t),t.tag){case 3:bl(at),Me();break;case 26:case 27:case 5:Nt(t);break;case 4:Me();break;case 31:t.memoizedState!==null&&Qt(t);break;case 13:Qt(t);break;case 19:j(et);break;case 10:bl(t.type);break;case 22:case 23:Qt(t),gc(),e!==null&&j(ya);break;case 24:bl(at)}}function Ln(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){Ee(t,t.return,s)}}function Ql(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){Ee(n,o,z)}}}a=a.next}while(a!==i)}}catch(z){Ee(t,t.return,z)}}function br(e){var t=e.updateQueue;if(t!==null){var l=e.stateNode;try{so(t,l)}catch(a){Ee(e,e.return,a)}}}function Sr(e,t,l){l.props=Sa(e.type,e.memoizedProps),l.state=e.memoizedState;try{l.componentWillUnmount()}catch(a){Ee(e,t,a)}}function Yn(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){Ee(e,t,n)}}function ol(e,t){var l=e.ref,a=e.refCleanup;if(l!==null)if(typeof a=="function")try{a()}catch(n){Ee(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){Ee(e,t,n)}else l.current=null}function xr(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){Ee(e,e.return,n)}}function Jc(e,t,l){try{var a=e.stateNode;Wh(a,e.type,l,t),a[Dt]=t}catch(n){Ee(e,e.return,n)}}function _r(e){return e.tag===5||e.tag===3||e.tag===26||e.tag===27&&Wl(e.type)||e.tag===4}function $c(e){e:for(;;){for(;e.sibling===null;){if(e.return===null||_r(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&&Wl(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 Wc(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=hl));else if(a!==4&&(a===27&&Wl(e.type)&&(l=e.stateNode,t=null),e=e.child,e!==null))for(Wc(e,t,l),e=e.sibling;e!==null;)Wc(e,t,l),e=e.sibling}function Zi(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&&Wl(e.type)&&(l=e.stateNode),e=e.child,e!==null))for(Zi(e,t,l),e=e.sibling;e!==null;)Zi(e,t,l),e=e.sibling}function jr(e){var t=e.stateNode,l=e.memoizedProps;try{for(var a=e.type,n=t.attributes;n.length;)t.removeAttributeNode(n[0]);jt(t,a,l),t[bt]=e,t[Dt]=l}catch(i){Ee(e,e.return,i)}}var zl=!1,ut=!1,Fc=!1,zr=typeof WeakSet=="function"?WeakSet:Set,ht=null;function Ah(e,t){if(e=e.containerInfo,vs=mu,e=Rf(e),ku(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(bs={focusedElem:e,selectionRange:l},mu=!1,ht=t;ht!==null;)if(t=ht,e=t.child,(t.subtreeFlags&1028)!==0&&e!==null)e.return=t,ht=e;else for(;ht!==null;){switch(t=ht,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"))),jt(i,a,l),i[bt]=e,mt(i),a=i;break e;case"link":var u=Dd("link","href",n).get(a+(l.href||""));if(u){for(var s=0;sUe&&(u=Ue,Ue=F,F=u);var y=Uf(s,F),m=Uf(s,Ue);if(y&&m&&(S.rangeCount!==1||S.anchorNode!==y.node||S.anchorOffset!==y.offset||S.focusNode!==m.node||S.focusOffset!==m.offset)){var g=M.createRange();g.setStart(y.node,y.offset),S.removeAllRanges(),F>Ue?(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,_.T=null,l=ns,ns=null;var i=Kl,u=Al;if(ft=0,ln=Kl=null,Al=0,(Te&6)!==0)throw Error(r(331));var s=Te;if(Te|=4,Rr(i.current),Or(i,i.current,u,l),Te=s,Kn(0,!1),Pe&&typeof Pe.onPostCommitFiberRoot=="function")try{Pe.onPostCommitFiberRoot(st,i)}catch{}return!0}finally{C.p=n,_.T=a,Pr(e,t)}}function td(e,t,l){t=Wt(l,t),t=Hc(e.stateNode,t,2),e=Ll(e,t,2),e!==null&&(mn(e,2),rl(e))}function Ee(e,t,l){if(e.tag===3)td(e,e,l);else for(;t!==null;){if(t.tag===3){td(t,e,l);break}else if(t.tag===1){var a=t.stateNode;if(typeof t.type.getDerivedStateFromError=="function"||typeof a.componentDidCatch=="function"&&(Zl===null||!Zl.has(a))){e=Wt(l,e),l=lr(2),a=Ll(t,l,2),a!==null&&(ar(l,a,t,e),mn(a,2),rl(a));break}}t=t.return}}function ss(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)||(es=!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,He===e&&(ye&l)===l&&(Ie===4||Ie===3&&(ye&62914560)===ye&&300>we()-$i?(Te&2)===0&&an(e,0):ts|=l,tn===ye&&(tn=0)),rl(e)}function ld(e,t){t===0&&(t=ci()),e=oa(e,t),e!==null&&(mn(e,t),rl(e))}function Gh(e){var t=e.memoizedState,l=0;t!==null&&(l=t.retryLane),ld(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),ld(e,l)}function Lh(e,t){return ae(e,t)}var lu=null,un=null,fs=!1,au=!1,os=!1,$l=0;function rl(e){e!==un&&e.next===null&&(un===null?lu=un=e:un=un.next=e),au=!0,fs||(fs=!0,Xh())}function Kn(e,t){if(!os&&au){os=!0;do for(var l=!1,a=lu;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-rt(42|e)+1)-1,i&=n&~(u&~s),i=i&201326741?i&201326741|1:i?i|2:0}i!==0&&(l=!0,ud(a,i))}else i=ye,i=dt(a,a===He?i:0,a.cancelPendingCommit!==null||a.timeoutHandle!==-1),(i&3)===0||vt(a,i)||(l=!0,ud(a,i));a=a.next}while(l);os=!1}}function Yh(){ad()}function ad(){au=fs=!1;var e=0;$l!==0&&Ih()&&(e=$l);for(var t=we(),l=null,a=lu;a!==null;){var n=a.next,i=nd(a,t);i===0?(a.next=null,l===null?lu=n:l.next=n,n===null&&(un=l)):(l=a,(e!==0||(i&3)!==0)&&(au=!0)),a=n}ft!==0&&ft!==5||Kn(e),$l!==0&&($l=0)}function nd(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&&hd(M)&&(o=o.responseEnd,u+=z*(o"u"?null:document;function Md(e,t,l){var a=cn;if(a&&typeof t=="string"&&t){var n=Jt(t);n='link[rel="'+e+'"][href="'+n+'"]',typeof l=="string"&&(n+='[crossorigin="'+l+'"]'),Td.has(n)||(Td.add(n),e={rel:e,crossOrigin:l,href:t},a.querySelector(n)===null&&(t=a.createElement("link"),jt(t,"link",e),mt(t),a.head.appendChild(t)))}}function cy(e){Dl.D(e),Md("dns-prefetch",e,null)}function sy(e,t){Dl.C(e,t),Md("preconnect",e,t)}function fy(e,t,l){Dl.L(e,t,l);var a=cn;if(a&&e&&t){var n='link[rel="preload"][as="'+Jt(t)+'"]';t==="image"&&l&&l.imageSrcSet?(n+='[imagesrcset="'+Jt(l.imageSrcSet)+'"]',typeof l.imageSizes=="string"&&(n+='[imagesizes="'+Jt(l.imageSizes)+'"]')):n+='[href="'+Jt(e)+'"]';var i=n;switch(t){case"style":i=sn(e);break;case"script":i=fn(e)}ll.has(i)||(e=O({rel:"preload",href:t==="image"&&l&&l.imageSrcSet?void 0:e,as:t},l),ll.set(i,e),a.querySelector(n)!==null||t==="style"&&a.querySelector(Fn(i))||t==="script"&&a.querySelector(In(i))||(t=a.createElement("link"),jt(t,"link",e),mt(t),a.head.appendChild(t)))}}function oy(e,t){Dl.m(e,t);var l=cn;if(l&&e){var a=t&&typeof t.as=="string"?t.as:"script",n='link[rel="modulepreload"][as="'+Jt(a)+'"][href="'+Jt(e)+'"]',i=n;switch(a){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":i=fn(e)}if(!ll.has(i)&&(e=O({rel:"modulepreload",href:e},t),ll.set(i,e),l.querySelector(n)===null)){switch(a){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":if(l.querySelector(In(i)))return}a=l.createElement("link"),jt(a,"link",e),mt(a),l.head.appendChild(a)}}}function ry(e,t,l){Dl.S(e,t,l);var a=cn;if(a&&e){var n=Aa(a).hoistableStyles,i=sn(e);t=t||"default";var u=n.get(i);if(!u){var s={loading:0,preload:null};if(u=a.querySelector(Fn(i)))s.loading=5;else{e=O({rel:"stylesheet",href:e,"data-precedence":t},l),(l=ll.get(i))&&Ms(e,l);var o=u=a.createElement("link");mt(o),jt(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,su(u,t,a)}u={type:"stylesheet",instance:u,count:1,state:s},n.set(i,u)}}}function dy(e,t){Dl.X(e,t);var l=cn;if(l&&e){var a=Aa(l).hoistableScripts,n=fn(e),i=a.get(n);i||(i=l.querySelector(In(n)),i||(e=O({src:e,async:!0},t),(t=ll.get(n))&&Ns(e,t),i=l.createElement("script"),mt(i),jt(i,"link",e),l.head.appendChild(i)),i={type:"script",instance:i,count:1,state:null},a.set(n,i))}}function my(e,t){Dl.M(e,t);var l=cn;if(l&&e){var a=Aa(l).hoistableScripts,n=fn(e),i=a.get(n);i||(i=l.querySelector(In(n)),i||(e=O({src:e,async:!0,type:"module"},t),(t=ll.get(n))&&Ns(e,t),i=l.createElement("script"),mt(i),jt(i,"link",e),l.head.appendChild(i)),i={type:"script",instance:i,count:1,state:null},a.set(n,i))}}function Nd(e,t,l,a){var n=(n=I.current)?cu(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=sn(l.href),l=Aa(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=sn(l.href);var i=Aa(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(Fn(e)))&&!i._p&&(u.instance=i,u.state.loading=5),ll.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},ll.set(e,l),i||hy(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=fn(l),l=Aa(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 sn(e){return'href="'+Jt(e)+'"'}function Fn(e){return'link[rel="stylesheet"]['+e+"]"}function Ed(e){return O({},e,{"data-precedence":e.precedence,precedence:null})}function hy(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}),jt(t,"link",l),mt(t),e.head.appendChild(t))}function fn(e){return'[src="'+Jt(e)+'"]'}function In(e){return"script[async]"+e}function Ad(e,t,l){if(t.count++,t.instance===null)switch(t.type){case"style":var a=e.querySelector('style[data-href~="'+Jt(l.href)+'"]');if(a)return t.instance=a,mt(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"),mt(a),jt(a,"style",n),su(a,l.precedence,e),t.instance=a;case"stylesheet":n=sn(l.href);var i=e.querySelector(Fn(n));if(i)return t.state.loading|=4,t.instance=i,mt(i),i;a=Ed(l),(n=ll.get(n))&&Ms(a,n),i=(e.ownerDocument||e).createElement("link"),mt(i);var u=i;return u._p=new Promise(function(s,o){u.onload=s,u.onerror=o}),jt(i,"link",a),t.state.loading|=4,su(i,l.precedence,e),t.instance=i;case"script":return i=fn(l.src),(n=e.querySelector(In(i)))?(t.instance=n,mt(n),n):(a=l,(n=ll.get(i))&&(a=O({},l),Ns(a,n)),e=e.ownerDocument||e,n=e.createElement("script"),mt(n),jt(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,su(a,l.precedence,e));return t.instance}function su(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 yy(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 Od(e){return!(e.type==="stylesheet"&&(e.state.loading&3)===0)}function gy(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=sn(a.href),i=t.querySelector(Fn(n));if(i){t=i._p,t!==null&&typeof t=="object"&&typeof t.then=="function"&&(e.count++,e=ou.bind(e),t.then(e,e)),l.state.loading|=4,l.instance=i,mt(i);return}i=t.ownerDocument||t,a=Ed(a),(n=ll.get(n))&&Ms(a,n),i=i.createElement("link"),mt(i);var u=i;u._p=new Promise(function(s,o){u.onload=s,u.onerror=o}),jt(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=ou.bind(e),t.addEventListener("load",l),t.addEventListener("error",l))}}var Es=0;function py(e,t){return e.stylesheets&&e.count===0&&du(e,e.stylesheets),0Es?50:800)+t);return e.unsuspend=l,function(){e.unsuspend=null,clearTimeout(a),clearTimeout(n)}}:null}function ou(){if(this.count--,this.count===0&&(this.imgCount===0||!this.waitingForImages)){if(this.stylesheets)du(this,this.stylesheets);else if(this.unsuspend){var e=this.unsuspend;this.unsuspend=null,e()}}}var ru=null;function du(e,t){e.stylesheets=null,e.unsuspend!==null&&(e.count++,ru=new Map,t.forEach(vy,e),ru=null,ou.call(e))}function vy(e,t){if(!(t.state.loading&4)){var l=ru.get(e);if(l)var a=l.get(null);else{l=new Map,ru.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(),Hs.exports=Ry(),Hs.exports}var Hy=By();const Gy=fm(Hy);const om=(...f)=>f.filter((b,N,r)=>!!b&&b.trim()!==""&&r.indexOf(b)===N).join(" ").trim();const qy=f=>f.replace(/([a-z0-9])([A-Z])/g,"$1-$2").toLowerCase();const Ly=f=>f.replace(/^([A-Z])|[\s-_]+(\w)/g,(b,N,r)=>r?r.toUpperCase():N.toLowerCase());const lm=f=>{const b=Ly(f);return b.charAt(0).toUpperCase()+b.slice(1)};var Ys={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 Yy=f=>{for(const b in f)if(b.startsWith("aria-")||b==="role"||b==="title")return!0;return!1},Xy=U.createContext({}),Qy=()=>U.useContext(Xy),ky=U.forwardRef(({color:f,size:b,strokeWidth:N,absoluteStrokeWidth:r,className:x="",children:E,iconNode:q,...H},w)=>{const{size:h=24,strokeWidth:A=2,absoluteStrokeWidth:O=!1,color:Q="currentColor",className:P=""}=Qy()??{},J=r??O?Number(N??A)*24/Number(b??h):N??A;return U.createElement("svg",{ref:w,...Ys,width:b??h??Ys.width,height:b??h??Ys.height,stroke:f??Q,strokeWidth:J,className:om("lucide",P,x),...!E&&!Yy(H)&&{"aria-hidden":"true"},...H},[...q.map(([$,fe])=>U.createElement($,fe)),...Array.isArray(E)?E:[E]])});const Xe=(f,b)=>{const N=U.forwardRef(({className:r,...x},E)=>U.createElement(ky,{ref:E,iconNode:b,className:om(`lucide-${qy(lm(f))}`,`lucide-${f}`,r),...x}));return N.displayName=lm(f),N};const Vy=[["path",{d:"M20 6 9 17l-5-5",key:"1gmf2c"}]],Xs=Xe("check",Vy);const Zy=[["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"}]],am=Xe("cloud-download",Zy);const Ky=[["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"}]],Jy=Xe("copy",Ky);const $y=[["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"}]],rm=Xe("cpu",$y);const Wy=[["path",{d:"M6 2v14a2 2 0 0 0 2 2h14",key:"ron5a4"}],["path",{d:"M18 22V8a2 2 0 0 0-2-2H2",key:"7s9ehn"}]],Fy=Xe("crop",Wy);const Iy=[["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"}]],Qs=Xe("database",Iy);const Py=[["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"}]],nm=Xe("download",Py);const e0=[["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"}]],t0=Xe("folder-down",e0);const l0=[["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"}]],im=Xe("folder-open",l0);const a0=[["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"}]],xu=Xe("hard-drive",a0);const n0=[["path",{d:"M16 5h6",key:"1vod17"}],["path",{d:"M19 2v6",key:"4bpg5p"}],["path",{d:"M21 11.5V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h7.5",key:"1ue2ih"}],["path",{d:"m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21",key:"1xmnt7"}],["circle",{cx:"9",cy:"9",r:"2",key:"af1f0g"}]],i0=Xe("image-plus",n0);const u0=[["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"}]],c0=Xe("image",u0);const s0=[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["path",{d:"M12 16v-4",key:"1dtifu"}],["path",{d:"M12 8h.01",key:"e9boi3"}]],f0=Xe("info",s0);const o0=[["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"}]],r0=Xe("library",o0);const d0=[["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"}]],m0=Xe("moon",d0);const h0=[["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"}]],aa=Xe("refresh-cw",h0);const y0=[["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"}]],g0=Xe("shield",y0);const p0=[["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"}]],Ks=Xe("sliders-vertical",p0);const v0=[["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"}]],Su=Xe("sparkles",v0);const b0=[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",key:"afitv7"}]],ks=Xe("square",b0);const S0=[["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"}]],x0=Xe("sun",S0);const _0=[["path",{d:"M12 19h8",key:"baeox8"}],["path",{d:"m4 17 6-6-6-6",key:"1yngyt"}]],j0=Xe("terminal",_0);const z0=[["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"}]],rn=Xe("trash-2",z0);const T0=[["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"}]],M0=Xe("triangle-alert",T0);function N0({activeTab:f,setActiveTab:b,specs:N}){return c.jsxs("div",{className:"sidebar",children:[c.jsxs("div",{children:[c.jsxs("div",{className:"sidebar-logo",children:[c.jsx(g0,{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(c0,{size:20}),c.jsx("span",{children:"Image Generator"})]}),c.jsxs("div",{className:`nav-item ${f==="models"?"active":""}`,onClick:()=>b("models"),children:[c.jsx(t0,{size:20}),c.jsx("span",{children:"Model Manager"})]}),c.jsxs("div",{className:`nav-item ${f==="constraints"?"active":""}`,onClick:()=>b("constraints"),children:[c.jsx(Ks,{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(j0,{size:12}),c.jsx("span",{children:"Host Specifications"})]}),c.jsxs("div",{className:"sidebar-specs-item",title:N.cpu_name,children:["CPU: ",N.cpu_name]}),c.jsxs("div",{className:"sidebar-specs-item",title:N.gpu_name,children:["GPU: ",N.gpu_name]}),c.jsxs("div",{className:"sidebar-specs-item",children:["Memory: ",N.ram_total_gb.toFixed(0)," GB RAM (",N.cpu_cores_physical," Cores)"]}),c.jsxs("div",{className:"sidebar-specs-os",children:["OS: ",N.os_name]})]})]})}const E0=U.memo(N0);function A0({telemetry:f,serverRunning:b,activeModel:N,onStopServer:r,isStoppingServer:x=!1,theme:E,setTheme:q}){const H=A=>{const O=Number(A);return Number.isFinite(O)&&O>0?O.toFixed(O>=10?0:1):"--"},w=()=>b?"Server Active":"Local Mode",h=()=>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:h()}),c.jsx("span",{style:{fontWeight:600,fontSize:"0.95rem"},children:w()}),N&&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:N})]})]}),c.jsxs("div",{className:"telemetry-group",children:[c.jsx("button",{className:"theme-toggle-btn",onClick:()=>q(E==="dark"?"light":"dark"),title:`Switch to ${E==="dark"?"light":"dark"} theme`,children:E==="dark"?c.jsx(x0,{size:18}):c.jsx(m0,{size:18})}),b&&c.jsxs("button",{className:"m3-btn m3-btn-error",style:{height:"34px",padding:"0 14px"},onClick:r,disabled:x,title:"Stop local model server",children:[x?c.jsx(aa,{className:"progress-spinner",size:14}):c.jsx(ks,{size:14}),c.jsx("span",{children:x?"Stopping":"Stop Server"})]}),c.jsxs("div",{className:"telemetry-chip",title:"CPU Utilization",children:[c.jsx(rm,{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(xu,{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(Qs,{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 D0=U.memo(A0),C0="modulepreload",O0=function(f){return"/"+f},um={},U0=function(b,N,r){let x=Promise.resolve();if(N&&N.length>0){let w=function(h){return Promise.all(h.map(A=>Promise.resolve(A).then(O=>({status:"fulfilled",value:O}),O=>({status:"rejected",reason:O}))))};document.getElementsByTagName("link");const q=document.querySelector("meta[property=csp-nonce]"),H=q?.nonce||q?.getAttribute("nonce");x=w(N.map(h=>{if(h=O0(h),h in um)return;um[h]=!0;const A=h.endsWith(".css"),O=A?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${h}"]${O}`))return;const Q=document.createElement("link");if(Q.rel=A?"stylesheet":C0,A||(Q.as="script"),Q.crossOrigin="",Q.href=h,H&&Q.setAttribute("nonce",H),document.head.appendChild(Q),A)return new Promise((P,J)=>{Q.addEventListener("load",P),Q.addEventListener("error",()=>J(new Error(`Unable to preload CSS for ${h}`)))})}))}function E(q){const H=new Event("vite:preloadError",{cancelable:!0});if(H.payload=q,window.dispatchEvent(H),!H.defaultPrevented)throw q}return x.then(q=>{for(const H of q||[])H.status==="rejected"&&E(H.reason);return b().catch(E)})};function rg(f,b=!1){return window.__TAURI_INTERNALS__.transformCallback(f,b)}async function ja(f,b={},N){return window.__TAURI_INTERNALS__.invoke(f,b,N)}const ia=()=>typeof window<"u"&&window.__TAURI_INTERNALS__!==void 0;let la=null,_u=null;const w0="polish-setup-v1",na=()=>typeof window<"u"&&(window.location.hostname==="localhost"||window.location.hostname==="127.0.0.1");async function dm(){if(na())try{const f=await Cl(),b=Number(f?.port);if(Number.isInteger(b)&&b>0)return _u=b,b}catch{}return _u||8080}async function mm(){return`http://127.0.0.1:${await dm()}`}function ii(f){const b=Number(f)||0;if(b<=0)return"0 B";const N=["B","KB","MB","GB","TB"],r=Math.min(N.length-1,Math.floor(Math.log(b)/Math.log(1024)));return`${(b/1024**r).toFixed(r===0?0:1)} ${N[r]}`}function ui(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?ii(f.sizeBytes):"Unknown")}}async function dn(f,b="The local server returned an invalid response."){const N=await f.text();let r={};try{r=JSON.parse(N||"{}")}catch{const E=N.trim().startsWith("0&&(_u=Number(q.port)),console.log("Backend restart:",q.message),q.message}catch(x){if(console.warn("Could not reach management API:",x.message),na())throw x;return"Backend management unavailable"}}async function Js(){if(ia())return await ja("stop_server");try{await fetch("/api/stop-backend",{method:"POST"})}catch{}return"Backend stopped"}async function Cl(){try{return await(await fetch("/api/backend-status")).json()}catch{return{ready:!1,settings:{}}}}async function Q0(){try{return(await(await fetch("/api/outputs")).json()).outputs||[]}catch{return[]}}async function k0(f,b){const N=await fetch("/api/save-output",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({image:f,metadata:b})});return(await dn(N,"The local server returned an invalid save response.")).output}async function V0(f){const b=await fetch("/api/delete-outputs",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({outputs:f})});return await dn(b,"The local server returned an invalid delete response.")}async function Z0(){try{return((await(await fetch("/api/models")).json()).models||[]).map(ui)}catch{return[]}}async function K0(f,b,N,r,x,E,q){console.log("Initiating image generation:",{prompt:f,negativePrompt:b,constraints:N,activeModelName:r});const H=Date.now(),w=await mm(),h={prompt:f,negative_prompt:b||"",width:N.width||512,height:N.height||512,steps:N.steps||20,cfg_scale:N.cfgScale||7,seed:N.seed===-1?Math.floor(Math.random()*1e6):N.seed,sampler:N.sampler||"euler_a",image:x||null,denoising_strength:N.denoisingStrength||.7},A=!!h.image;let O=`${w}/v1/images/generations`,Q={prompt:h.prompt,negative_prompt:h.negative_prompt||"",n:1,size:`${h.width}x${h.height}`,response_format:"b64_json",steps:h.steps,cfg_scale:h.cfg_scale,seed:h.seed,sample_method:h.sampler};if(A){const P=String(h.image).replace(/^data:[^;]+;base64,/,"");O=`${w}/sdapi/v1/img2img`,Q={init_images:[P],prompt:h.prompt,negative_prompt:h.negative_prompt||"",denoising_strength:h.denoising_strength,steps:h.steps,cfg_scale:h.cfg_scale,seed:h.seed,width:h.width,height:h.height,sampler_name:h.sampler,sample_method:h.sampler,batch_size:1,n_iter:1,send_images:!0,save_images:!1}}try{const P=await fetch(O,{method:"POST",headers:{"Content-Type":"application/json"},signal:q,body:JSON.stringify(Q)});if(P.ok){const J=await P.json(),$=J?.data?.[0]?.b64_json??J?.images?.[0];if($){const fe=parseFloat(((Date.now()-H)/1e3).toFixed(1));return{image:`data:image/png;base64,${$}`,seed:J.data?.[0]?.seed??h.seed,duration_sec:fe}}}else{let J=`Generation failed (HTTP ${P.status})`;try{const $=await P.json();($?.detail||$?.error?.message)&&(J=$.detail||$.error.message)}catch{}throw new Error(J)}}catch(P){throw P.name==="AbortError"||P.message.startsWith("Generation failed")?P:(console.warn("Could not reach local server.",P),new Error("The image generation server is not responding or crashed. Try restarting the backend from Model Manager, or check the terminal for a backend error."))}}async function J0(f,b,N){if(f instanceof File){const H=f;if(!na())throw new Error("File import requires the local image generator server.");return await $0(H,b,N),{response:"Model imported successfully"}}if(ia()){const{listen:H}=await U0(async()=>{const{listen:h}=await import("./event-Df1n27Ua.js");return{listen:h}},[]);let w=null;b&&(w=await H("import-progress",h=>{b(h.payload)}));try{return{response:await ja("import_model_file",{sourcePath:f}),unlisten:w}}catch(h){throw w&&w(),h}}const r=f.split(/[\\/]/).pop()||"imported_model.gguf";console.log(`Web Mode: Simulating copying ${r} to USB models folder`);const x=40;for(let H=1;H<=x;H++){if(N?.aborted)throw new DOMException("The user aborted a request.","AbortError");await new Promise(O=>setTimeout(O,150));const w=H/x*100,h=40+Math.sin(H)*5+Math.random()*2,A=(x-H)*.15;b&&b({filename:r,progress:w,speed_mb_s:h,eta_secs:A,status:"Copying to USB..."})}const E=localStorage.getItem("imported-models"),q=E?JSON.parse(E):[];return q.includes(r)||(q.push({filename:r,sizeBytes:0,size:"Unknown"}),localStorage.setItem("imported-models",JSON.stringify(q))),{response:"Model imported successfully"}}function $0(f,b,N){return new Promise((r,x)=>{const E=new XMLHttpRequest,q=Date.now();let H=!1;E.open("POST",`/api/import-model?filename=${encodeURIComponent(f.name)}`),E.setRequestHeader("Content-Type","application/octet-stream");const w=()=>{H=!0,E.abort()};N&&(N.aborted?w():N.addEventListener("abort",w,{once:!0})),E.upload.onprogress=h=>{if(!h.lengthComputable||!b)return;const A=Math.max(.1,(Date.now()-q)/1e3),O=h.loaded/A,Q=Math.max(0,h.total-h.loaded);b({filename:f.name,progress:h.loaded/h.total*100,speed_mb_s:O/(1024*1024),eta_secs:Q/Math.max(1,O),status:"Copying to models folder..."})},E.onload=()=>{let h={};try{h=JSON.parse(E.responseText||"{}")}catch{}E.status>=200&&E.status<300&&h.ok!==!1?(b&&b({filename:f.name,progress:100,speed_mb_s:0,eta_secs:0,status:"Import complete"}),r(h)):x(new Error(h.error||`Import failed (HTTP ${E.status})`))},E.onerror=()=>x(new Error("Import failed while uploading the file.")),E.onabort=()=>x(new DOMException(H?"Import cancelled by user.":"Import aborted.","AbortError")),E.send(f)})}async function W0(f){if(ia())return await ja("delete_model_file",{filename:f});if(typeof window<"u"&&(window.location.hostname==="localhost"||window.location.hostname==="127.0.0.1"))try{const x=await fetch("/api/delete-model",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({filename:f})}),E=await x.json();if(!x.ok)throw new Error(E.error||"Failed to delete model file");return E}catch(x){throw console.error("Failed to delete model via local API:",x),x}const N=localStorage.getItem("imported-models");let r=N?JSON.parse(N):[];return r=r.filter(x=>ui(x).filename!==f),localStorage.setItem("imported-models",JSON.stringify(r)),`Simulated deletion of ${f} from browser session`}async function hm(){const f=await mm();try{return(await fetch(`${f}/v1/models`,{method:"GET"})).ok}catch{return!1}}async function F0(f=30){const b=ia()||na()?f:3;for(let N=0;NsetTimeout(x,500))}return!1}async function I0(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 P0(){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 cm(){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 eg(){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 tg=U.memo(({img:f,idx:b,isSelected:N,onClick:r})=>{const x=E=>{r(b,E)};return c.jsxs("div",{className:`gallery-item ${N?"selected":""}`,onClick:x,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"}),N&&c.jsx("div",{className:"gallery-select-badge",children:c.jsx(Xs,{size:14})})]})});function lg({prompt:f,setPrompt:b,negativePrompt:N,setNegativePrompt:r,constraints:x,setConstraints:E,activeModel:q,generatedImages:H,setGeneratedImages:w,isGenerating:h,setIsGenerating:A,generationProgress:O,setGenerationProgress:Q,setActiveTab:P,showAlert:J=async({message:fe})=>window.alert(fe),showConfirm:$=async({message:fe})=>window.confirm(fe)}){const[fe,te]=U.useState(null),[lt,Ae]=U.useState(null),[ke,Ve]=U.useState(null),[De,ee]=U.useState(!1),[Se,ot]=U.useState(0),[Mt,de]=U.useState(0),[Ze,ct]=U.useState(0),[Ke,Le]=U.useState(""),[_,C]=U.useState(!1),[Z,me]=U.useState(!1),[ce,d]=U.useState(!1),[j,R]=U.useState(null),[G,V]=U.useState(null),[I,se]=U.useState(!1),[Qe,Me]=U.useState([]),[yt,Nt]=U.useState(null),Je=U.useRef(null),Ht=U.useRef(null),zt=U.useRef(!1),k=L=>{const he=L.target.files?.[0];if(L.target.value="",!he)return;if(!he.type.startsWith("image/")){V("Please choose an image file (PNG, JPG, or WEBP).");return}const Re=new FileReader;Re.onload=()=>Nt(Re.result),Re.onerror=()=>V("Could not read the selected image file."),Re.readAsDataURL(he)},ie=()=>Nt(null),D=async()=>{if(!f.trim())return;V(null),d(!0),R(null);let L=!1;try{const ve=await Cl();if(ve&&ve.settings){const be=ve.settings,Be=be.model?be.model.split(/[\\/]/).pop():null,xe=q?q.split(/[\\/]/).pop():null;(Be!==xe||parseInt(be.steps)!==parseInt(x.steps)||Math.abs(parseFloat(be.cfgScale)-parseFloat(x.cfgScale))>.05||be.sampler!==x.sampler||parseInt(be.threads)!==parseInt(x.threads)||!!be.useGpu!=(x.useGpu!==!1)||(be.backendType||(be.useGpu===!1?"cpu":"auto"))!==(x.backendType||(x.useGpu===!1?"cpu":"auto")))&&(L=!0)}else L=!0}catch{L=!0}if(L)try{console.log("Settings out of sync, restarting backend..."),await Vs(q,x);let ve=!1,be=null;for(let Be=0;Be<240;Be++){const xe=await Cl();if(xe.loading&&R({progress:xe.loading.progress||0,phase:xe.loading.phase||"Loading model...",speed:xe.loading.speed||"",current:xe.loading.current||0,total:xe.loading.total||0,backendMode:xe.loading.backendMode||xe.settings?.backendMode||"",device:xe.loading.device||xe.settings?.backendDevice||""}),xe.ready){ve=!0;break}if(xe.error){be=xe.error;break}if(!xe.running&&Be>3){be="The backend process terminated immediately on startup.";break}await new Promise(We=>setTimeout(We,500))}if(!ve)throw new Error(be||"Backend server failed to start after applying configuration changes.")}catch(ve){console.error("Failed to restart backend:",ve),V(ve.message||"Failed to sync settings with backend."),d(!1);return}d(!1),R(null),Je.current&&clearInterval(Je.current),A(!0),Q(0),ot(0),ct(0),Le(""),zt.current=!1,C(!1),se(!1),Ve(null),te(null);const he=(x.width>=1024?140:35)*.04,Re=x.width>=1024?140:35,gt=(x.backendType||(x.useGpu===!1?"cpu":"auto"))!=="cpu";let st=gt?he:Re,Pe=!1,qt=0,rt=0,pt=0;de(Math.round(x.steps*st)),Je.current=setInterval(async()=>{pt++,ot(pt);try{const ve=await eg();if(ve&&ve.active){const be=ve.decoding||!1;se(be);const Be=be?ve.steps||x.steps||20:ve.step||0,xe=ve.steps||x.steps||20,We=be?"":ve.speed||"";(be||ve.steps>0)&&(zt.current=!0,ct(Be)),Le(be?"decoding":We);let _e=0;be?_e=99:xe>0&&(_e=Math.round(Be/xe*100)),_e=Math.min(99,_e),be||ve.steps>0?Q(_e):Q(vt=>Math.max(vt,_e));let dt=0;if(be)dt=3;else{const vt=parseFloat(We);if(!isNaN(vt)&&vt>0){const cl=Math.max(0,xe-Be);We.includes("it/s")?dt=cl/vt:We.includes("s/it")&&(dt=cl*vt)}else{const cl=gt?he:Re;dt=Math.max(0,(xe-Be)*cl)}}if(gt&&!Pe){const vt=We.includes("it/s")&&numericSpeed<.2,cl=We.includes("s/it")&&numericSpeed>5;(vt||cl)&&(Pe=!0,C(!0))}de(Math.round(dt))}else Q(be=>Math.min(15,be+1)),de(be=>Math.max(1,be-1))}catch(ve){console.warn("Failed to get generation progress, running simulation fallback:",ve),gt&&!Pe&&pt>x.steps*he*1.3&&(Pe=!0,C(!0),st=Re,qt=pt,rt=Math.min(95,Math.round(pt/(x.steps*he)*100)));let be=Math.min(x.steps-1,Math.floor(pt/st)),Be=x.steps*st;if(pt>=Be){const _e=Math.ceil(pt/Math.max(.5,be));st=Math.max(st+15,_e+15),Be=x.steps*st,be=Math.min(x.steps-1,Math.floor(pt/st))}const xe=Math.max(1,Be-pt);de(Math.round(xe));let We=0;if(Pe){const _e=99-rt,dt=Be-qt;if(dt>0){const vt=Math.min(1,(pt-qt)/dt);if(vt<.85)We=Math.round(rt+vt*_e);else{const cl=(pt-(qt+dt*.85))/(st*2),ci=1-Math.exp(-cl);We=Math.min(99,Math.round(rt+.85*_e+.14*_e*ci))}}else We=99}else if(ptMath.max(_e,We))}},1e3);try{Ht.current=new AbortController;const ve=await K0(f,N,x,q,yt,_e=>Q(dt=>Math.max(dt,_e)),Ht.current.signal);Je.current&&clearInterval(Je.current),Q(100),ct(x.steps),de(0),Le("");const be={prompt:f,negativePrompt:N,seed:ve.seed,steps:x.steps,cfgScale:x.cfgScale,width:x.width,height:x.height,sampler:x.sampler,model:q,mode:yt?"img2img":"txt2img",denoisingStrength:yt?x.denoisingStrength:null,duration_sec:ve.duration_sec,timestamp:new Date().toLocaleTimeString()};let Be=null,xe=null;try{if(Be=await k0(ve.image,be),xe=Be.url,!xe)throw new Error("The local server saved the image but did not return a file URL.")}catch(_e){throw console.error("Generated image could not be saved:",_e),new Error(`Image generated but could not be saved to USB: ${_e.message||_e}`)}te(xe),Ae(ve.seed),Ve(ve.duration_sec);const We={...be,...Be||{},url:xe};w(_e=>[We,..._e])}catch(ve){ve.name==="AbortError"?console.log("Generation request was aborted by the user"):(console.error("Generation failed:",ve),V(ve.message||"Generation failed. Please try again.")),Je.current&&clearInterval(Je.current)}finally{A(!1),Ht.current=null}},B=async()=>{if(await $({title:"Stop Generation?",message:"The current image generation will be cancelled and the local model server may restart.",confirmLabel:"Stop",danger:!0})){Je.current&&clearInterval(Je.current),me(!0),Ht.current&&Ht.current.abort();try{console.log("Cancelling: Stopping server to kill generation threads..."),await Js(),ct(0),Le(""),se(!1),zt.current=!1,q&&(console.log("Cancelling: Restarting server for future generations..."),await Vs(q,x),await F0()||console.warn("Server failed to restart properly."))}catch(L){console.error("Failed to restart server on cancellation:",L)}finally{me(!1),A(!1),Q(0),de(0)}}},W=async()=>{if(fe)try{if(fe.startsWith("data:image")){const he=await(await fetch(fe)).blob();await navigator.clipboard.write([new ClipboardItem({[he.type]:he})])}else{const L=new Image;L.crossOrigin="anonymous",L.src=fe,L.onload=async()=>{const he=document.createElement("canvas");he.width=L.width,he.height=L.height,he.getContext("2d").drawImage(L,0,0),he.toBlob(async gt=>{await navigator.clipboard.write([new ClipboardItem({[gt.type]:gt})])},"image/png")}}ee(!0),setTimeout(()=>ee(!1),2e3)}catch(L){console.error("Failed to copy image:",L)}},ae=()=>{if(!fe)return;const L=document.createElement("a");L.href=fe,L.download=`diffusion-${lt||Date.now()}.png`,document.body.appendChild(L),L.click(),document.body.removeChild(L)},At=(L,he=`diffusion-${Date.now()}.png`)=>{if(!L)return;const Re=document.createElement("a");Re.href=L,Re.download=he,document.body.appendChild(Re),Re.click(),document.body.removeChild(Re)},Gt=U.useCallback(L=>{b(L.prompt),r(L.negativePrompt),E(he=>({...he,steps:L.steps,cfgScale:L.cfgScale,width:L.width,height:L.height,sampler:L.sampler,seed:L.seed})),te(L.url),Ae(L.seed),Ve(L.duration_sec??L.durationSec??null)},[b,r,E]),dl=U.useCallback((L,he)=>{const Re=he.ctrlKey||he.metaKey||he.shiftKey;Me(gt=>Re?gt.includes(L)?gt.filter(st=>st!==L):[...gt,L]:[L]),H[L]&&Gt(H[L])},[H,Gt]),we=Qe.map(L=>H[L]).filter(Boolean),al=()=>{Me([])},$e=()=>{we[0]&&Gt(we[0])},za=()=>{we.forEach((L,he)=>{const Re=L.seed??Date.now();At(L.url,`diffusion-${Re}-${he+1}.png`)})},Ta=async()=>{if(we.length===0)return;const L=we.length;if(await $({title:"Delete Selected Outputs?",message:`Delete ${L} selected output${L===1?"":"s"} from USB? This removes the image and metadata files.`,confirmLabel:"Delete",danger:!0}))try{await V0(we);const Re=new Set(Qe);w(gt=>gt.filter((st,Pe)=>!Re.has(Pe))),Me([]),we.some(gt=>gt.url===fe)&&(te(null),Ae(null),Ve(null))}catch(Re){console.error("Failed to delete selected outputs:",Re),J({title:"Delete Failed",message:Re.message||String(Re),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(Su,{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:L=>b(L.target.value),placeholder:"Enter a descriptive prompt (e.g. 'A futuristic city in cyberpunk aesthetic, high details, cinematic lighting')...",disabled:h})]}),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:N,onChange:L=>r(L.target.value),placeholder:"Items to avoid (e.g. 'blurry, low quality, deformed hands, texts')...",disabled:h})]}),c.jsxs("div",{className:"m3-text-field",children:[c.jsx("label",{className:"m3-text-field-label",children:"Base Image (Optional)"}),yt?c.jsxs("div",{style:{display:"flex",gap:"12px",alignItems:"center",padding:"12px",background:"var(--md-sys-color-surface-variant)",borderRadius:"var(--md-shape-corner-medium)",border:"1px solid var(--md-sys-color-outline-variant)"},children:[c.jsx("img",{src:yt,alt:"Base",style:{width:"64px",height:"64px",objectFit:"cover",borderRadius:"8px",flexShrink:0}}),c.jsxs("div",{style:{flex:1,minWidth:0},children:[c.jsx("div",{style:{fontWeight:600,fontSize:"0.85rem"},children:"Base image ready"}),c.jsx("div",{style:{fontSize:"0.75rem",color:"var(--md-sys-color-outline)"},children:"The AI will redraw this image guided by your prompt."})]}),c.jsxs("button",{type:"button",className:"m3-btn m3-btn-error",style:{height:"34px",flexShrink:0},onClick:ie,disabled:h,children:[c.jsx(rn,{size:14}),c.jsx("span",{children:"Remove"})]})]}):c.jsxs("label",{className:"import-box",style:{margin:0,padding:"16px",cursor:h?"not-allowed":"pointer"},children:[c.jsx("input",{type:"file",accept:"image/png,image/jpeg,image/webp",style:{display:"none"},onChange:k,disabled:h}),c.jsx(i0,{className:"import-icon"}),c.jsx("span",{style:{fontWeight:600},children:"Upload a base image"}),c.jsx("span",{style:{fontSize:"0.75rem",color:"var(--md-sys-color-outline)",textAlign:"center"},children:"Optional. Generate a new image based on one of your own."})]}),yt&&c.jsxs("div",{style:{marginTop:"12px"},children:[c.jsxs("div",{style:{display:"flex",justifyContent:"space-between",fontSize:"0.8rem",marginBottom:"4px"},children:[c.jsx("span",{children:"Transformation strength"}),c.jsx("span",{children:x.denoisingStrength.toFixed(2)})]}),c.jsx("input",{type:"range",min:"0.1",max:"1",step:"0.05",value:x.denoisingStrength,onChange:L=>E(he=>({...he,denoisingStrength:parseFloat(L.target.value)})),disabled:h,style:{width:"100%"}}),c.jsx("div",{style:{fontSize:"0.72rem",color:"var(--md-sys-color-outline)",marginTop:"2px"},children:"Lower = closer to your image; higher = more creative freedom. 0.7 is a good start."})]})]}),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:()=>P("constraints"),children:[c.jsx(Ks,{size:14}),c.jsxs("span",{children:["Resolution: ",x.width,"x",x.height]})]}),c.jsxs("div",{className:"status-chip",onClick:()=>P("constraints"),children:[c.jsx(aa,{size:14}),c.jsxs("span",{children:["Steps: ",x.steps]})]}),c.jsxs("div",{className:"status-chip",onClick:()=>P("constraints"),children:[c.jsx(Su,{size:14}),c.jsxs("span",{children:["Sampler: ",x.sampler]})]}),c.jsx("div",{className:"status-chip",onClick:()=>P("constraints"),children:c.jsxs("span",{children:["Seed: ",x.seed===-1?"Random":x.seed]})})]})]}),c.jsxs("button",{className:"m3-btn m3-btn-filled",style:{height:"48px",marginTop:"8px"},onClick:D,disabled:h||!f.trim()||!q,children:[c.jsx(Su,{size:18}),c.jsx("span",{children:q?yt?"Generate from Base Image":"Generate Local Image":"Select Model to Generate"})]})]})]})}),c.jsxs("div",{className:"m3-card output-panel",children:[c.jsx("div",{className:"output-image-container",children:h||Z||ce?c.jsx("div",{className:"progress-overlay",children:ce?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."})]}):Z?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:I?"Decoding Latents...":"Generating Locally..."}),_&&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:"})," ",Ze," / ",x.steps," (",Math.max(0,x.steps-Ze)," 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: ",Mt,"s"]})]}),c.jsx("button",{className:"m3-btn m3-btn-error",style:{marginTop:"16px",height:"36px",padding:"0 24px"},onClick:B,children:"Stop Generating"})]})}):fe?c.jsx("img",{src:fe,className:"output-image",alt:"Generated Output"}):G?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:G}),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(Su,{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."]})]})}),fe&&!h&&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: ",lt]}),ke&&c.jsxs("span",{children:["Inference Time: ",ke.toFixed(1),"s"]})]}),c.jsxs("div",{className:"image-actions",children:[c.jsxs("button",{className:"m3-btn m3-btn-tonal",onClick:W,children:[De?c.jsx(Xs,{size:16}):c.jsx(Jy,{size:16}),c.jsx("span",{children:De?"Copied":"Copy"})]}),c.jsxs("button",{className:"m3-btn m3-btn-outlined",onClick:ae,children:[c.jsx(nm,{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"}),we.length>0&&c.jsxs("div",{className:"gallery-selection-actions",children:[c.jsxs("span",{className:"gallery-selection-count",children:[we.length," selected"]}),c.jsxs("button",{className:"m3-btn m3-btn-tonal",onClick:$e,children:[c.jsx(Xs,{size:14}),c.jsx("span",{children:"Use"})]}),c.jsxs("button",{className:"m3-btn m3-btn-outlined",onClick:za,children:[c.jsx(nm,{size:14}),c.jsx("span",{children:"Download"})]}),c.jsxs("button",{className:"m3-btn m3-btn-error",onClick:Ta,children:[c.jsx(rn,{size:14}),c.jsx("span",{children:"Delete"})]}),c.jsx("button",{className:"m3-btn m3-btn-outlined",onClick:al,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((L,he)=>c.jsx(tg,{img:L,idx:he,isSelected:Qe.includes(he),onClick:dl},L.image||he))})]})]})]})}const ag=U.memo(lg),ng=[{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"}]},{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 ig({activeModel:f,setActiveModel:b,serverRunning:N,setServerRunning:r,constraints:x,showAlert:E=async({message:H})=>window.alert(H),showConfirm:q=async({message:H})=>window.confirm(H)}){const[H,w]=U.useState([]),[h,A]=U.useState(null),[O,Q]=U.useState(0),[P,J]=U.useState(""),[$,fe]=U.useState(null),[te,lt]=U.useState(null),[Ae,ke]=U.useState(null),[Ve,De]=U.useState({filename:"",speed:"0.0",eta:0,status:""}),[ee,Se]=U.useState(""),[ot,Mt]=U.useState(null),[de,Ze]=U.useState(!1),[ct,Ke]=U.useState({progress:0,phase:""}),[Le,_]=U.useState(null),[C,Z]=U.useState({backendMode:"",backendBinary:"",backendDevice:""}),me=H.map(D=>ui(D).filename),ce=$!==null||de;U.useEffect(()=>{R(),d()},[]),U.useEffect(()=>{if(!N&&!$){Z({backendMode:"",backendBinary:"",backendDevice:""});return}let D=!1;const B=async()=>{try{const ae=await Cl();if(D)return;Z({backendMode:ae.settings?.backendMode||ae.loading?.backendMode||"",backendBinary:ae.settings?.backendBinary||ae.loading?.backendBinary||"",backendDevice:ae.settings?.backendDevice||ae.loading?.device||""})}catch{}};B();const W=setInterval(B,2e3);return()=>{D=!0,clearInterval(W)}},[N,$]);const d=async()=>{try{const D=await cm();D.active&&D.filename&&j(D.filename)}catch(D){console.error("Check active download failed:",D)}},j=D=>{A(D);const B=setInterval(async()=>{try{const W=await cm();W.active?(Q(W.progress===-1?0:W.progress),J(`${W.speed} • ETA ${W.eta}s`)):(clearInterval(B),A(null),W.error?String(W.error).toLowerCase().includes("cancelled")||E({title:"Download Failed",message:W.error,danger:!0}):R())}catch(W){console.error("Polling error:",W)}},1e3)},R=async()=>{try{const D=await X0();w(D.map(ui).filter(B=>B.filename))}catch(D){console.error(D)}},G=async(D,B)=>{if(h||me.includes(B)&&!await q({title:"Overwrite Model?",message:`"${B}" is already downloaded. Do you want to download and overwrite it?`,confirmLabel:"Overwrite"}))return;const W=typeof window<"u"&&window.__TAURI_INTERNALS__!==void 0,ae=typeof window<"u"&&(window.location.hostname==="localhost"||window.location.hostname==="127.0.0.1");if(!W&&!ae){E({title:"Server Required",message:"Model download requires the local image generator server.",danger:!0});return}try{const At=await I0(D);At.ok?j(B):E({title:"Download Failed",message:At.error||"Unknown error",danger:!0})}catch(At){E({title:"Download Error",message:At.message,danger:!0})}},V=async D=>{if(D.preventDefault(),!ee.trim())return;let B="model.gguf";try{const W=new URL(ee.trim());if(W.protocol!=="http:"&&W.protocol!=="https:")throw new Error("URL protocol must be http or https");if(B=W.pathname.split("/").pop()||"",!B)throw new Error("Could not extract filename from URL");const ae=B.toLowerCase();if(!ae.endsWith(".gguf")&&!ae.endsWith(".safetensors")&&!ae.endsWith(".ckpt"))throw new Error("URL must point to a .gguf, .safetensors, or .ckpt weights file")}catch(W){E({title:"Invalid URL",message:W.message,danger:!0});return}await G(ee.trim(),B),Se("")},I=D=>{G(D.url,D.filename)},se=async()=>{await P0(),A(null),Q(0),J(""),await R()},Qe=async D=>{if(f&&f!==D&&N){_(D);return}await Me(D)},Me=async D=>{const B=typeof window<"u"&&window.__TAURI_INTERNALS__!==void 0,W=typeof window<"u"&&(window.location.hostname==="localhost"||window.location.hostname==="127.0.0.1"),At=(await Cl())?.port||8080;if(!B&&!W){const Gt=await hm(),dl=`.\\backend\\win\\vulkan\\sd-vulkan.exe --listen-port ${At} --model .\\models\\${D} --threads 8`;Gt?await q({title:"Web Browser Mode",message:`To load "${D}" on the active GPU server, restart your terminal backend with: + +${dl} + +Update the UI status anyway?`,confirmLabel:"Update UI"})&&(b(D),r(!0)):await q({title:"Backend Not Running",message:`C++ backend server is not running on port ${At}. + +To run locally, start: + +${dl} + +Proceed in Simulation Mode instead?`,confirmLabel:"Proceed"})&&(b(D),r(!1));return}fe(D),lt({progress:0,phase:"Starting backend...",speed:"",current:0,total:0,model:D,backendMode:"",backendBinary:"",device:""});try{const Gt=await Vs(D,x);console.log(Gt);let dl=!1,we=null;for(let al=0;al<240;al++){const $e=await Cl();if($e.loading&<({progress:$e.loading.progress||0,phase:$e.loading.phase||"Loading model...",speed:$e.loading.speed||"",current:$e.loading.current||0,total:$e.loading.total||0,model:$e.loading.model||D,backendMode:$e.loading.backendMode||$e.settings?.backendMode||"",backendBinary:$e.loading.backendBinary||$e.settings?.backendBinary||"",device:$e.loading.device||$e.settings?.backendDevice||""}),$e.ready){dl=!0;break}if($e.error){we=$e.error;break}if(!$e.running&&al>3){we="The backend process terminated immediately on startup.";break}await new Promise(za=>setTimeout(za,500))}if(dl)lt(al=>({...al||{},progress:100,phase:"Model ready",speed:"",current:al?.current||0,total:al?.total||0,model:D})),b(D),r(!0);else throw new Error(we||`Model server failed to respond on port ${At}.`)}catch(Gt){console.error("Failed to load model:",Gt),E({title:"Model Load Failed",message:Gt.message||String(Gt),danger:!0})}finally{setTimeout(()=>lt(null),800),fe(null)}},yt=async()=>{const D=Le;_(null),await Nt(),D&&await Me(D)},Nt=async()=>{if(de)return;Ze(!0),Ke({progress:10,phase:"Stopping backend process..."});const D=setInterval(async()=>{try{const B=await Cl();B.unloading?.active?Ke({progress:B.unloading.progress||50,phase:B.unloading.phase||"Unloading model..."}):Ke(W=>({progress:Math.min(95,W.progress+10),phase:W.phase||"Unloading model..."}))}catch{}},300);try{await Js(),Ke({progress:100,phase:"Model unloaded"}),b(null),_(null),r(!1)}catch(B){console.error(B),E({title:"Unload Failed",message:B.message||String(B),danger:!0})}finally{clearInterval(D),setTimeout(()=>{Ze(!1),Ke({progress:0,phase:""})},500)}},Je=async D=>{if(await q({title:"Delete Model?",message:`Delete "${D}" from your drive?`,confirmLabel:"Delete",danger:!0}))try{await W0(D),await R(),f===D&&await Nt()}catch(B){console.error("Failed to delete model:",B),E({title:"Delete Failed",message:B.message||String(B),danger:!0})}},Ht=async(D,B)=>{const W=new AbortController;Mt(W),ke(0),De({filename:B,speed:"0.0",eta:0,status:"Initiating file copy..."});try{await J0(D,ae=>{ke(Math.round(ae.progress)),De({filename:ae.filename,speed:ae.speed_mb_s.toFixed(1),eta:Math.round(ae.eta_secs),status:ae.status})},W.signal),await R()}catch(ae){console.error("Import failed:",ae),ae.name!=="AbortError"&&E({title:"Import Failed",message:ae.message||String(ae),danger:!0})}finally{ke(null),Mt(null)}},zt=()=>{ot&&ot.abort()},k=D=>{const B=D.target.files[0];B&&Ht(B,B.name),D.target.value=""},ie=!!h;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(xu,{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:Nt,disabled:de||$!==null,children:[de?c.jsx(aa,{className:"progress-spinner",size:16}):c.jsx(rn,{size:16}),c.jsx("span",{children:de?"Unloading":"Unload Server"})]})]})}),de&&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:ct.phase||"Unloading model..."}),c.jsxs("span",{children:[Math.round(ct.progress),"%"]})]}),c.jsx("div",{className:"model-progress-bar",children:c.jsx("div",{className:"model-progress-fill",style:{width:`${Math.min(100,Math.max(0,ct.progress))}%`,transition:"width 0.25s ease"}})})]})]}),te&&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: ",te.model||$]}),(te.backendMode||te.backendBinary||te.device)&&c.jsxs("div",{style:{display:"flex",flexWrap:"wrap",gap:"8px",marginBottom:"10px"},children:[te.backendMode&&c.jsxs("span",{className:"status-chip",style:{cursor:"default"},children:[c.jsx(xu,{size:14}),c.jsxs("span",{children:["Loading on ",te.backendMode]})]}),te.device&&c.jsx("span",{className:"status-chip",style:{cursor:"default"},children:c.jsx("span",{children:te.device})}),te.backendBinary&&c.jsx("span",{className:"status-chip",style:{cursor:"default"},children:c.jsx("span",{children:te.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:[te.phase,te.speed?` (${te.speed})`:""]}),c.jsx("span",{children:te.total>0?`Loaded ${te.current} / ${te.total} tensors`:`${Math.round(te.progress)}%`})]}),c.jsx("div",{className:"model-progress-bar",children:c.jsx("div",{className:"model-progress-fill",style:{width:`${Math.min(100,Math.max(0,te.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(Qs,{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 B=D.filename,W=f===B;return c.jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center",padding:"12px 16px",background:W?"var(--md-sys-color-primary-container)":"var(--md-sys-color-surface-variant)",color:W?"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:B}),c.jsxs("span",{style:{fontSize:"0.75rem",opacity:.8},children:["Local Weights File • ",D.size||ii(D.sizeBytes)]})]}),c.jsx("div",{style:{display:"flex",gap:"8px"},children:W?c.jsxs("button",{className:"m3-btn m3-btn-error",style:{height:"36px",padding:"0 16px"},onClick:Nt,disabled:de,children:[de?c.jsx(aa,{className:"progress-spinner",size:14}):c.jsx(rn,{size:14}),c.jsx("span",{children:de?"Unloading":"Unload"})]}):c.jsxs(c.Fragment,{children:[c.jsxs("button",{className:"m3-btn m3-btn-filled",style:{height:"36px",padding:"0 16px"},onClick:()=>Qe(B),disabled:ce,children:[$===B?c.jsx(aa,{className:"progress-spinner",size:14}):c.jsx(Qs,{size:14}),c.jsx("span",{children:$===B?"Loading":"Load"})]}),c.jsx("button",{className:"m3-btn m3-btn-error",style:{height:"36px",width:"36px",padding:0,minWidth:"36px"},onClick:()=>Je(B),disabled:ce,title:"Delete from models folder",children:c.jsx(rn,{size:14})})]})})]},B)})})]}),c.jsx("div",{className:"workspace-title-section",style:{marginTop:"32px",marginBottom:"16px"},children:c.jsxs("h3",{className:"m3-card-title",children:[c.jsx(r0,{size:20,style:{color:"var(--md-sys-color-primary)"}}),"Model Library"]})}),c.jsx("div",{style:{display:"flex",flexDirection:"column",gap:"16px"},children:ng.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(B=>{const W=me.includes(B.filename),ae=h===B.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:B.name}),c.jsxs("span",{style:{fontSize:"0.75rem",color:"var(--md-sys-color-outline)"},children:[B.format," • approx. ",B.approxSize," • ",B.resolution]})]}),c.jsx("p",{style:{fontSize:"0.78rem",color:"var(--md-sys-color-on-surface-variant)",lineHeight:1.35,margin:0},children:B.notes}),ae&&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"}})}),P&&c.jsx("div",{style:{fontSize:"0.7rem",color:"var(--md-sys-color-outline)",marginTop:"4px"},children:P})]}),c.jsxs("button",{className:W?"m3-btn m3-btn-tonal":"m3-btn m3-btn-filled",style:{height:"36px",marginTop:"auto"},onClick:()=>I(B),disabled:W||h!==null,children:[W?c.jsx(xu,{size:14}):ae?c.jsx(aa,{className:"progress-spinner",size:14}):c.jsx(am,{size:14}),c.jsx("span",{children:W?"Downloaded":ae?"Downloading":"Download"})]}),c.jsx("a",{href:B.url,target:"_blank",rel:"noreferrer",style:{alignSelf:"center",color:"var(--md-sys-color-primary)",fontSize:"0.75rem",fontWeight:600,lineHeight:1.2,textDecoration:"none"},children:"Save to Downloads folder"})]},B.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(im,{size:20,style:{color:"var(--md-sys-color-primary)"}}),"Local Model Import"]})}),Ae!==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: ",Ve.filename]}),c.jsxs("button",{className:"m3-btn m3-btn-error",style:{height:"34px",padding:"0 14px"},onClick:zt,children:[c.jsx(ks,{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:[Ve.status," (",Ve.speed," MB/s)"]}),c.jsxs("span",{children:[Ae,"% (",Ve.eta,"s remaining)"]})]}),c.jsx("div",{className:"model-progress-bar",children:c.jsx("div",{className:"model-progress-fill",style:{width:`${Ae}%`,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:Ae!==null}),c.jsx(im,{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(am,{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."}),ie?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:h,children:h}),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:P}),c.jsxs("button",{className:"m3-btn m3-btn-error",style:{height:"34px",padding:"0 14px",marginTop:"10px"},onClick:se,children:[c.jsx(ks,{size:14}),c.jsx("span",{children:"Stop Download"})]})]}):c.jsxs("form",{onSubmit:V,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:ee,onChange:D=>Se(D.target.value),disabled:h!==null}),c.jsx("button",{type:"submit",className:"m3-btn m3-btn-filled",style:{height:"40px"},disabled:h!==null,children:"Download"})]})]})]}),Le&&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(M0,{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 "',Le,'".']}),c.jsxs("div",{style:{display:"flex",justifyContent:"flex-end",gap:"10px"},children:[c.jsx("button",{className:"m3-btn m3-btn-outlined",onClick:()=>_(null),disabled:de,children:"Cancel"}),c.jsxs("button",{className:"m3-btn m3-btn-error",onClick:Nt,disabled:de,children:[c.jsx(rn,{size:14}),c.jsx("span",{children:"Unload Only"})]}),c.jsxs("button",{className:"m3-btn m3-btn-filled",onClick:yt,disabled:de,children:[de?c.jsx(aa,{className:"progress-spinner",size:14}):c.jsx(aa,{size:14}),c.jsx("span",{children:"Unload and Load"})]})]})]})})]})}const ug=U.memo(ig),sm=[{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"}],cg=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 sg({constraints:f,setConstraints:b,activeModel:N,specs:r,backendOptions:x}){const E=N?cg(N):!1,q=x?.options?.length?x.options:[{id:"cpu",label:"CPU",available:!0}],H=(A,O)=>{b(Q=>({...Q,[A]:O}))},w=(A,O)=>{const Q=O==="sdxl"&&!E,P=sm.find(J=>J.id===A);if(P){let J=Q?P.sdxl_width:P.width,$=Q?P.sdxl_height:P.height;E&&(J>$?($=Math.round($*512/J),J=512):(J=Math.round(J*512/$),$=512),J=Math.round(J/64)*64,$=Math.round($/64)*64),H("width",J),H("height",$)}},h=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(Fy,{size:18,style:{color:"var(--md-sys-color-primary)"}}),"1. Picture Size & Shape"]}),E&&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(f0,{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:N}),"). 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:[E?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||E?"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:E?"*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:sm.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:()=>w(A.id,E?"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:E?`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(Ks,{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(rm,{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:q.map(A=>c.jsx("div",{className:`m3-segment-item ${f.backendType===A.id||!f.backendType&&A.id==="cpu"?"active":""}`,onClick:()=>h(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."]}),x?.unavailable?.length>0&&c.jsx("div",{style:{marginTop:"8px",display:"flex",flexDirection:"column",gap:"4px"},children:x.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 fg=U.memo(sg);function og(){const f=U.useRef(null),[b,N]=U.useState(null),r=U.useCallback(k=>{const ie=f.current;f.current=null,N(null),ie&&ie(k)},[]),x=U.useCallback(({title:k="Confirm Action",message:ie,confirmLabel:D="OK",cancelLabel:B="Cancel",danger:W=!1})=>new Promise(ae=>{f.current=ae,N({type:"confirm",title:k,message:ie,confirmLabel:D,cancelLabel:B,danger:W})}),[]),E=U.useCallback(({title:k="Notice",message:ie,confirmLabel:D="OK",danger:B=!1})=>new Promise(W=>{f.current=W,N({type:"alert",title:k,message:ie,confirmLabel:D,danger:B})}),[]),[q,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",q),localStorage.setItem("theme",q)},[q]);const[w,h]=U.useState("generator"),[A,O]=U.useState(""),[Q,P]=U.useState(""),[J,$]=U.useState(null),[fe,te]=U.useState(!1),[lt,Ae]=U.useState(!1),[ke,Ve]=U.useState({options:[{id:"cpu",label:"CPU",available:!0}],cudaAvailable:!1,vulkanAvailable:!1,defaultBackendType:"cpu"}),[De,ee]=U.useState(null),[Se,ot]=U.useState([]),[Mt,de]=U.useState(!1),[Ze,ct]=U.useState(!1),[Ke,Le]=U.useState([]),[_,C]=U.useState(!1),[Z,me]=U.useState(0),[ce,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,R]=U.useState({cpu_usage:0,ram_used_gb:0,ram_total_gb:0,gpu_name:"Detecting...",vram_used_gb:0,vram_total_gb:0}),[G,V]=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 ie=await q0(),D=await Y0();Ve(D),d(ie),V(B=>({...B,threads:ie.cpu_cores_physical||4,backendType:B.backendType==="auto"?D.defaultBackendType||"cpu":B.backendType,useGpu:(B.backendType==="auto"?D.defaultBackendType:B.backendType)!=="cpu"}))}catch(ie){console.error("Error fetching hardware specs:",ie)}}k()},[]);const I=U.useCallback(async()=>{de(!0);try{const[k,ie]=await Promise.all([R0(),H0().catch(()=>[])]);ee(k),ot(ie)}finally{de(!1)}},[]);U.useEffect(()=>{I()},[I]);const se=U.useCallback(async()=>{try{const k=await B0();await navigator.clipboard.writeText(JSON.stringify(k,null,2)),ct(!0),setTimeout(()=>ct(!1),1800)}catch(k){E({title:"Diagnostics Failed",message:k.message||String(k),danger:!0})}},[E]),Qe=U.useCallback(async()=>{if(Se.length===0)return;const k=Se.reduce((D,B)=>D+Number(B.sizeBytes||0),0);if(await x({title:"Clean Safe Files?",message:`Delete ${Se.length} temporary/cache item${Se.length===1?"":"s"} and free about ${ii(k)}? + +Models and generated outputs are not included.`,confirmLabel:"Clean",danger:!0})){de(!0);try{await G0(Se.map(D=>D.id)),await I()}catch(D){E({title:"Cleanup Failed",message:D.message||String(D),danger:!0})}finally{de(!1)}}},[Se,I,E,x]);U.useEffect(()=>{async function k(){const ie=await Q0();Le(ie)}k()},[]),U.useEffect(()=>{J?localStorage.setItem("active-model",J):localStorage.removeItem("active-model")},[J]),U.useEffect(()=>{let k=null;async function ie(){const D=await Cl();if(!!D.ready){k&&clearInterval(k);const W=localStorage.getItem("active-model");if(W)$(W),te(!0);else{try{if(D&&D.settings&&D.settings.model){const ae=D.settings.model.split(/[\\/]/).pop();$(ae)}}catch{}te(!0)}}else if(!(typeof window<"u"&&window.__TAURI_INTERNALS__!==void 0)){const ae=localStorage.getItem("active-model");ae&&($(ae),te(!1))}}return ie(),k=setInterval(ie,2e3),()=>{k&&clearInterval(k)}},[]),U.useEffect(()=>{async function k(){try{const D=await L0();R(B=>B.cpu_usage===D.cpu_usage&&B.ram_used_gb===D.ram_used_gb&&B.ram_total_gb===D.ram_total_gb&&B.gpu_name===D.gpu_name&&B.vram_used_gb===D.vram_used_gb&&B.vram_total_gb===D.vram_total_gb?B:D)}catch{}}k();const ie=setInterval(k,1500);return()=>clearInterval(ie)},[]),U.useEffect(()=>{if(J){const k=J.toLowerCase();k.includes("flux")||k.includes("schnell")?V(ie=>({...ie,steps:4,cfgScale:1,width:1024,height:1024})):k.includes("lightning")||k.includes("turbo")?V(ie=>({...ie,steps:4,cfgScale:1.5,width:1024,height:1024})):k.includes("sd15")?V(ie=>({...ie,steps:25,cfgScale:7,width:512,height:512})):k.includes("sd35")?V(ie=>({...ie,steps:20,cfgScale:4.5,width:1024,height:1024})):V(ie=>({...ie,steps:20,cfgScale:7,width:512,height:512}))}},[J]);const Me=U.useMemo(()=>{switch(w){case"generator":return c.jsx(ag,{prompt:A,setPrompt:O,negativePrompt:Q,setNegativePrompt:P,constraints:G,setConstraints:V,activeModel:J,generatedImages:Ke,setGeneratedImages:Le,isGenerating:_,setIsGenerating:C,generationProgress:Z,setGenerationProgress:me,setActiveTab:h,showAlert:E,showConfirm:x});case"models":return c.jsx(ug,{activeModel:J,setActiveModel:$,serverRunning:fe,setServerRunning:te,constraints:G,showAlert:E,showConfirm:x});case"constraints":return c.jsx(fg,{constraints:G,setConstraints:V,activeModel:J,specs:ce,backendOptions:ke});default:return null}},[w,A,Q,G,J,Ke,_,Z,fe,ce,ke,E,x]),yt=U.useMemo(()=>c.jsx(E0,{activeTab:w,setActiveTab:h,specs:ce}),[w,ce]),Nt=U.useCallback(async()=>{if(!(!fe||lt)){Ae(!0);try{await Js(),te(!1),$(null)}catch(k){console.error("Failed to stop server:",k),E({title:"Stop Server Failed",message:k.message||String(k),danger:!0})}finally{Ae(!1)}}},[fe,lt,E]),Je=[...De?.stale?["Restart Local AI Image Generator so the local server loads the latest API."]:[],...De?.issues||[]],Ht=Se.reduce((k,ie)=>k+Number(ie.sizeBytes||0),0),zt=!!(De&&(Je.length>0||Se.length>0));return c.jsxs("div",{className:"app-container",children:[yt,c.jsxs("div",{className:"main-content",children:[c.jsx(D0,{telemetry:j,serverRunning:fe,activeModel:J,onStopServer:Nt,isStoppingServer:lt,theme:q,setTheme:H}),zt&&c.jsxs("div",{className:`m3-card readiness-card ${De?.stale||Je.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:De?.stale?"Restart Required":Je.length>0?"System Readiness":"Safe Cleanup Available"}),c.jsx("p",{className:"m3-card-subtitle",style:{margin:0},children:De?.stale?`Running server build: ${De.build||"unknown"}`:Je.length>0?"Local AI Image Generator found setup items that may need attention.":`${Se.length} temporary item${Se.length===1?"":"s"} can be cleaned (${ii(Ht)}).`})]}),c.jsxs("div",{className:"readiness-actions",children:[c.jsx("button",{className:"m3-btn m3-btn-outlined",onClick:I,disabled:Mt,children:Mt?"Checking":"Refresh"}),c.jsx("button",{className:"m3-btn m3-btn-tonal",onClick:se,children:Ze?"Copied":"Copy Diagnostics"}),Se.length>0&&c.jsxs("button",{className:"m3-btn m3-btn-error",onClick:Qe,disabled:Mt,children:["Clean ",ii(Ht)]})]})]}),Je.length>0&&c.jsx("div",{className:"readiness-issues",children:Je.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))})]}),Me]}),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})]})]})})]})}Gy.createRoot(document.getElementById("root")).render(c.jsx(Dy.StrictMode,{children:c.jsx(og,{})}));export{ja as i,rg as t}; diff --git a/app/dist/assets/index-jXnaCwmK.js b/app/dist/assets/index-jXnaCwmK.js deleted file mode 100644 index bd6788e..0000000 --- a/app/dist/assets/index-jXnaCwmK.js +++ /dev/null @@ -1,121 +0,0 @@ -(function(){const b=document.createElement("link").relList;if(b&&b.supports&&b.supports("modulepreload"))return;for(const x of document.querySelectorAll('link[rel="modulepreload"]'))r(x);new MutationObserver(x=>{for(const N of x)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(x){const N={};return x.integrity&&(N.integrity=x.integrity),x.referrerPolicy&&(N.referrerPolicy=x.referrerPolicy),x.crossOrigin==="use-credentials"?N.credentials="include":x.crossOrigin==="anonymous"?N.credentials="omit":N.credentials="same-origin",N}function r(x){if(x.ep)return;x.ep=!0;const N=E(x);fetch(x.href,N)}})();function fm(f){return f&&f.__esModule&&Object.prototype.hasOwnProperty.call(f,"default")?f.default:f}var Bs={exports:{}},ai={};var Zd;function E0(){if(Zd)return ai;Zd=1;var f=Symbol.for("react.transitional.element"),b=Symbol.for("react.fragment");function E(r,x,N){var G=null;if(N!==void 0&&(G=""+N),x.key!==void 0&&(G=""+x.key),"key"in x){N={};for(var H in x)H!=="key"&&(N[H]=x[H])}else N=x;return x=N.ref,{$$typeof:f,type:r,key:G,ref:x!==void 0?x:null,props:N}}return ai.Fragment=b,ai.jsx=E,ai.jsxs=E,ai}var Kd;function N0(){return Kd||(Kd=1,Bs.exports=E0()),Bs.exports}var c=N0(),Rs={exports:{}},le={};var Jd;function A0(){if(Jd)return le;Jd=1;var f=Symbol.for("react.transitional.element"),b=Symbol.for("react.portal"),E=Symbol.for("react.fragment"),r=Symbol.for("react.strict_mode"),x=Symbol.for("react.profiler"),N=Symbol.for("react.consumer"),G=Symbol.for("react.context"),H=Symbol.for("react.forward_ref"),w=Symbol.for("react.suspense"),h=Symbol.for("react.memo"),A=Symbol.for("react.lazy"),U=Symbol.for("react.activity"),V=Symbol.iterator;function fe(d){return d===null||typeof d!="object"?null:(d=V&&d[V]||d["@@iterator"],typeof d=="function"?d:null)}var X={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},L=Object.assign,te={};function W(d,j,B){this.props=d,this.context=j,this.refs=te,this.updater=B||X}W.prototype.isReactComponent={},W.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")},W.prototype.forceUpdate=function(d){this.updater.enqueueForceUpdate(this,d,"forceUpdate")};function Oe(){}Oe.prototype=W.prototype;function de(d,j,B){this.props=d,this.context=j,this.refs=te,this.updater=B||X}var Ee=de.prototype=new Oe;Ee.constructor=de,L(Ee,W.prototype),Ee.isPureReactComponent=!0;var ke=Array.isArray;function Ae(){}var P={H:null,A:null,T:null,S:null},ve=Object.prototype.hasOwnProperty;function Ke(d,j,B){var q=B.ref;return{$$typeof:f,type:d,key:j,ref:q!==void 0?q:null,props:B}}function yt(d,j){return Ke(d.type,j,d.props)}function me(d){return typeof d=="object"&&d!==null&&d.$$typeof===f}function Je(d){var j={"=":"=0",":":"=2"};return"$"+d.replace(/[=:]/g,function(B){return j[B]})}var st=/\/+/g;function $e(d,j){return typeof d=="object"&&d!==null&&d.key!=null?Je(""+d.key):j.toString(36)}function Xe(d){switch(d.status){case"fulfilled":return d.value;case"rejected":throw d.reason;default:switch(typeof d.status=="string"?d.then(Ae,Ae):(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 _(d,j,B,q,K){var ee=typeof d;(ee==="undefined"||ee==="boolean")&&(d=null);var se=!1;if(d===null)se=!0;else switch(ee){case"bigint":case"string":case"number":se=!0;break;case"object":switch(d.$$typeof){case f:case b:se=!0;break;case A:return se=d._init,_(se(d._payload),j,B,q,K)}}if(se)return K=K(d),se=q===""?"."+$e(d,0):q,ke(K)?(B="",se!=null&&(B=se.replace(st,"$&/")+"/"),_(K,j,B,"",function(gt){return gt})):K!=null&&(me(K)&&(K=yt(K,B+(K.key==null||d&&d.key===K.key?"":(""+K.key).replace(st,"$&/")+"/")+se)),j.push(K)),1;se=0;var Ze=q===""?".":q+":";if(ke(d))for(var Ne=0;Ne>>1,ce=_[he];if(0>>1;hex(B,J))qx(K,B)?(_[he]=K,_[q]=J,he=q):(_[he]=B,_[j]=J,he=j);else if(qx(K,J))_[he]=K,_[q]=J,he=q;else break e}}return C}function x(_,C){var J=_.sortIndex-C.sortIndex;return J!==0?J:_.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 w=[],h=[],A=1,U=null,V=3,fe=!1,X=!1,L=!1,te=!1,W=typeof setTimeout=="function"?setTimeout:null,Oe=typeof clearTimeout=="function"?clearTimeout:null,de=typeof setImmediate<"u"?setImmediate:null;function Ee(_){for(var C=E(h);C!==null;){if(C.callback===null)r(h);else if(C.startTime<=_)r(h),C.sortIndex=C.expirationTime,b(w,C);else break;C=E(h)}}function ke(_){if(L=!1,Ee(_),!X)if(E(w)!==null)X=!0,Ae||(Ae=!0,Je());else{var C=E(h);C!==null&&Xe(ke,C.startTime-_)}}var Ae=!1,P=-1,ve=5,Ke=-1;function yt(){return te?!0:!(f.unstable_now()-Ke_&&yt());){var he=U.callback;if(typeof he=="function"){U.callback=null,V=U.priorityLevel;var ce=he(U.expirationTime<=_);if(_=f.unstable_now(),typeof ce=="function"){U.callback=ce,Ee(_),C=!0;break t}U===E(w)&&r(w),Ee(_)}else r(w);U=E(w)}if(U!==null)C=!0;else{var d=E(h);d!==null&&Xe(ke,d.startTime-_),C=!1}}break e}finally{U=null,V=J,fe=!1}C=void 0}}finally{C?Je():Ae=!1}}}var Je;if(typeof de=="function")Je=function(){de(me)};else if(typeof MessageChannel<"u"){var st=new MessageChannel,$e=st.port2;st.port1.onmessage=me,Je=function(){$e.postMessage(null)}}else Je=function(){W(me,0)};function Xe(_,C){P=W(function(){_(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(_){_.callback=null},f.unstable_forceFrameRate=function(_){0>_||125<_?console.error("forceFrameRate takes a positive int between 0 and 125, forcing frame rates higher than 125 fps is not supported"):ve=0<_?Math.floor(1e3/_):5},f.unstable_getCurrentPriorityLevel=function(){return V},f.unstable_next=function(_){switch(V){case 1:case 2:case 3:var C=3;break;default:C=V}var J=V;V=C;try{return _()}finally{V=J}},f.unstable_requestPaint=function(){te=!0},f.unstable_runWithPriority=function(_,C){switch(_){case 1:case 2:case 3:case 4:case 5:break;default:_=3}var J=V;V=_;try{return C()}finally{V=J}},f.unstable_scheduleCallback=function(_,C,J){var he=f.unstable_now();switch(typeof J=="object"&&J!==null?(J=J.delay,J=typeof J=="number"&&0he?(_.sortIndex=J,b(h,_),E(w)===null&&_===E(h)&&(L?(Oe(P),P=-1):L=!0,Xe(ke,J-he))):(_.sortIndex=ce,b(w,_),X||fe||(X=!0,Ae||(Ae=!0,Je()))),_},f.unstable_shouldYield=yt,f.unstable_wrapCallback=function(_){var C=V;return function(){var J=V;V=C;try{return _.apply(this,arguments)}finally{V=J}}}})(qs)),qs}var Fd;function O0(){return Fd||(Fd=1,Gs.exports=C0()),Gs.exports}var Ls={exports:{}},Mt={};var Id;function U0(){if(Id)return Mt;Id=1;var f=Zs();function b(w){var h="https://react.dev/errors/"+w;if(1"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(f)}catch(b){console.error(b)}}return f(),Ls.exports=U0(),Ls.exports}var em;function B0(){if(em)return ni;em=1;var f=O0(),b=Zs(),E=w0();function r(e){var t="https://react.dev/errors/"+e;if(1ce||(e.current=he[ce],he[ce]=null,ce--)}function B(e,t){ce++,he[ce]=e.current,e.current=t}var q=d(null),K=d(null),ee=d(null),se=d(null);function Ze(e,t){switch(B(ee,t),B(K,e),B(q,null),t.nodeType){case 9:case 11:e=(e=t.documentElement)&&(e=e.namespaceURI)?yd(e):0;break;default:if(e=t.tagName,t=t.namespaceURI)t=yd(t),e=gd(t,e);else switch(e){case"svg":e=1;break;case"math":e=2;break;default:e=0}}j(q),B(q,e)}function Ne(){j(q),j(K),j(ee)}function gt(e){e.memoizedState!==null&&B(se,e);var t=q.current,l=gd(t,e.type);t!==l&&(B(K,e),B(q,l))}function Et(e){K.current===e&&(j(q),j(K)),se.current===e&&(j(se),Pn._currentValue=J)}var We,Ht;function Tt(e){if(We===void 0)try{throw Error()}catch(l){var t=l.stack.trim().match(/\n( *(at )?)/);We=t&&t[1]||"",Ht=-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{Z=!1,Error.prepareStackTrace=l}return(l=e?e.displayName||e.name:"")?Tt(l):""}function D(e,t){switch(e.tag){case 26:case 27:case 5:return Tt(e.type);case 16:return Tt("Lazy");case 13:return e.child!==t&&t!==null?Tt("Suspense Fallback"):Tt("Suspense");case 19:return Tt("SuspenseList");case 0:case 15:return ie(e.type,!1);case 11:return ie(e.type.render,!1);case 1:return ie(e.type,!0);case 31:return Tt("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 F=Object.prototype.hasOwnProperty,ae=f.unstable_scheduleCallback,At=f.unstable_cancelCallback,Gt=f.unstable_shouldYield,dl=f.unstable_requestPaint,Re=f.unstable_now,al=f.unstable_getCurrentPriorityLevel,Fe=f.unstable_ImmediatePriority,za=f.unstable_UserBlockingPriority,Ta=f.unstable_NormalPriority,Y=f.unstable_LowPriority,ye=f.unstable_IdlePriority,He=f.log,pt=f.unstable_setDisableYieldValue,ft=null,tt=null;function qt(e){if(typeof He=="function"&&pt(e),tt&&typeof tt.setStrictMode=="function")try{tt.setStrictMode(ft,e)}catch{}}var rt=Math.clz32?Math.clz32:xe,vt=Math.log,Se=Math.LN2;function xe(e){return e>>>=0,e===0?32:31-(vt(e)/Se|0)|0}var Ge=256,_e=262144,Ie=4194304;function je(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 dt(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=je(a):(u&=s,u!==0?n=je(u):l||(l=s&~e,l!==0&&(n=je(l))))):(s=a&~i,s!==0?n=je(s):u!==0?n=je(u):l||(l=a&~e,l!==0&&(n=je(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 bt(e,t){return(e.pendingLanes&~(e.suspendedLanes&~e.pingedLanes)&t)===0}function cl(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 ci(){var e=Ie;return Ie<<=1,(Ie&62914560)===0&&(Ie=4194304),e}function ju(e){for(var t=[],l=0;31>l;l++)t.push(e);return t}function mn(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 Jt(e){return e.replace(xm,function(t){return"\\"+t.charCodeAt(0).toString(16)+" "})}function Au(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=""+Kt(t)):e.value!==""+Kt(t)&&(e.value=""+Kt(t)):u!=="submit"&&u!=="reset"||e.removeAttribute("value"),t!=null?Du(e,u,Kt(t)):l!=null?Du(e,u,Kt(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=""+Kt(s):e.removeAttribute("name")}function sf(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)){Nu(e);return}l=l!=null?""+Kt(l):"",t=t!=null?""+Kt(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),Nu(e)}function Du(e,t,l){t==="number"&&oi(e.ownerDocument)===e||e.defaultValue===""+l||(e.defaultValue=""+l)}function Ca(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"),Bu=!1;if(yl)try{var pn={};Object.defineProperty(pn,"passive",{get:function(){Bu=!0}}),window.addEventListener("test",pn,pn),window.removeEventListener("test",pn,pn)}catch{Bu=!1}var Ul=null,Ru=null,di=null;function yf(){if(di)return di;var e,t=Ru,l=t.length,a,n="value"in Ul?Ul.value:Ul.textContent,i=n.length;for(e=0;e=Sn),xf=" ",_f=!1;function jf(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 zf(e){return e=e.detail,typeof e=="object"&&"data"in e?e.data:null}var Ba=!1;function Fm(e,t){switch(e){case"compositionend":return zf(t);case"keypress":return t.which!==32?null:(_f=!0,xf);case"textInput":return e=t.data,e===xf&&_f?null:e;default:return null}}function Im(e,t){if(Ba)return e==="compositionend"||!Yu&&jf(e,t)?(e=yf(),di=Ru=Ul=null,Ba=!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=Of(l)}}function wf(e,t){return e&&t?e===t?!0:e&&e.nodeType===3?!1:t&&t.nodeType===3?wf(e,t.parentNode):"contains"in e?e.contains(t):e.compareDocumentPosition?!!(e.compareDocumentPosition(t)&16):!1:!1}function Bf(e){e=e!=null&&e.ownerDocument!=null&&e.ownerDocument.defaultView!=null?e.ownerDocument.defaultView:window;for(var t=oi(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=oi(e.document)}return t}function Qu(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=yl&&"documentMode"in document&&11>=document.documentMode,Ra=null,Vu=null,zn=null,Zu=!1;function Rf(e,t,l){var a=l.window===l?l.document:l.nodeType===9?l:l.ownerDocument;Zu||Ra==null||Ra!==oi(a)||(a=Ra,"selectionStart"in a&&Qu(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}),zn&&jn(zn,a)||(zn=a,a=iu(Vu,"onSelect"),0>=u,n-=u,sl=1<<32-rt(t)+n|l<ue?(pe=Q,Q=null):pe=Q.sibling;var Te=v(y,Q,g[ue],T);if(Te===null){Q===null&&(Q=pe);break}e&&Q&&Te.alternate===null&&t(y,Q),m=i(Te,m,ue),ze===null?$=Te:ze.sibling=Te,ze=Te,Q=pe}if(ue===g.length)return l(y,Q),be&&pl(y,ue),$;if(Q===null){for(;ueue?(pe=Q,Q=null):pe=Q.sibling;var ta=v(y,Q,Te.value,T);if(ta===null){Q===null&&(Q=pe);break}e&&Q&&ta.alternate===null&&t(y,Q),m=i(ta,m,ue),ze===null?$=ta:ze.sibling=ta,ze=ta,Q=pe}if(Te.done)return l(y,Q),be&&pl(y,ue),$;if(Q===null){for(;!Te.done;ue++,Te=g.next())Te=M(y,Te.value,T),Te!==null&&(m=i(Te,m,ue),ze===null?$=Te:ze.sibling=Te,ze=Te);return be&&pl(y,ue),$}for(Q=a(Q);!Te.done;ue++,Te=g.next())Te=S(Q,y,ue,Te.value,T),Te!==null&&(e&&Te.alternate!==null&&Q.delete(Te.key===null?ue:Te.key),m=i(Te,m,ue),ze===null?$=Te:ze.sibling=Te,ze=Te);return e&&Q.forEach(function(M0){return t(y,M0)}),be&&pl(y,ue),$}function Be(y,m,g,T){if(typeof g=="object"&&g!==null&&g.type===L&&g.key===null&&(g=g.props.children),typeof g=="object"&&g!==null){switch(g.$$typeof){case fe:e:{for(var $=g.key;m!==null;){if(m.key===$){if($=g.type,$===L){if(m.tag===7){l(y,m.sibling),T=n(m,g.props.children),T.return=y,y=T;break e}}else if(m.elementType===$||typeof $=="object"&&$!==null&&$.$$typeof===ve&&ga($)===m.type){l(y,m.sibling),T=n(m,g.props),Dn(T,g),T.return=y,y=T;break e}l(y,m);break}else t(y,m);m=m.sibling}g.type===L?(T=ra(g.props.children,y.mode,T,g.key),T.return=y,y=T):(T=_i(g.type,g.key,g.props,null,y.mode,T),Dn(T,g),T.return=y,y=T)}return u(y);case X:e:{for($=g.key;m!==null;){if(m.key===$)if(m.tag===4&&m.stateNode.containerInfo===g.containerInfo&&m.stateNode.implementation===g.implementation){l(y,m.sibling),T=n(m,g.children||[]),T.return=y,y=T;break e}else{l(y,m);break}else t(y,m);m=m.sibling}T=Pu(g,y.mode,T),T.return=y,y=T}return u(y);case ve:return g=ga(g),Be(y,m,g,T)}if(Xe(g))return k(y,m,g,T);if(Je(g)){if($=Je(g),typeof $!="function")throw Error(r(150));return g=$.call(g),I(y,m,g,T)}if(typeof g.then=="function")return Be(y,m,Ai(g),T);if(g.$$typeof===de)return Be(y,m,Ti(y,g),T);Di(y,g)}return typeof g=="string"&&g!==""||typeof g=="number"||typeof g=="bigint"?(g=""+g,m!==null&&m.tag===6?(l(y,m.sibling),T=n(m,g),T.return=y,y=T):(l(y,m),T=Iu(g,y.mode,T),T.return=y,y=T),u(y)):l(y,m)}return function(y,m,g,T){try{An=0;var $=Be(y,m,g,T);return Ka=null,$}catch(Q){if(Q===Za||Q===Ei)throw Q;var ze=Yt(29,Q,null,y.mode);return ze.lanes=T,ze.return=y,ze}}}var va=io(!0),uo=io(!1),Gl=!1;function rc(e){e.updateQueue={baseState:e.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,lanes:0,hiddenCallbacks:null},callbacks:null}}function dc(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 ql(e){return{lane:e,tag:0,payload:null,callback:null,next:null}}function Ll(e,t,l){var a=e.updateQueue;if(a===null)return null;if(a=a.shared,(Me&2)!==0){var n=a.pending;return n===null?t.next=t:(t.next=n.next,n.next=t),a.pending=t,t=xi(e),Xf(e,null,l),t}return Si(e,a,t,l),xi(e)}function Cn(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,Ws(e,l)}}function mc(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 hc=!1;function On(){if(hc){var e=Va;if(e!==null)throw e}}function Un(e,t,l,a){hc=!1;var n=e.updateQueue;Gl=!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?(ge&v)===v:(a&v)===v){v!==0&&v===Qa&&(hc=!0),z!==null&&(z=z.next={lane:0,tag:s.tag,payload:s.payload,callback:null,next:null});e:{var k=e,I=s;v=t;var Be=l;switch(I.tag){case 1:if(k=I.payload,typeof k=="function"){M=k.call(Be,M,v);break e}M=k;break e;case 3:k.flags=k.flags&-65537|128;case 0:if(k=I.payload,v=typeof k=="function"?k.call(Be,M,v):k,v==null)break e;M=U({},M,v);break e;case 2:Gl=!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),Vl|=u,e.lanes=u,e.memoizedState=M}}function co(e,t){if(typeof e!="function")throw Error(r(191,e));e.call(t)}function so(e,t){var l=e.callbacks;if(l!==null)for(e.callbacks=null,e=0;ei?i:8;var u=_.T,s={};_.T=s,Uc(e,!1,t,l);try{var o=n(),p=_.S;if(p!==null&&p(s,o),o!==null&&typeof o=="object"&&typeof o.then=="function"){var z=yh(o,a);Rn(e,t,z,Zt(e))}else Rn(e,t,a,Zt(e))}catch(M){Rn(e,t,{then:function(){},status:"rejected",reason:M},Zt())}finally{C.p=i,u!==null&&s.types!==null&&(u.types=s.types),_.T=u}}function xh(){}function Cc(e,t,l,a){if(e.tag!==5)throw Error(r(476));var n=Yo(e).queue;Lo(e,n,t,J,l===null?xh:function(){return ko(e),l(a)})}function Yo(e){var t=e.memoizedState;if(t!==null)return t;t={memoizedState:J,baseState:J,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:xl,lastRenderedState:J},next:null};var l={};return t.next={memoizedState:l,baseState:l,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:xl,lastRenderedState:l},next:null},e.memoizedState=t,e=e.alternate,e!==null&&(e.memoizedState=t),t}function ko(e){var t=Yo(e);t.next===null&&(t=e.alternate.memoizedState),Rn(e,t.next.queue,{},Zt())}function Oc(){return _t(Pn)}function Xo(){return at().memoizedState}function Qo(){return at().memoizedState}function _h(e){for(var t=e.return;t!==null;){switch(t.tag){case 24:case 3:var l=Zt();e=ql(l);var a=Ll(t,e,l);a!==null&&(Rt(a,t,l),Cn(a,t,l)),t={cache:cc()},e.payload=t;return}t=t.return}}function jh(e,t,l){var a=Zt();l={lane:a,revertLane:0,gesture:null,action:l,hasEagerState:!1,eagerState:null,next:null},Li(e)?Zo(t,l):(l=Wu(e,t,l,a),l!==null&&(Rt(l,e,a),Ko(l,t,a)))}function Vo(e,t,l){var a=Zt();Rn(e,t,l,a)}function Rn(e,t,l,a){var n={lane:a,revertLane:0,gesture:null,action:l,hasEagerState:!1,eagerState:null,next:null};if(Li(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,Lt(s,u))return Si(e,t,n,0),qe===null&&bi(),!1}catch{}if(l=Wu(e,t,n,a),l!==null)return Rt(l,e,a),Ko(l,t,a),!0}return!1}function Uc(e,t,l,a){if(a={lane:2,revertLane:rs(),gesture:null,action:a,hasEagerState:!1,eagerState:null,next:null},Li(e)){if(t)throw Error(r(479))}else t=Wu(e,l,a,2),t!==null&&Rt(t,e,2)}function Li(e){var t=e.alternate;return e===ne||t!==null&&t===ne}function Zo(e,t){$a=Ui=!0;var l=e.pending;l===null?t.next=t:(t.next=l.next,l.next=t),e.pending=t}function Ko(e,t,l){if((l&4194048)!==0){var a=t.lanes;a&=e.pendingLanes,l|=a,t.lanes=l,Ws(e,l)}}var Hn={readContext:_t,use:Ri,useCallback:Pe,useContext:Pe,useEffect:Pe,useImperativeHandle:Pe,useLayoutEffect:Pe,useInsertionEffect:Pe,useMemo:Pe,useReducer:Pe,useRef:Pe,useState:Pe,useDebugValue:Pe,useDeferredValue:Pe,useTransition:Pe,useSyncExternalStore:Pe,useId:Pe,useHostTransitionStatus:Pe,useFormState:Pe,useActionState:Pe,useOptimistic:Pe,useMemoCache:Pe,useCacheRefresh:Pe};Hn.useEffectEvent=Pe;var Jo={readContext:_t,use:Ri,useCallback:function(e,t){return Nt().memoizedState=[e,t===void 0?null:t],e},useContext:_t,useEffect:Co,useImperativeHandle:function(e,t,l){l=l!=null?l.concat([e]):null,Gi(4194308,4,Bo.bind(null,t,e),l)},useLayoutEffect:function(e,t){return Gi(4194308,4,e,t)},useInsertionEffect:function(e,t){Gi(4,2,e,t)},useMemo:function(e,t){var l=Nt();t=t===void 0?null:t;var a=e();if(ba){qt(!0);try{e()}finally{qt(!1)}}return l.memoizedState=[a,t],a},useReducer:function(e,t,l){var a=Nt();if(l!==void 0){var n=l(t);if(ba){qt(!0);try{l(t)}finally{qt(!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,ne,e),[a.memoizedState,e]},useRef:function(e){var t=Nt();return e={current:e},t.memoizedState=e},useState:function(e){e=Mc(e);var t=e.queue,l=Vo.bind(null,ne,t);return t.dispatch=l,[e.memoizedState,l]},useDebugValue:Ac,useDeferredValue:function(e,t){var l=Nt();return Dc(l,e,t)},useTransition:function(){var e=Mc(!1);return e=Lo.bind(null,ne,e.queue,!0,!1),Nt().memoizedState=e,[!1,e]},useSyncExternalStore:function(e,t,l){var a=ne,n=Nt();if(be){if(l===void 0)throw Error(r(407));l=l()}else{if(l=t(),qe===null)throw Error(r(349));(ge&127)!==0||yo(a,t,l)}n.memoizedState=l;var i={value:l,getSnapshot:t};return n.queue=i,Co(po.bind(null,a,i,e),[e]),a.flags|=2048,Fa(9,{destroy:void 0},go.bind(null,a,i,l,t),null),l},useId:function(){var e=Nt(),t=qe.identifierPrefix;if(be){var l=fl,a=sl;l=(a&~(1<<32-rt(a)-1)).toString(32)+l,t="_"+t+"R_"+l,l=wi++,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[St]=t,i[Dt]=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(zt(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&&jl(t)}}return Ye(t),Kc(t,t.type,e===null?null:e.memoizedProps,t.pendingProps,l),null;case 6:if(e&&t.stateNode!=null)e.memoizedProps!==a&&jl(t);else{if(typeof a!="string"&&t.stateNode===null)throw Error(r(166));if(e=ee.current,ka(t)){if(e=t.stateNode,l=t.memoizedProps,a=null,n=xt,n!==null)switch(n.tag){case 27:case 5:a=n.memoizedProps}e[St]=t,e=!!(e.nodeValue===l||a!==null&&a.suppressHydrationWarning===!0||md(e.nodeValue,l)),e||Rl(t,!0)}else e=uu(e).createTextNode(a),e[St]=t,t.stateNode=e}return Ye(t),null;case 31:if(l=t.memoizedState,e===null||e.memoizedState!==null){if(a=ka(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[St]=t}else da(),(t.flags&128)===0&&(t.memoizedState=null),t.flags|=4;Ye(t),e=!1}else l=ac(),e!==null&&e.memoizedState!==null&&(e.memoizedState.hydrationErrors=l),e=!0;if(!e)return t.flags&256?(Xt(t),t):(Xt(t),null);if((t.flags&128)!==0)throw Error(r(558))}return Ye(t),null;case 13:if(a=t.memoizedState,e===null||e.memoizedState!==null&&e.memoizedState.dehydrated!==null){if(n=ka(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[St]=t}else da(),(t.flags&128)===0&&(t.memoizedState=null),t.flags|=4;Ye(t),n=!1}else n=ac(),e!==null&&e.memoizedState!==null&&(e.memoizedState.hydrationErrors=n),n=!0;if(!n)return t.flags&256?(Xt(t),t):(Xt(t),null)}return Xt(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),Vi(t,t.updateQueue),Ye(t),null);case 4:return Ne(),e===null&&ys(t.stateNode.containerInfo),Ye(t),null;case 10:return bl(t.type),Ye(t),null;case 19:if(j(lt),a=t.memoizedState,a===null)return Ye(t),null;if(n=(t.flags&128)!==0,i=a.rendering,i===null)if(n)qn(a,!1);else{if(et!==0||e!==null&&(e.flags&128)!==0)for(e=t.child;e!==null;){if(i=Oi(e),i!==null){for(t.flags|=128,qn(a,!1),e=i.updateQueue,t.updateQueue=e,Vi(t,e),t.subtreeFlags=0,e=l,l=t.child;l!==null;)Qf(l,e),l=l.sibling;return B(lt,lt.current&1|2),be&&pl(t,a.treeForkCount),t.child}e=e.sibling}a.tail!==null&&Re()>Wi&&(t.flags|=128,n=!0,qn(a,!1),t.lanes=4194304)}else{if(!n)if(e=Oi(i),e!==null){if(t.flags|=128,n=!0,e=e.updateQueue,t.updateQueue=e,Vi(t,e),qn(a,!0),a.tail===null&&a.tailMode==="hidden"&&!i.alternate&&!be)return Ye(t),null}else 2*Re()-a.renderingStartTime>Wi&&l!==536870912&&(t.flags|=128,n=!0,qn(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=Re(),e.sibling=null,l=lt.current,B(lt,n?l&1|2:l&1),be&&pl(t,a.treeForkCount),e):(Ye(t),null);case 22:case 23:return Xt(t),gc(),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&&(Ye(t),t.subtreeFlags&6&&(t.flags|=8192)):Ye(t),l=t.updateQueue,l!==null&&Vi(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(ya),null;case 24:return l=null,e!==null&&(l=e.memoizedState.cache),t.memoizedState.cache!==l&&(t.flags|=2048),bl(nt),Ye(t),null;case 25:return null;case 30:return null}throw Error(r(156,t.tag))}function Nh(e,t){switch(tc(t),t.tag){case 1:return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 3:return bl(nt),Ne(),e=t.flags,(e&65536)!==0&&(e&128)===0?(t.flags=e&-65537|128,t):null;case 26:case 27:case 5:return Et(t),null;case 31:if(t.memoizedState!==null){if(Xt(t),t.alternate===null)throw Error(r(340));da()}return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 13:if(Xt(t),e=t.memoizedState,e!==null&&e.dehydrated!==null){if(t.alternate===null)throw Error(r(340));da()}return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 19:return j(lt),null;case 4:return Ne(),null;case 10:return bl(t.type),null;case 22:case 23:return Xt(t),gc(),e!==null&&j(ya),e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 24:return bl(nt),null;case 25:return null;default:return null}}function vr(e,t){switch(tc(t),t.tag){case 3:bl(nt),Ne();break;case 26:case 27:case 5:Et(t);break;case 4:Ne();break;case 31:t.memoizedState!==null&&Xt(t);break;case 13:Xt(t);break;case 19:j(lt);break;case 10:bl(t.type);break;case 22:case 23:Xt(t),gc(),e!==null&&j(ya);break;case 24:bl(nt)}}function Ln(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){Ce(t,t.return,s)}}function Xl(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){Ce(n,o,z)}}}a=a.next}while(a!==i)}}catch(z){Ce(t,t.return,z)}}function br(e){var t=e.updateQueue;if(t!==null){var l=e.stateNode;try{so(t,l)}catch(a){Ce(e,e.return,a)}}}function Sr(e,t,l){l.props=Sa(e.type,e.memoizedProps),l.state=e.memoizedState;try{l.componentWillUnmount()}catch(a){Ce(e,t,a)}}function Yn(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){Ce(e,t,n)}}function ol(e,t){var l=e.ref,a=e.refCleanup;if(l!==null)if(typeof a=="function")try{a()}catch(n){Ce(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){Ce(e,t,n)}else l.current=null}function xr(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){Ce(e,e.return,n)}}function Jc(e,t,l){try{var a=e.stateNode;Wh(a,e.type,l,t),a[Dt]=t}catch(n){Ce(e,e.return,n)}}function _r(e){return e.tag===5||e.tag===3||e.tag===26||e.tag===27&&Wl(e.type)||e.tag===4}function $c(e){e:for(;;){for(;e.sibling===null;){if(e.return===null||_r(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&&Wl(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 Wc(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=hl));else if(a!==4&&(a===27&&Wl(e.type)&&(l=e.stateNode,t=null),e=e.child,e!==null))for(Wc(e,t,l),e=e.sibling;e!==null;)Wc(e,t,l),e=e.sibling}function Zi(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&&Wl(e.type)&&(l=e.stateNode),e=e.child,e!==null))for(Zi(e,t,l),e=e.sibling;e!==null;)Zi(e,t,l),e=e.sibling}function jr(e){var t=e.stateNode,l=e.memoizedProps;try{for(var a=e.type,n=t.attributes;n.length;)t.removeAttributeNode(n[0]);zt(t,a,l),t[St]=e,t[Dt]=l}catch(i){Ce(e,e.return,i)}}var zl=!1,ct=!1,Fc=!1,zr=typeof WeakSet=="function"?WeakSet:Set,ht=null;function Ah(e,t){if(e=e.containerInfo,vs=mu,e=Bf(e),Qu(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(bs={focusedElem:e,selectionRange:l},mu=!1,ht=t;ht!==null;)if(t=ht,e=t.child,(t.subtreeFlags&1028)!==0&&e!==null)e.return=t,ht=e;else for(;ht!==null;){switch(t=ht,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"))),zt(i,a,l),i[St]=e,mt(i),a=i;break e;case"link":var u=Dd("link","href",n).get(a+(l.href||""));if(u){for(var s=0;sBe&&(u=Be,Be=I,I=u);var y=Uf(s,I),m=Uf(s,Be);if(y&&m&&(S.rangeCount!==1||S.anchorNode!==y.node||S.anchorOffset!==y.offset||S.focusNode!==m.node||S.focusOffset!==m.offset)){var g=M.createRange();g.setStart(y.node,y.offset),S.removeAllRanges(),I>Be?(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,_.T=null,l=ns,ns=null;var i=Kl,u=Al;if(ot=0,ln=Kl=null,Al=0,(Me&6)!==0)throw Error(r(331));var s=Me;if(Me|=4,Br(i.current),Or(i,i.current,u,l),Me=s,Kn(0,!1),tt&&typeof tt.onPostCommitFiberRoot=="function")try{tt.onPostCommitFiberRoot(ft,i)}catch{}return!0}finally{C.p=n,_.T=a,Pr(e,t)}}function td(e,t,l){t=Wt(l,t),t=Hc(e.stateNode,t,2),e=Ll(e,t,2),e!==null&&(mn(e,2),rl(e))}function Ce(e,t,l){if(e.tag===3)td(e,e,l);else for(;t!==null;){if(t.tag===3){td(t,e,l);break}else if(t.tag===1){var a=t.stateNode;if(typeof t.type.getDerivedStateFromError=="function"||typeof a.componentDidCatch=="function"&&(Zl===null||!Zl.has(a))){e=Wt(l,e),l=lr(2),a=Ll(t,l,2),a!==null&&(ar(l,a,t,e),mn(a,2),rl(a));break}}t=t.return}}function ss(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)||(es=!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,qe===e&&(ge&l)===l&&(et===4||et===3&&(ge&62914560)===ge&&300>Re()-$i?(Me&2)===0&&an(e,0):ts|=l,tn===ge&&(tn=0)),rl(e)}function ld(e,t){t===0&&(t=ci()),e=oa(e,t),e!==null&&(mn(e,t),rl(e))}function Gh(e){var t=e.memoizedState,l=0;t!==null&&(l=t.retryLane),ld(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),ld(e,l)}function Lh(e,t){return ae(e,t)}var lu=null,un=null,fs=!1,au=!1,os=!1,$l=0;function rl(e){e!==un&&e.next===null&&(un===null?lu=un=e:un=un.next=e),au=!0,fs||(fs=!0,kh())}function Kn(e,t){if(!os&&au){os=!0;do for(var l=!1,a=lu;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-rt(42|e)+1)-1,i&=n&~(u&~s),i=i&201326741?i&201326741|1:i?i|2:0}i!==0&&(l=!0,ud(a,i))}else i=ge,i=dt(a,a===qe?i:0,a.cancelPendingCommit!==null||a.timeoutHandle!==-1),(i&3)===0||bt(a,i)||(l=!0,ud(a,i));a=a.next}while(l);os=!1}}function Yh(){ad()}function ad(){au=fs=!1;var e=0;$l!==0&&Ih()&&(e=$l);for(var t=Re(),l=null,a=lu;a!==null;){var n=a.next,i=nd(a,t);i===0?(a.next=null,l===null?lu=n:l.next=n,n===null&&(un=l)):(l=a,(e!==0||(i&3)!==0)&&(au=!0)),a=n}ot!==0&&ot!==5||Kn(e),$l!==0&&($l=0)}function nd(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&&hd(M)&&(o=o.responseEnd,u+=z*(o"u"?null:document;function Md(e,t,l){var a=cn;if(a&&typeof t=="string"&&t){var n=Jt(t);n='link[rel="'+e+'"][href="'+n+'"]',typeof l=="string"&&(n+='[crossorigin="'+l+'"]'),Td.has(n)||(Td.add(n),e={rel:e,crossOrigin:l,href:t},a.querySelector(n)===null&&(t=a.createElement("link"),zt(t,"link",e),mt(t),a.head.appendChild(t)))}}function c0(e){Dl.D(e),Md("dns-prefetch",e,null)}function s0(e,t){Dl.C(e,t),Md("preconnect",e,t)}function f0(e,t,l){Dl.L(e,t,l);var a=cn;if(a&&e&&t){var n='link[rel="preload"][as="'+Jt(t)+'"]';t==="image"&&l&&l.imageSrcSet?(n+='[imagesrcset="'+Jt(l.imageSrcSet)+'"]',typeof l.imageSizes=="string"&&(n+='[imagesizes="'+Jt(l.imageSizes)+'"]')):n+='[href="'+Jt(e)+'"]';var i=n;switch(t){case"style":i=sn(e);break;case"script":i=fn(e)}ll.has(i)||(e=U({rel:"preload",href:t==="image"&&l&&l.imageSrcSet?void 0:e,as:t},l),ll.set(i,e),a.querySelector(n)!==null||t==="style"&&a.querySelector(Fn(i))||t==="script"&&a.querySelector(In(i))||(t=a.createElement("link"),zt(t,"link",e),mt(t),a.head.appendChild(t)))}}function o0(e,t){Dl.m(e,t);var l=cn;if(l&&e){var a=t&&typeof t.as=="string"?t.as:"script",n='link[rel="modulepreload"][as="'+Jt(a)+'"][href="'+Jt(e)+'"]',i=n;switch(a){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":i=fn(e)}if(!ll.has(i)&&(e=U({rel:"modulepreload",href:e},t),ll.set(i,e),l.querySelector(n)===null)){switch(a){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":if(l.querySelector(In(i)))return}a=l.createElement("link"),zt(a,"link",e),mt(a),l.head.appendChild(a)}}}function r0(e,t,l){Dl.S(e,t,l);var a=cn;if(a&&e){var n=Aa(a).hoistableStyles,i=sn(e);t=t||"default";var u=n.get(i);if(!u){var s={loading:0,preload:null};if(u=a.querySelector(Fn(i)))s.loading=5;else{e=U({rel:"stylesheet",href:e,"data-precedence":t},l),(l=ll.get(i))&&Ms(e,l);var o=u=a.createElement("link");mt(o),zt(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,su(u,t,a)}u={type:"stylesheet",instance:u,count:1,state:s},n.set(i,u)}}}function d0(e,t){Dl.X(e,t);var l=cn;if(l&&e){var a=Aa(l).hoistableScripts,n=fn(e),i=a.get(n);i||(i=l.querySelector(In(n)),i||(e=U({src:e,async:!0},t),(t=ll.get(n))&&Es(e,t),i=l.createElement("script"),mt(i),zt(i,"link",e),l.head.appendChild(i)),i={type:"script",instance:i,count:1,state:null},a.set(n,i))}}function m0(e,t){Dl.M(e,t);var l=cn;if(l&&e){var a=Aa(l).hoistableScripts,n=fn(e),i=a.get(n);i||(i=l.querySelector(In(n)),i||(e=U({src:e,async:!0,type:"module"},t),(t=ll.get(n))&&Es(e,t),i=l.createElement("script"),mt(i),zt(i,"link",e),l.head.appendChild(i)),i={type:"script",instance:i,count:1,state:null},a.set(n,i))}}function Ed(e,t,l,a){var n=(n=ee.current)?cu(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=sn(l.href),l=Aa(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=sn(l.href);var i=Aa(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(Fn(e)))&&!i._p&&(u.instance=i,u.state.loading=5),ll.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},ll.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=fn(l),l=Aa(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 sn(e){return'href="'+Jt(e)+'"'}function Fn(e){return'link[rel="stylesheet"]['+e+"]"}function Nd(e){return U({},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}),zt(t,"link",l),mt(t),e.head.appendChild(t))}function fn(e){return'[src="'+Jt(e)+'"]'}function In(e){return"script[async]"+e}function Ad(e,t,l){if(t.count++,t.instance===null)switch(t.type){case"style":var a=e.querySelector('style[data-href~="'+Jt(l.href)+'"]');if(a)return t.instance=a,mt(a),a;var n=U({},l,{"data-href":l.href,"data-precedence":l.precedence,href:null,precedence:null});return a=(e.ownerDocument||e).createElement("style"),mt(a),zt(a,"style",n),su(a,l.precedence,e),t.instance=a;case"stylesheet":n=sn(l.href);var i=e.querySelector(Fn(n));if(i)return t.state.loading|=4,t.instance=i,mt(i),i;a=Nd(l),(n=ll.get(n))&&Ms(a,n),i=(e.ownerDocument||e).createElement("link"),mt(i);var u=i;return u._p=new Promise(function(s,o){u.onload=s,u.onerror=o}),zt(i,"link",a),t.state.loading|=4,su(i,l.precedence,e),t.instance=i;case"script":return i=fn(l.src),(n=e.querySelector(In(i)))?(t.instance=n,mt(n),n):(a=l,(n=ll.get(i))&&(a=U({},l),Es(a,n)),e=e.ownerDocument||e,n=e.createElement("script"),mt(n),zt(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,su(a,l.precedence,e));return t.instance}function su(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 Od(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=sn(a.href),i=t.querySelector(Fn(n));if(i){t=i._p,t!==null&&typeof t=="object"&&typeof t.then=="function"&&(e.count++,e=ou.bind(e),t.then(e,e)),l.state.loading|=4,l.instance=i,mt(i);return}i=t.ownerDocument||t,a=Nd(a),(n=ll.get(n))&&Ms(a,n),i=i.createElement("link"),mt(i);var u=i;u._p=new Promise(function(s,o){u.onload=s,u.onerror=o}),zt(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=ou.bind(e),t.addEventListener("load",l),t.addEventListener("error",l))}}var Ns=0;function p0(e,t){return e.stylesheets&&e.count===0&&du(e,e.stylesheets),0Ns?50:800)+t);return e.unsuspend=l,function(){e.unsuspend=null,clearTimeout(a),clearTimeout(n)}}:null}function ou(){if(this.count--,this.count===0&&(this.imgCount===0||!this.waitingForImages)){if(this.stylesheets)du(this,this.stylesheets);else if(this.unsuspend){var e=this.unsuspend;this.unsuspend=null,e()}}}var ru=null;function du(e,t){e.stylesheets=null,e.unsuspend!==null&&(e.count++,ru=new Map,t.forEach(v0,e),ru=null,ou.call(e))}function v0(e,t){if(!(t.state.loading&4)){var l=ru.get(e);if(l)var a=l.get(null);else{l=new Map,ru.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(),Hs.exports=B0(),Hs.exports}var H0=R0();const G0=fm(H0);const om=(...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 lm=f=>{const b=L0(f);return b.charAt(0).toUpperCase()+b.slice(1)};var Ys={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},k0=O.createContext({}),X0=()=>O.useContext(k0),Q0=O.forwardRef(({color:f,size:b,strokeWidth:E,absoluteStrokeWidth:r,className:x="",children:N,iconNode:G,...H},w)=>{const{size:h=24,strokeWidth:A=2,absoluteStrokeWidth:U=!1,color:V="currentColor",className:fe=""}=X0()??{},X=r??U?Number(E??A)*24/Number(b??h):E??A;return O.createElement("svg",{ref:w,...Ys,width:b??h??Ys.width,height:b??h??Ys.height,stroke:f??V,strokeWidth:X,className:om("lucide",fe,x),...!N&&!Y0(H)&&{"aria-hidden":"true"},...H},[...G.map(([L,te])=>O.createElement(L,te)),...Array.isArray(N)?N:[N]])});const Ve=(f,b)=>{const E=O.forwardRef(({className:r,...x},N)=>O.createElement(Q0,{ref:N,iconNode:b,className:om(`lucide-${q0(lm(f))}`,`lucide-${f}`,r),...x}));return E.displayName=lm(f),E};const V0=[["path",{d:"M20 6 9 17l-5-5",key:"1gmf2c"}]],ks=Ve("check",V0);const Z0=[["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"}]],am=Ve("cloud-download",Z0);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=Ve("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"}]],rm=Ve("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=Ve("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"}]],Xs=Ve("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"}]],nm=Ve("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=Ve("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"}]],im=Ve("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"}]],xu=Ve("hard-drive",ay);const ny=[["path",{d:"M16 5h6",key:"1vod17"}],["path",{d:"M19 2v6",key:"4bpg5p"}],["path",{d:"M21 11.5V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h7.5",key:"1ue2ih"}],["path",{d:"m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21",key:"1xmnt7"}],["circle",{cx:"9",cy:"9",r:"2",key:"af1f0g"}]],iy=Ve("image-plus",ny);const uy=[["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"}]],cy=Ve("image",uy);const sy=[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["path",{d:"M12 16v-4",key:"1dtifu"}],["path",{d:"M12 8h.01",key:"e9boi3"}]],fy=Ve("info",sy);const oy=[["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"}]],ry=Ve("library",oy);const dy=[["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"}]],my=Ve("moon",dy);const hy=[["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"}]],aa=Ve("refresh-cw",hy);const yy=[["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"}]],gy=Ve("shield",yy);const py=[["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"}]],Ks=Ve("sliders-vertical",py);const vy=[["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"}]],Su=Ve("sparkles",vy);const by=[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",key:"afitv7"}]],Qs=Ve("square",by);const Sy=[["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"}]],xy=Ve("sun",Sy);const _y=[["path",{d:"M12 19h8",key:"baeox8"}],["path",{d:"m4 17 6-6-6-6",key:"1yngyt"}]],jy=Ve("terminal",_y);const zy=[["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"}]],rn=Ve("trash-2",zy);const Ty=[["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"}]],My=Ve("triangle-alert",Ty);function Ey({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(gy,{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(cy,{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(Ks,{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(jy,{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 Ny=O.memo(Ey);function Ay({telemetry:f,serverRunning:b,activeModel:E,onStopServer:r,isStoppingServer:x=!1,theme:N,setTheme:G}){const H=A=>{const U=Number(A);return Number.isFinite(U)&&U>0?U.toFixed(U>=10?0:1):"--"},w=()=>b?"Server Active":"Local Mode",h=()=>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:h()}),c.jsx("span",{style:{fontWeight:600,fontSize:"0.95rem"},children:w()}),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(xy,{size:18}):c.jsx(my,{size:18})}),b&&c.jsxs("button",{className:"m3-btn m3-btn-error",style:{height:"34px",padding:"0 14px"},onClick:r,disabled:x,title:"Stop local model server",children:[x?c.jsx(aa,{className:"progress-spinner",size:14}):c.jsx(Qs,{size:14}),c.jsx("span",{children:x?"Stopping":"Stop Server"})]}),c.jsxs("div",{className:"telemetry-chip",title:"CPU Utilization",children:[c.jsx(rm,{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(xu,{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(Xs,{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 Dy=O.memo(Ay),Cy="modulepreload",Oy=function(f){return"/"+f},um={},Uy=function(b,E,r){let x=Promise.resolve();if(E&&E.length>0){let w=function(h){return Promise.all(h.map(A=>Promise.resolve(A).then(U=>({status:"fulfilled",value:U}),U=>({status:"rejected",reason:U}))))};document.getElementsByTagName("link");const G=document.querySelector("meta[property=csp-nonce]"),H=G?.nonce||G?.getAttribute("nonce");x=w(E.map(h=>{if(h=Oy(h),h in um)return;um[h]=!0;const A=h.endsWith(".css"),U=A?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${h}"]${U}`))return;const V=document.createElement("link");if(V.rel=A?"stylesheet":Cy,A||(V.as="script"),V.crossOrigin="",V.href=h,H&&V.setAttribute("nonce",H),document.head.appendChild(V),A)return new Promise((fe,X)=>{V.addEventListener("load",fe),V.addEventListener("error",()=>X(new Error(`Unable to preload CSS for ${h}`)))})}))}function N(G){const H=new Event("vite:preloadError",{cancelable:!0});if(H.payload=G,window.dispatchEvent(H),!H.defaultPrevented)throw G}return x.then(G=>{for(const H of G||[])H.status==="rejected"&&N(H.reason);return b().catch(N)})};function rg(f,b=!1){return window.__TAURI_INTERNALS__.transformCallback(f,b)}async function ja(f,b={},E){return window.__TAURI_INTERNALS__.invoke(f,b,E)}const ia=()=>typeof window<"u"&&window.__TAURI_INTERNALS__!==void 0;let la=null,_u=null;const wy="polish-setup-v1",na=()=>typeof window<"u"&&(window.location.hostname==="localhost"||window.location.hostname==="127.0.0.1");async function dm(){if(na())try{const f=await Cl(),b=Number(f?.port);if(Number.isInteger(b)&&b>0)return _u=b,b}catch{}return _u||8080}async function mm(){return`http://127.0.0.1:${await dm()}`}function ii(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 ui(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?ii(f.sizeBytes):"Unknown")}}async function dn(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&&(_u=Number(G.port)),console.log("Backend restart:",G.message),G.message}catch(x){if(console.warn("Could not reach management API:",x.message),na())throw x;return"Backend management unavailable"}}async function Js(){if(ia())return await ja("stop_server");try{await fetch("/api/stop-backend",{method:"POST"})}catch{}return"Backend stopped"}async function Cl(){try{return await(await fetch("/api/backend-status")).json()}catch{return{ready:!1,settings:{}}}}async function Xy(){try{return(await(await fetch("/api/outputs")).json()).outputs||[]}catch{return[]}}async function Qy(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 dn(E,"The local server returned an invalid save response.")).output}async function Vy(f){const b=await fetch("/api/delete-outputs",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({outputs:f})});return await dn(b,"The local server returned an invalid delete response.")}async function Zy(){try{return((await(await fetch("/api/models")).json()).models||[]).map(ui)}catch{return[]}}async function Ky(f,b,E,r,x,N,G){console.log("Initiating image generation:",{prompt:f,negativePrompt:b,constraints:E,activeModelName:r});const H=Date.now(),w=await mm(),h={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:x||null,denoising_strength:E.denoisingStrength||.7},A=async()=>{const X=h.steps;for(let Ke=1;Ke<=X;Ke++){if(G&&G.aborted)throw new DOMException("The user aborted a request.","AbortError");await new Promise(yt=>setTimeout(yt,3e3/X)),N&&N(Math.round(Ke/X*100))}const L=f.toLowerCase(),te=Math.abs(h.seed)||Math.floor(Math.random()*1e3);let W="#3B82F6",Oe="#8B5CF6",de="",Ee="Abstract Generation";L.includes("moon")||L.includes("space")||L.includes("astronomy")||L.includes("sky")?(W="#1E293B",Oe="#0F172A",Ee="Luminous Moon in Starry Sky",de=` - - - - - - - - - - - - `):L.includes("cat")||L.includes("kitten")||L.includes("feline")?(W="#4F46E5",Oe="#7C3AED",Ee="Stylized Cat Portrait",de=` - - - - - - - - - - - - - - - - `):L.includes("dog")||L.includes("puppy")||L.includes("canine")?(W="#D97706",Oe="#B45309",Ee="Friendly Dog Portrait",de=` - - - - - - - - - - - - - `):L.includes("city")||L.includes("cyberpunk")||L.includes("tokyo")||L.includes("neon")?(W="#111827",Oe="#311042",Ee="Neon Cyberpunk Skyline",de=` - - - - - - - - - - - - - `):L.includes("car")||L.includes("vehicle")||L.includes("supercar")?(W="#DC2626",Oe="#991B1B",Ee="Futuristic Concept Car",de=` - - - - - - - - - - - - - `):(W="#06B6D4",Oe="#0891B2",Ee="Abstract Creative Concept",de=` - - - - `);const ke=` - - - - - - - - - - - - - - - - - ${de} - - - - - - - ${Ee} - Seed: ${te} • Steps: ${h.steps} • Scale: ${h.cfg_scale} - - `,P=`data:image/svg+xml;base64,${btoa(unescape(encodeURIComponent(ke)))}`,ve=parseFloat(((Date.now()-H)/1e3).toFixed(1));return{image:P,seed:h.seed,duration_sec:ve}},U=!!h.image;let V=`${w}/v1/images/generations`,fe={prompt:h.prompt,negative_prompt:h.negative_prompt||"",n:1,size:`${h.width}x${h.height}`,response_format:"b64_json",steps:h.steps,cfg_scale:h.cfg_scale,seed:h.seed,sample_method:h.sampler};if(U){const X=String(h.image).replace(/^data:[^;]+;base64,/,"");V=`${w}/sdapi/v1/img2img`,fe={init_images:[X],prompt:h.prompt,negative_prompt:h.negative_prompt||"",denoising_strength:h.denoising_strength,steps:h.steps,cfg_scale:h.cfg_scale,seed:h.seed,width:h.width,height:h.height,sampler_name:h.sampler,sample_method:h.sampler,batch_size:1,n_iter:1,send_images:!0,save_images:!1}}try{const X=await fetch(V,{method:"POST",headers:{"Content-Type":"application/json"},signal:G,body:JSON.stringify(fe)});if(X.ok){const L=await X.json(),te=L?.data?.[0]?.b64_json??L?.images?.[0];if(te){const W=parseFloat(((Date.now()-H)/1e3).toFixed(1));return{image:`data:image/png;base64,${te}`,seed:L.data?.[0]?.seed??h.seed,duration_sec:W}}}else{let L=`Generation failed (HTTP ${X.status})`;try{const te=await X.json();(te?.detail||te?.error?.message)&&(L=te.detail||te.error.message)}catch{}throw new Error(L)}}catch(X){if(X.name==="AbortError"||X.message.startsWith("Generation failed"))throw X;console.warn("Could not reach local server. Falling back to simulation mode.",X)}return await A()}async function Jy(f,b,E){if(f instanceof File){const H=f;if(!na())throw new Error("File import requires the local image generator server.");return await $y(H,b,E),{response:"Model imported successfully"}}if(ia()){const{listen:H}=await Uy(async()=>{const{listen:h}=await import("./event-DeDJUvqC.js");return{listen:h}},[]);let w=null;b&&(w=await H("import-progress",h=>{b(h.payload)}));try{return{response:await ja("import_model_file",{sourcePath:f}),unlisten:w}}catch(h){throw w&&w(),h}}const r=f.split(/[\\/]/).pop()||"imported_model.gguf";console.log(`Web Mode: Simulating copying ${r} to USB models folder`);const x=40;for(let H=1;H<=x;H++){if(E?.aborted)throw new DOMException("The user aborted a request.","AbortError");await new Promise(U=>setTimeout(U,150));const w=H/x*100,h=40+Math.sin(H)*5+Math.random()*2,A=(x-H)*.15;b&&b({filename:r,progress:w,speed_mb_s:h,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 $y(f,b,E){return new Promise((r,x)=>{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 w=()=>{H=!0,N.abort()};E&&(E.aborted?w():E.addEventListener("abort",w,{once:!0})),N.upload.onprogress=h=>{if(!h.lengthComputable||!b)return;const A=Math.max(.1,(Date.now()-G)/1e3),U=h.loaded/A,V=Math.max(0,h.total-h.loaded);b({filename:f.name,progress:h.loaded/h.total*100,speed_mb_s:U/(1024*1024),eta_secs:V/Math.max(1,U),status:"Copying to models folder..."})},N.onload=()=>{let h={};try{h=JSON.parse(N.responseText||"{}")}catch{}N.status>=200&&N.status<300&&h.ok!==!1?(b&&b({filename:f.name,progress:100,speed_mb_s:0,eta_secs:0,status:"Import complete"}),r(h)):x(new Error(h.error||`Import failed (HTTP ${N.status})`))},N.onerror=()=>x(new Error("Import failed while uploading the file.")),N.onabort=()=>x(new DOMException(H?"Import cancelled by user.":"Import aborted.","AbortError")),N.send(f)})}async function Wy(f){if(ia())return await ja("delete_model_file",{filename:f});if(typeof window<"u"&&(window.location.hostname==="localhost"||window.location.hostname==="127.0.0.1"))try{const x=await fetch("/api/delete-model",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({filename:f})}),N=await x.json();if(!x.ok)throw new Error(N.error||"Failed to delete model file");return N}catch(x){throw console.error("Failed to delete model via local API:",x),x}const E=localStorage.getItem("imported-models");let r=E?JSON.parse(E):[];return r=r.filter(x=>ui(x).filename!==f),localStorage.setItem("imported-models",JSON.stringify(r)),`Simulated deletion of ${f} from browser session`}async function hm(){const f=await mm();try{return(await fetch(`${f}/v1/models`,{method:"GET"})).ok}catch{return!1}}async function Fy(f=30){const b=ia()||na()?f:3;for(let E=0;EsetTimeout(x,500))}return!1}async function Iy(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 Py(){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 cm(){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 eg(){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 tg=O.memo(({img:f,idx:b,isSelected:E,onClick:r})=>{const x=N=>{r(b,N)};return c.jsxs("div",{className:`gallery-item ${E?"selected":""}`,onClick:x,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(ks,{size:14})})]})});function lg({prompt:f,setPrompt:b,negativePrompt:E,setNegativePrompt:r,constraints:x,setConstraints:N,activeModel:G,generatedImages:H,setGeneratedImages:w,isGenerating:h,setIsGenerating:A,generationProgress:U,setGenerationProgress:V,setActiveTab:fe,showAlert:X=async({message:te})=>window.alert(te),showConfirm:L=async({message:te})=>window.confirm(te)}){const[te,W]=O.useState(null),[Oe,de]=O.useState(null),[Ee,ke]=O.useState(null),[Ae,P]=O.useState(!1),[ve,Ke]=O.useState(0),[yt,me]=O.useState(0),[Je,st]=O.useState(0),[$e,Xe]=O.useState(""),[_,C]=O.useState(!1),[J,he]=O.useState(!1),[ce,d]=O.useState(!1),[j,B]=O.useState(null),[q,K]=O.useState(null),[ee,se]=O.useState(!1),[Ze,Ne]=O.useState([]),[gt,Et]=O.useState(null),We=O.useRef(null),Ht=O.useRef(null),Tt=O.useRef(!1),Z=Y=>{const ye=Y.target.files?.[0];if(Y.target.value="",!ye)return;if(!ye.type.startsWith("image/")){K("Please choose an image file (PNG, JPG, or WEBP).");return}const He=new FileReader;He.onload=()=>Et(He.result),He.onerror=()=>K("Could not read the selected image file."),He.readAsDataURL(ye)},ie=()=>Et(null),D=async()=>{if(!f.trim())return;K(null),d(!0),B(null);let Y=!1;try{const Se=await Cl();if(Se&&Se.settings){const xe=Se.settings,Ge=xe.model?xe.model.split(/[\\/]/).pop():null,_e=G?G.split(/[\\/]/).pop():null;(Ge!==_e||parseInt(xe.steps)!==parseInt(x.steps)||Math.abs(parseFloat(xe.cfgScale)-parseFloat(x.cfgScale))>.05||xe.sampler!==x.sampler||parseInt(xe.threads)!==parseInt(x.threads)||!!xe.useGpu!=(x.useGpu!==!1)||(xe.backendType||(xe.useGpu===!1?"cpu":"auto"))!==(x.backendType||(x.useGpu===!1?"cpu":"auto")))&&(Y=!0)}else Y=!0}catch{Y=!0}if(Y)try{console.log("Settings out of sync, restarting backend..."),await Vs(G,x);let Se=!1,xe=null;for(let Ge=0;Ge<240;Ge++){const _e=await Cl();if(_e.loading&&B({progress:_e.loading.progress||0,phase:_e.loading.phase||"Loading model...",speed:_e.loading.speed||"",current:_e.loading.current||0,total:_e.loading.total||0,backendMode:_e.loading.backendMode||_e.settings?.backendMode||"",device:_e.loading.device||_e.settings?.backendDevice||""}),_e.ready){Se=!0;break}if(_e.error){xe=_e.error;break}if(!_e.running&&Ge>3){xe="The backend process terminated immediately on startup.";break}await new Promise(Ie=>setTimeout(Ie,500))}if(!Se)throw new Error(xe||"Backend server failed to start after applying configuration changes.")}catch(Se){console.error("Failed to restart backend:",Se),K(Se.message||"Failed to sync settings with backend."),d(!1);return}d(!1),B(null),We.current&&clearInterval(We.current),A(!0),V(0),Ke(0),st(0),Xe(""),Tt.current=!1,C(!1),se(!1),ke(null),W(null);const ye=(x.width>=1024?140:35)*.04,He=x.width>=1024?140:35,pt=(x.backendType||(x.useGpu===!1?"cpu":"auto"))!=="cpu";let ft=pt?ye:He,tt=!1,qt=0,rt=0,vt=0;me(Math.round(x.steps*ft)),We.current=setInterval(async()=>{vt++,Ke(vt);try{const Se=await eg();if(Se&&Se.active){const xe=Se.decoding||!1;se(xe);const Ge=xe?Se.steps||x.steps||20:Se.step||0,_e=Se.steps||x.steps||20,Ie=xe?"":Se.speed||"";(xe||Se.steps>0)&&(Tt.current=!0,st(Ge)),Xe(xe?"decoding":Ie);let je=0;xe?je=99:_e>0&&(je=Math.round(Ge/_e*100)),je=Math.min(99,je),xe||Se.steps>0?V(je):V(bt=>Math.max(bt,je));let dt=0;if(xe)dt=3;else{const bt=parseFloat(Ie);if(!isNaN(bt)&&bt>0){const cl=Math.max(0,_e-Ge);Ie.includes("it/s")?dt=cl/bt:Ie.includes("s/it")&&(dt=cl*bt)}else{const cl=pt?ye:He;dt=Math.max(0,(_e-Ge)*cl)}}if(pt&&!tt){const bt=Ie.includes("it/s")&&numericSpeed<.2,cl=Ie.includes("s/it")&&numericSpeed>5;(bt||cl)&&(tt=!0,C(!0))}me(Math.round(dt))}else V(xe=>Math.min(15,xe+1)),me(xe=>Math.max(1,xe-1))}catch(Se){console.warn("Failed to get generation progress, running simulation fallback:",Se),pt&&!tt&&vt>x.steps*ye*1.3&&(tt=!0,C(!0),ft=He,qt=vt,rt=Math.min(95,Math.round(vt/(x.steps*ye)*100)));let xe=Math.min(x.steps-1,Math.floor(vt/ft)),Ge=x.steps*ft;if(vt>=Ge){const je=Math.ceil(vt/Math.max(.5,xe));ft=Math.max(ft+15,je+15),Ge=x.steps*ft,xe=Math.min(x.steps-1,Math.floor(vt/ft))}const _e=Math.max(1,Ge-vt);me(Math.round(_e));let Ie=0;if(tt){const je=99-rt,dt=Ge-qt;if(dt>0){const bt=Math.min(1,(vt-qt)/dt);if(bt<.85)Ie=Math.round(rt+bt*je);else{const cl=(vt-(qt+dt*.85))/(ft*2),ci=1-Math.exp(-cl);Ie=Math.min(99,Math.round(rt+.85*je+.14*je*ci))}}else Ie=99}else if(vtMath.max(je,Ie))}},1e3);try{Ht.current=new AbortController;const Se=await Ky(f,E,x,G,gt,je=>V(dt=>Math.max(dt,je)),Ht.current.signal);We.current&&clearInterval(We.current),V(100),st(x.steps),me(0),Xe("");const xe={prompt:f,negativePrompt:E,seed:Se.seed,steps:x.steps,cfgScale:x.cfgScale,width:x.width,height:x.height,sampler:x.sampler,model:G,mode:gt?"img2img":"txt2img",denoisingStrength:gt?x.denoisingStrength:null,duration_sec:Se.duration_sec,timestamp:new Date().toLocaleTimeString()};let Ge=null,_e=null;try{if(Ge=await Qy(Se.image,xe),_e=Ge.url,!_e)throw new Error("The local server saved the image but did not return a file URL.")}catch(je){throw console.error("Generated image could not be saved:",je),new Error(`Image generated but could not be saved to USB: ${je.message||je}`)}W(_e),de(Se.seed),ke(Se.duration_sec);const Ie={...xe,...Ge||{},url:_e};w(je=>[Ie,...je])}catch(Se){Se.name==="AbortError"?console.log("Generation request was aborted by the user"):(console.error("Generation failed:",Se),K(Se.message||"Generation failed. Please try again.")),We.current&&clearInterval(We.current)}finally{A(!1),Ht.current=null}},R=async()=>{if(await L({title:"Stop Generation?",message:"The current image generation will be cancelled and the local model server may restart.",confirmLabel:"Stop",danger:!0})){We.current&&clearInterval(We.current),he(!0),Ht.current&&Ht.current.abort();try{console.log("Cancelling: Stopping server to kill generation threads..."),await Js(),st(0),Xe(""),se(!1),Tt.current=!1,G&&(console.log("Cancelling: Restarting server for future generations..."),await Vs(G,x),await Fy()||console.warn("Server failed to restart properly."))}catch(Y){console.error("Failed to restart server on cancellation:",Y)}finally{he(!1),A(!1),V(0),me(0)}}},F=async()=>{if(te)try{if(te.startsWith("data:image")){const ye=await(await fetch(te)).blob();await navigator.clipboard.write([new ClipboardItem({[ye.type]:ye})])}else{const Y=new Image;Y.crossOrigin="anonymous",Y.src=te,Y.onload=async()=>{const ye=document.createElement("canvas");ye.width=Y.width,ye.height=Y.height,ye.getContext("2d").drawImage(Y,0,0),ye.toBlob(async pt=>{await navigator.clipboard.write([new ClipboardItem({[pt.type]:pt})])},"image/png")}}P(!0),setTimeout(()=>P(!1),2e3)}catch(Y){console.error("Failed to copy image:",Y)}},ae=()=>{if(!te)return;const Y=document.createElement("a");Y.href=te,Y.download=`diffusion-${Oe||Date.now()}.png`,document.body.appendChild(Y),Y.click(),document.body.removeChild(Y)},At=(Y,ye=`diffusion-${Date.now()}.png`)=>{if(!Y)return;const He=document.createElement("a");He.href=Y,He.download=ye,document.body.appendChild(He),He.click(),document.body.removeChild(He)},Gt=O.useCallback(Y=>{b(Y.prompt),r(Y.negativePrompt),N(ye=>({...ye,steps:Y.steps,cfgScale:Y.cfgScale,width:Y.width,height:Y.height,sampler:Y.sampler,seed:Y.seed})),W(Y.url),de(Y.seed),ke(Y.duration_sec??Y.durationSec??null)},[b,r,N]),dl=O.useCallback((Y,ye)=>{const He=ye.ctrlKey||ye.metaKey||ye.shiftKey;Ne(pt=>He?pt.includes(Y)?pt.filter(ft=>ft!==Y):[...pt,Y]:[Y]),H[Y]&&Gt(H[Y])},[H,Gt]),Re=Ze.map(Y=>H[Y]).filter(Boolean),al=()=>{Ne([])},Fe=()=>{Re[0]&&Gt(Re[0])},za=()=>{Re.forEach((Y,ye)=>{const He=Y.seed??Date.now();At(Y.url,`diffusion-${He}-${ye+1}.png`)})},Ta=async()=>{if(Re.length===0)return;const Y=Re.length;if(await L({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 Vy(Re);const He=new Set(Ze);w(pt=>pt.filter((ft,tt)=>!He.has(tt))),Ne([]),Re.some(pt=>pt.url===te)&&(W(null),de(null),ke(null))}catch(He){console.error("Failed to delete selected outputs:",He),X({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(Su,{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:h})]}),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:h})]}),c.jsxs("div",{className:"m3-text-field",children:[c.jsx("label",{className:"m3-text-field-label",children:"Base Image (Optional)"}),gt?c.jsxs("div",{style:{display:"flex",gap:"12px",alignItems:"center",padding:"12px",background:"var(--md-sys-color-surface-variant)",borderRadius:"var(--md-shape-corner-medium)",border:"1px solid var(--md-sys-color-outline-variant)"},children:[c.jsx("img",{src:gt,alt:"Base",style:{width:"64px",height:"64px",objectFit:"cover",borderRadius:"8px",flexShrink:0}}),c.jsxs("div",{style:{flex:1,minWidth:0},children:[c.jsx("div",{style:{fontWeight:600,fontSize:"0.85rem"},children:"Base image ready"}),c.jsx("div",{style:{fontSize:"0.75rem",color:"var(--md-sys-color-outline)"},children:"The AI will redraw this image guided by your prompt."})]}),c.jsxs("button",{type:"button",className:"m3-btn m3-btn-error",style:{height:"34px",flexShrink:0},onClick:ie,disabled:h,children:[c.jsx(rn,{size:14}),c.jsx("span",{children:"Remove"})]})]}):c.jsxs("label",{className:"import-box",style:{margin:0,padding:"16px",cursor:h?"not-allowed":"pointer"},children:[c.jsx("input",{type:"file",accept:"image/png,image/jpeg,image/webp",style:{display:"none"},onChange:Z,disabled:h}),c.jsx(iy,{className:"import-icon"}),c.jsx("span",{style:{fontWeight:600},children:"Upload a base image"}),c.jsx("span",{style:{fontSize:"0.75rem",color:"var(--md-sys-color-outline)",textAlign:"center"},children:"Optional. Generate a new image based on one of your own."})]}),gt&&c.jsxs("div",{style:{marginTop:"12px"},children:[c.jsxs("div",{style:{display:"flex",justifyContent:"space-between",fontSize:"0.8rem",marginBottom:"4px"},children:[c.jsx("span",{children:"Transformation strength"}),c.jsx("span",{children:x.denoisingStrength.toFixed(2)})]}),c.jsx("input",{type:"range",min:"0.1",max:"1",step:"0.05",value:x.denoisingStrength,onChange:Y=>N(ye=>({...ye,denoisingStrength:parseFloat(Y.target.value)})),disabled:h,style:{width:"100%"}}),c.jsx("div",{style:{fontSize:"0.72rem",color:"var(--md-sys-color-outline)",marginTop:"2px"},children:"Lower = closer to your image; higher = more creative freedom. 0.7 is a good start."})]})]}),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:()=>fe("constraints"),children:[c.jsx(Ks,{size:14}),c.jsxs("span",{children:["Resolution: ",x.width,"x",x.height]})]}),c.jsxs("div",{className:"status-chip",onClick:()=>fe("constraints"),children:[c.jsx(aa,{size:14}),c.jsxs("span",{children:["Steps: ",x.steps]})]}),c.jsxs("div",{className:"status-chip",onClick:()=>fe("constraints"),children:[c.jsx(Su,{size:14}),c.jsxs("span",{children:["Sampler: ",x.sampler]})]}),c.jsx("div",{className:"status-chip",onClick:()=>fe("constraints"),children:c.jsxs("span",{children:["Seed: ",x.seed===-1?"Random":x.seed]})})]})]}),c.jsxs("button",{className:"m3-btn m3-btn-filled",style:{height:"48px",marginTop:"8px"},onClick:D,disabled:h||!f.trim()||!G,children:[c.jsx(Su,{size:18}),c.jsx("span",{children:G?gt?"Generate from Base Image":"Generate Local Image":"Select Model to Generate"})]})]})]})}),c.jsxs("div",{className:"m3-card output-panel",children:[c.jsx("div",{className:"output-image-container",children:h||J||ce?c.jsx("div",{className:"progress-overlay",children:ce?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."})]}):J?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:ee?"Decoding Latents...":"Generating Locally..."}),_&&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:"})," ",Je," / ",x.steps," (",Math.max(0,x.steps-Je)," left)"]}),c.jsxs("div",{style:{textAlign:"right"},children:[c.jsx("strong",{children:"Elapsed:"})," ",ve,"s",$e&&` (${$e==="decoding"?"decoding":$e})`]})]}),c.jsx("div",{className:"progress-bar-container",style:{margin:"4px 0 10px 0"},children:c.jsx("div",{className:"progress-bar-fill",style:{width:`${U}%`,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: ",U,"%"]}),c.jsx("span",{children:"•"}),c.jsxs("span",{children:["Est. remaining: ",yt,"s"]})]}),c.jsx("button",{className:"m3-btn m3-btn-error",style:{marginTop:"16px",height:"36px",padding:"0 24px"},onClick:R,children:"Stop Generating"})]})}):te?c.jsx("img",{src:te,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(Su,{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."]})]})}),te&&!h&&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: ",Oe]}),Ee&&c.jsxs("span",{children:["Inference Time: ",Ee.toFixed(1),"s"]})]}),c.jsxs("div",{className:"image-actions",children:[c.jsxs("button",{className:"m3-btn m3-btn-tonal",onClick:F,children:[Ae?c.jsx(ks,{size:16}):c.jsx(J0,{size:16}),c.jsx("span",{children:Ae?"Copied":"Copy"})]}),c.jsxs("button",{className:"m3-btn m3-btn-outlined",onClick:ae,children:[c.jsx(nm,{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"}),Re.length>0&&c.jsxs("div",{className:"gallery-selection-actions",children:[c.jsxs("span",{className:"gallery-selection-count",children:[Re.length," selected"]}),c.jsxs("button",{className:"m3-btn m3-btn-tonal",onClick:Fe,children:[c.jsx(ks,{size:14}),c.jsx("span",{children:"Use"})]}),c.jsxs("button",{className:"m3-btn m3-btn-outlined",onClick:za,children:[c.jsx(nm,{size:14}),c.jsx("span",{children:"Download"})]}),c.jsxs("button",{className:"m3-btn m3-btn-error",onClick:Ta,children:[c.jsx(rn,{size:14}),c.jsx("span",{children:"Delete"})]}),c.jsx("button",{className:"m3-btn m3-btn-outlined",onClick:al,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,ye)=>c.jsx(tg,{img:Y,idx:ye,isSelected:Ze.includes(ye),onClick:dl},Y.image||ye))})]})]})]})}const ag=O.memo(lg),ng=[{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"}]},{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 ig({activeModel:f,setActiveModel:b,serverRunning:E,setServerRunning:r,constraints:x,showAlert:N=async({message:H})=>window.alert(H),showConfirm:G=async({message:H})=>window.confirm(H)}){const[H,w]=O.useState([]),[h,A]=O.useState(null),[U,V]=O.useState(0),[fe,X]=O.useState(""),[L,te]=O.useState(null),[W,Oe]=O.useState(null),[de,Ee]=O.useState(null),[ke,Ae]=O.useState({filename:"",speed:"0.0",eta:0,status:""}),[P,ve]=O.useState(""),[Ke,yt]=O.useState(null),[me,Je]=O.useState(!1),[st,$e]=O.useState({progress:0,phase:""}),[Xe,_]=O.useState(null),[C,J]=O.useState({backendMode:"",backendBinary:"",backendDevice:""}),he=H.map(D=>ui(D).filename),ce=L!==null||me;O.useEffect(()=>{B(),d()},[]),O.useEffect(()=>{if(!E&&!L){J({backendMode:"",backendBinary:"",backendDevice:""});return}let D=!1;const R=async()=>{try{const ae=await Cl();if(D)return;J({backendMode:ae.settings?.backendMode||ae.loading?.backendMode||"",backendBinary:ae.settings?.backendBinary||ae.loading?.backendBinary||"",backendDevice:ae.settings?.backendDevice||ae.loading?.device||""})}catch{}};R();const F=setInterval(R,2e3);return()=>{D=!0,clearInterval(F)}},[E,L]);const d=async()=>{try{const D=await cm();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 F=await cm();F.active?(V(F.progress===-1?0:F.progress),X(`${F.speed} • ETA ${F.eta}s`)):(clearInterval(R),A(null),F.error?String(F.error).toLowerCase().includes("cancelled")||N({title:"Download Failed",message:F.error,danger:!0}):B())}catch(F){console.error("Polling error:",F)}},1e3)},B=async()=>{try{const D=await ky();w(D.map(ui).filter(R=>R.filename))}catch(D){console.error(D)}},q=async(D,R)=>{if(h||he.includes(R)&&!await G({title:"Overwrite Model?",message:`"${R}" is already downloaded. Do you want to download and overwrite it?`,confirmLabel:"Overwrite"}))return;const F=typeof window<"u"&&window.__TAURI_INTERNALS__!==void 0,ae=typeof window<"u"&&(window.location.hostname==="localhost"||window.location.hostname==="127.0.0.1");if(!F&&!ae){N({title:"Server Required",message:"Model download requires the local image generator server.",danger:!0});return}try{const At=await Iy(D);At.ok?j(R):N({title:"Download Failed",message:At.error||"Unknown error",danger:!0})}catch(At){N({title:"Download Error",message:At.message,danger:!0})}},K=async D=>{if(D.preventDefault(),!P.trim())return;let R="model.gguf";try{const F=new URL(P.trim());if(F.protocol!=="http:"&&F.protocol!=="https:")throw new Error("URL protocol must be http or https");if(R=F.pathname.split("/").pop()||"",!R)throw new Error("Could not extract filename from URL");const ae=R.toLowerCase();if(!ae.endsWith(".gguf")&&!ae.endsWith(".safetensors")&&!ae.endsWith(".ckpt"))throw new Error("URL must point to a .gguf, .safetensors, or .ckpt weights file")}catch(F){N({title:"Invalid URL",message:F.message,danger:!0});return}await q(P.trim(),R),ve("")},ee=D=>{q(D.url,D.filename)},se=async()=>{await Py(),A(null),V(0),X(""),await B()},Ze=async D=>{if(f&&f!==D&&E){_(D);return}await Ne(D)},Ne=async D=>{const R=typeof window<"u"&&window.__TAURI_INTERNALS__!==void 0,F=typeof window<"u"&&(window.location.hostname==="localhost"||window.location.hostname==="127.0.0.1"),At=(await Cl())?.port||8080;if(!R&&!F){const Gt=await hm(),dl=`.\\backend\\win\\vulkan\\sd-vulkan.exe --listen-port ${At} --model .\\models\\${D} --threads 8`;Gt?await G({title:"Web Browser Mode",message:`To load "${D}" on the active GPU server, restart your terminal backend with: - -${dl} - -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 ${At}. - -To run locally, start: - -${dl} - -Proceed in Simulation Mode instead?`,confirmLabel:"Proceed"})&&(b(D),r(!1));return}te(D),Oe({progress:0,phase:"Starting backend...",speed:"",current:0,total:0,model:D,backendMode:"",backendBinary:"",device:""});try{const Gt=await Vs(D,x);console.log(Gt);let dl=!1,Re=null;for(let al=0;al<240;al++){const Fe=await Cl();if(Fe.loading&&Oe({progress:Fe.loading.progress||0,phase:Fe.loading.phase||"Loading model...",speed:Fe.loading.speed||"",current:Fe.loading.current||0,total:Fe.loading.total||0,model:Fe.loading.model||D,backendMode:Fe.loading.backendMode||Fe.settings?.backendMode||"",backendBinary:Fe.loading.backendBinary||Fe.settings?.backendBinary||"",device:Fe.loading.device||Fe.settings?.backendDevice||""}),Fe.ready){dl=!0;break}if(Fe.error){Re=Fe.error;break}if(!Fe.running&&al>3){Re="The backend process terminated immediately on startup.";break}await new Promise(za=>setTimeout(za,500))}if(dl)Oe(al=>({...al||{},progress:100,phase:"Model ready",speed:"",current:al?.current||0,total:al?.total||0,model:D})),b(D),r(!0);else throw new Error(Re||`Model server failed to respond on port ${At}.`)}catch(Gt){console.error("Failed to load model:",Gt),N({title:"Model Load Failed",message:Gt.message||String(Gt),danger:!0})}finally{setTimeout(()=>Oe(null),800),te(null)}},gt=async()=>{const D=Xe;_(null),await Et(),D&&await Ne(D)},Et=async()=>{if(me)return;Je(!0),$e({progress:10,phase:"Stopping backend process..."});const D=setInterval(async()=>{try{const R=await Cl();R.unloading?.active?$e({progress:R.unloading.progress||50,phase:R.unloading.phase||"Unloading model..."}):$e(F=>({progress:Math.min(95,F.progress+10),phase:F.phase||"Unloading model..."}))}catch{}},300);try{await Js(),$e({progress:100,phase:"Model unloaded"}),b(null),_(null),r(!1)}catch(R){console.error(R),N({title:"Unload Failed",message:R.message||String(R),danger:!0})}finally{clearInterval(D),setTimeout(()=>{Je(!1),$e({progress:0,phase:""})},500)}},We=async D=>{if(await G({title:"Delete Model?",message:`Delete "${D}" from your drive?`,confirmLabel:"Delete",danger:!0}))try{await Wy(D),await B(),f===D&&await Et()}catch(R){console.error("Failed to delete model:",R),N({title:"Delete Failed",message:R.message||String(R),danger:!0})}},Ht=async(D,R)=>{const F=new AbortController;yt(F),Ee(0),Ae({filename:R,speed:"0.0",eta:0,status:"Initiating file copy..."});try{await Jy(D,ae=>{Ee(Math.round(ae.progress)),Ae({filename:ae.filename,speed:ae.speed_mb_s.toFixed(1),eta:Math.round(ae.eta_secs),status:ae.status})},F.signal),await B()}catch(ae){console.error("Import failed:",ae),ae.name!=="AbortError"&&N({title:"Import Failed",message:ae.message||String(ae),danger:!0})}finally{Ee(null),yt(null)}},Tt=()=>{Ke&&Ke.abort()},Z=D=>{const R=D.target.files[0];R&&Ht(R,R.name),D.target.value=""},ie=!!h;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(xu,{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:Et,disabled:me||L!==null,children:[me?c.jsx(aa,{className:"progress-spinner",size:16}):c.jsx(rn,{size:16}),c.jsx("span",{children:me?"Unloading":"Unload Server"})]})]})}),me&&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:st.phase||"Unloading model..."}),c.jsxs("span",{children:[Math.round(st.progress),"%"]})]}),c.jsx("div",{className:"model-progress-bar",children:c.jsx("div",{className:"model-progress-fill",style:{width:`${Math.min(100,Math.max(0,st.progress))}%`,transition:"width 0.25s ease"}})})]})]}),W&&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: ",W.model||L]}),(W.backendMode||W.backendBinary||W.device)&&c.jsxs("div",{style:{display:"flex",flexWrap:"wrap",gap:"8px",marginBottom:"10px"},children:[W.backendMode&&c.jsxs("span",{className:"status-chip",style:{cursor:"default"},children:[c.jsx(xu,{size:14}),c.jsxs("span",{children:["Loading on ",W.backendMode]})]}),W.device&&c.jsx("span",{className:"status-chip",style:{cursor:"default"},children:c.jsx("span",{children:W.device})}),W.backendBinary&&c.jsx("span",{className:"status-chip",style:{cursor:"default"},children:c.jsx("span",{children:W.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:[W.phase,W.speed?` (${W.speed})`:""]}),c.jsx("span",{children:W.total>0?`Loaded ${W.current} / ${W.total} tensors`:`${Math.round(W.progress)}%`})]}),c.jsx("div",{className:"model-progress-bar",children:c.jsx("div",{className:"model-progress-fill",style:{width:`${Math.min(100,Math.max(0,W.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(Xs,{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,F=f===R;return c.jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center",padding:"12px 16px",background:F?"var(--md-sys-color-primary-container)":"var(--md-sys-color-surface-variant)",color:F?"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||ii(D.sizeBytes)]})]}),c.jsx("div",{style:{display:"flex",gap:"8px"},children:F?c.jsxs("button",{className:"m3-btn m3-btn-error",style:{height:"36px",padding:"0 16px"},onClick:Et,disabled:me,children:[me?c.jsx(aa,{className:"progress-spinner",size:14}):c.jsx(rn,{size:14}),c.jsx("span",{children:me?"Unloading":"Unload"})]}):c.jsxs(c.Fragment,{children:[c.jsxs("button",{className:"m3-btn m3-btn-filled",style:{height:"36px",padding:"0 16px"},onClick:()=>Ze(R),disabled:ce,children:[L===R?c.jsx(aa,{className:"progress-spinner",size:14}):c.jsx(Xs,{size:14}),c.jsx("span",{children:L===R?"Loading":"Load"})]}),c.jsx("button",{className:"m3-btn m3-btn-error",style:{height:"36px",width:"36px",padding:0,minWidth:"36px"},onClick:()=>We(R),disabled:ce,title:"Delete from models folder",children:c.jsx(rn,{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(ry,{size:20,style:{color:"var(--md-sys-color-primary)"}}),"Model Library"]})}),c.jsx("div",{style:{display:"flex",flexDirection:"column",gap:"16px"},children:ng.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 F=he.includes(R.filename),ae=h===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}),ae&&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:U>0?`${U}%`:"Preparing"})]}),c.jsx("div",{className:"model-progress-bar",children:c.jsx("div",{className:"model-progress-fill",style:{width:`${Math.min(100,Math.max(0,U))}%`,transition:"width 0.2s ease"}})}),fe&&c.jsx("div",{style:{fontSize:"0.7rem",color:"var(--md-sys-color-outline)",marginTop:"4px"},children:fe})]}),c.jsxs("button",{className:F?"m3-btn m3-btn-tonal":"m3-btn m3-btn-filled",style:{height:"36px",marginTop:"auto"},onClick:()=>ee(R),disabled:F||h!==null,children:[F?c.jsx(xu,{size:14}):ae?c.jsx(aa,{className:"progress-spinner",size:14}):c.jsx(am,{size:14}),c.jsx("span",{children:F?"Downloaded":ae?"Downloading":"Download"})]}),c.jsx("a",{href:R.url,target:"_blank",rel:"noreferrer",style:{alignSelf:"center",color:"var(--md-sys-color-primary)",fontSize:"0.75rem",fontWeight:600,lineHeight:1.2,textDecoration:"none"},children:"Save to Downloads folder"})]},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(im,{size:20,style:{color:"var(--md-sys-color-primary)"}}),"Local Model Import"]})}),de!==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: ",ke.filename]}),c.jsxs("button",{className:"m3-btn m3-btn-error",style:{height:"34px",padding:"0 14px"},onClick:Tt,children:[c.jsx(Qs,{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:[ke.status," (",ke.speed," MB/s)"]}),c.jsxs("span",{children:[de,"% (",ke.eta,"s remaining)"]})]}),c.jsx("div",{className:"model-progress-bar",children:c.jsx("div",{className:"model-progress-fill",style:{width:`${de}%`,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:Z,disabled:de!==null}),c.jsx(im,{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(am,{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."}),ie?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:h,children:h}),c.jsxs("span",{children:[U,"%"]})]}),c.jsx("div",{className:"model-progress-bar",style:{margin:"4px 0"},children:c.jsx("div",{className:"model-progress-fill",style:{width:`${U}%`,transition:"width 0.15s ease"}})}),c.jsx("div",{style:{fontSize:"0.7rem",color:"var(--md-sys-color-outline)",marginTop:"2px"},children:fe}),c.jsxs("button",{className:"m3-btn m3-btn-error",style:{height:"34px",padding:"0 14px",marginTop:"10px"},onClick:se,children:[c.jsx(Qs,{size:14}),c.jsx("span",{children:"Stop Download"})]})]}):c.jsxs("form",{onSubmit:K,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:P,onChange:D=>ve(D.target.value),disabled:h!==null}),c.jsx("button",{type:"submit",className:"m3-btn m3-btn-filled",style:{height:"40px"},disabled:h!==null,children:"Download"})]})]})]}),Xe&&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(My,{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 "',Xe,'".']}),c.jsxs("div",{style:{display:"flex",justifyContent:"flex-end",gap:"10px"},children:[c.jsx("button",{className:"m3-btn m3-btn-outlined",onClick:()=>_(null),disabled:me,children:"Cancel"}),c.jsxs("button",{className:"m3-btn m3-btn-error",onClick:Et,disabled:me,children:[c.jsx(rn,{size:14}),c.jsx("span",{children:"Unload Only"})]}),c.jsxs("button",{className:"m3-btn m3-btn-filled",onClick:gt,disabled:me,children:[me?c.jsx(aa,{className:"progress-spinner",size:14}):c.jsx(aa,{size:14}),c.jsx("span",{children:"Unload and Load"})]})]})]})})]})}const ug=O.memo(ig),sm=[{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"}],cg=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 sg({constraints:f,setConstraints:b,activeModel:E,specs:r,backendOptions:x}){const N=E?cg(E):!1,G=x?.options?.length?x.options:[{id:"cpu",label:"CPU",available:!0}],H=(A,U)=>{b(V=>({...V,[A]:U}))},w=(A,U)=>{const V=U==="sdxl"&&!N,fe=sm.find(X=>X.id===A);if(fe){let X=V?fe.sdxl_width:fe.width,L=V?fe.sdxl_height:fe.height;N&&(X>L?(L=Math.round(L*512/X),X=512):(X=Math.round(X*512/L),L=512),X=Math.round(X/64)*64,L=Math.round(L/64)*64),H("width",X),H("height",L)}},h=A=>{b(U=>({...U,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(fy,{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:sm.map(A=>{const U=Math.abs(f.width/f.height-A.width/A.height)<.1;return c.jsxs("button",{className:`m3-btn m3-btn-outlined aspect-ratio-btn ${U?"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:()=>w(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(Ks,{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(rm,{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:()=>h(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."]}),x?.unavailable?.length>0&&c.jsx("div",{style:{marginTop:"8px",display:"flex",flexDirection:"column",gap:"4px"},children:x.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 fg=O.memo(sg);function og(){const f=O.useRef(null),[b,E]=O.useState(null),r=O.useCallback(Z=>{const ie=f.current;f.current=null,E(null),ie&&ie(Z)},[]),x=O.useCallback(({title:Z="Confirm Action",message:ie,confirmLabel:D="OK",cancelLabel:R="Cancel",danger:F=!1})=>new Promise(ae=>{f.current=ae,E({type:"confirm",title:Z,message:ie,confirmLabel:D,cancelLabel:R,danger:F})}),[]),N=O.useCallback(({title:Z="Notice",message:ie,confirmLabel:D="OK",danger:R=!1})=>new Promise(F=>{f.current=F,E({type:"alert",title:Z,message:ie,confirmLabel:D,danger:R})}),[]),[G,H]=O.useState(()=>{const Z=localStorage.getItem("theme");return Z||(window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light")});O.useEffect(()=>{document.documentElement.setAttribute("data-theme",G),localStorage.setItem("theme",G)},[G]);const[w,h]=O.useState("generator"),[A,U]=O.useState(""),[V,fe]=O.useState(""),[X,L]=O.useState(null),[te,W]=O.useState(!1),[Oe,de]=O.useState(!1),[Ee,ke]=O.useState({options:[{id:"cpu",label:"CPU",available:!0}],cudaAvailable:!1,vulkanAvailable:!1,defaultBackendType:"cpu"}),[Ae,P]=O.useState(null),[ve,Ke]=O.useState([]),[yt,me]=O.useState(!1),[Je,st]=O.useState(!1),[$e,Xe]=O.useState([]),[_,C]=O.useState(!1),[J,he]=O.useState(0),[ce,d]=O.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,B]=O.useState({cpu_usage:0,ram_used_gb:0,ram_total_gb:0,gpu_name:"Detecting...",vram_used_gb:0,vram_total_gb:0}),[q,K]=O.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"});O.useEffect(()=>{async function Z(){try{const ie=await qy(),D=await Yy();ke(D),d(ie),K(R=>({...R,threads:ie.cpu_cores_physical||4,backendType:R.backendType==="auto"?D.defaultBackendType||"cpu":R.backendType,useGpu:(R.backendType==="auto"?D.defaultBackendType:R.backendType)!=="cpu"}))}catch(ie){console.error("Error fetching hardware specs:",ie)}}Z()},[]);const ee=O.useCallback(async()=>{me(!0);try{const[Z,ie]=await Promise.all([By(),Hy().catch(()=>[])]);P(Z),Ke(ie)}finally{me(!1)}},[]);O.useEffect(()=>{ee()},[ee]);const se=O.useCallback(async()=>{try{const Z=await Ry();await navigator.clipboard.writeText(JSON.stringify(Z,null,2)),st(!0),setTimeout(()=>st(!1),1800)}catch(Z){N({title:"Diagnostics Failed",message:Z.message||String(Z),danger:!0})}},[N]),Ze=O.useCallback(async()=>{if(ve.length===0)return;const Z=ve.reduce((D,R)=>D+Number(R.sizeBytes||0),0);if(await x({title:"Clean Safe Files?",message:`Delete ${ve.length} temporary/cache item${ve.length===1?"":"s"} and free about ${ii(Z)}? - -Models and generated outputs are not included.`,confirmLabel:"Clean",danger:!0})){me(!0);try{await Gy(ve.map(D=>D.id)),await ee()}catch(D){N({title:"Cleanup Failed",message:D.message||String(D),danger:!0})}finally{me(!1)}}},[ve,ee,N,x]);O.useEffect(()=>{async function Z(){const ie=await Xy();Xe(ie)}Z()},[]),O.useEffect(()=>{X?localStorage.setItem("active-model",X):localStorage.removeItem("active-model")},[X]),O.useEffect(()=>{let Z=null;async function ie(){const D=await Cl();if(!!D.ready){Z&&clearInterval(Z);const F=localStorage.getItem("active-model");if(F)L(F),W(!0);else{try{if(D&&D.settings&&D.settings.model){const ae=D.settings.model.split(/[\\/]/).pop();L(ae)}}catch{}W(!0)}}else if(!(typeof window<"u"&&window.__TAURI_INTERNALS__!==void 0)){const ae=localStorage.getItem("active-model");ae&&(L(ae),W(!1))}}return ie(),Z=setInterval(ie,2e3),()=>{Z&&clearInterval(Z)}},[]),O.useEffect(()=>{async function Z(){try{const D=await Ly();B(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{}}Z();const ie=setInterval(Z,1500);return()=>clearInterval(ie)},[]),O.useEffect(()=>{if(X){const Z=X.toLowerCase();Z.includes("flux")||Z.includes("schnell")?K(ie=>({...ie,steps:4,cfgScale:1,width:1024,height:1024})):Z.includes("lightning")||Z.includes("turbo")?K(ie=>({...ie,steps:4,cfgScale:1.5,width:1024,height:1024})):Z.includes("sd15")?K(ie=>({...ie,steps:25,cfgScale:7,width:512,height:512})):Z.includes("sd35")?K(ie=>({...ie,steps:20,cfgScale:4.5,width:1024,height:1024})):K(ie=>({...ie,steps:20,cfgScale:7,width:512,height:512}))}},[X]);const Ne=O.useMemo(()=>{switch(w){case"generator":return c.jsx(ag,{prompt:A,setPrompt:U,negativePrompt:V,setNegativePrompt:fe,constraints:q,setConstraints:K,activeModel:X,generatedImages:$e,setGeneratedImages:Xe,isGenerating:_,setIsGenerating:C,generationProgress:J,setGenerationProgress:he,setActiveTab:h,showAlert:N,showConfirm:x});case"models":return c.jsx(ug,{activeModel:X,setActiveModel:L,serverRunning:te,setServerRunning:W,constraints:q,showAlert:N,showConfirm:x});case"constraints":return c.jsx(fg,{constraints:q,setConstraints:K,activeModel:X,specs:ce,backendOptions:Ee});default:return null}},[w,A,V,q,X,$e,_,J,te,ce,Ee,N,x]),gt=O.useMemo(()=>c.jsx(Ny,{activeTab:w,setActiveTab:h,specs:ce}),[w,ce]),Et=O.useCallback(async()=>{if(!(!te||Oe)){de(!0);try{await Js(),W(!1),L(null)}catch(Z){console.error("Failed to stop server:",Z),N({title:"Stop Server Failed",message:Z.message||String(Z),danger:!0})}finally{de(!1)}}},[te,Oe,N]),We=[...Ae?.stale?["Restart Local AI Image Generator so the local server loads the latest API."]:[],...Ae?.issues||[]],Ht=ve.reduce((Z,ie)=>Z+Number(ie.sizeBytes||0),0),Tt=!!(Ae&&(We.length>0||ve.length>0));return c.jsxs("div",{className:"app-container",children:[gt,c.jsxs("div",{className:"main-content",children:[c.jsx(Dy,{telemetry:j,serverRunning:te,activeModel:X,onStopServer:Et,isStoppingServer:Oe,theme:G,setTheme:H}),Tt&&c.jsxs("div",{className:`m3-card readiness-card ${Ae?.stale||We.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:Ae?.stale?"Restart Required":We.length>0?"System Readiness":"Safe Cleanup Available"}),c.jsx("p",{className:"m3-card-subtitle",style:{margin:0},children:Ae?.stale?`Running server build: ${Ae.build||"unknown"}`:We.length>0?"Local AI Image Generator found setup items that may need attention.":`${ve.length} temporary item${ve.length===1?"":"s"} can be cleaned (${ii(Ht)}).`})]}),c.jsxs("div",{className:"readiness-actions",children:[c.jsx("button",{className:"m3-btn m3-btn-outlined",onClick:ee,disabled:yt,children:yt?"Checking":"Refresh"}),c.jsx("button",{className:"m3-btn m3-btn-tonal",onClick:se,children:Je?"Copied":"Copy Diagnostics"}),ve.length>0&&c.jsxs("button",{className:"m3-btn m3-btn-error",onClick:Ze,disabled:yt,children:["Clean ",ii(Ht)]})]})]}),We.length>0&&c.jsx("div",{className:"readiness-issues",children:We.slice(0,4).map(Z=>c.jsx("span",{children:Z},Z))}),ve.length>0&&c.jsx("div",{className:"readiness-cleanup-list",children:ve.slice(0,3).map(Z=>c.jsxs("span",{title:Z.path,children:[Z.name," · ",Z.size," · ",Z.reason]},Z.id))})]}),Ne]}),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(og,{})}));export{ja as i,rg as t}; diff --git a/app/dist/index.html b/app/dist/index.html index 26edf65..eee907d 100644 --- a/app/dist/index.html +++ b/app/dist/index.html @@ -1,18 +1,18 @@ - - - - - - - - - - Local AI Image Generator - + + + + + + + + + + Local AI Image Generator + - - - -
- - + + + +
+ + diff --git a/app/frontend/package-lock.json b/app/frontend/package-lock.json index 143e984..6b97d45 100644 --- a/app/frontend/package-lock.json +++ b/app/frontend/package-lock.json @@ -802,9 +802,9 @@ "license": "MIT" }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.61.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.61.0.tgz", - "integrity": "sha512-dnxczajOqt0gesZlN5pGQ1s1imQVrsmCw5G2Ci4oM+0WvNz3pyRnlWrT7McoZIb8VlFwCawdmbWRmxRn7HI+VQ==", + "version": "4.61.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.61.1.tgz", + "integrity": "sha512-JnBB8MdXj45cajvTuO5FmPlvFVJRQgvrz1uSEl3NwqFnReAPGwb8EanbGi4z2nRaqLzjJSv5/JmycoTKlRZxHA==", "cpu": [ "arm" ], @@ -816,9 +816,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.61.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.61.0.tgz", - "integrity": "sha512-Bp3JpGP00Vu3f238ivRrjf7z3xSzVPXqCmaJYA9t2c+c8vKYvOzmXF7LkkeUalTEGd6cZcSWe+PFIP3Vy48fRg==", + "version": "4.61.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.61.1.tgz", + "integrity": "sha512-Jx2g7iSjw4AOT0HDPHM9RV3GNjRXwybWtSFZiZAYUTjUwjVrYIwq3kBf+LnhqJlzXFAqTAh2F7IGI+O568exPw==", "cpu": [ "arm64" ], @@ -830,9 +830,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.61.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.61.0.tgz", - "integrity": "sha512-zaYIpr670mUmmZ1tVzUFplbQbG7h3Gugx3L5FoqhsC2m/YnLlR1a7zVLmXNPy+iY1tFPEbNG+HHBXZGyId0G5w==", + "version": "4.61.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.61.1.tgz", + "integrity": "sha512-0F1L/Z3Eqv8mT2n3dCpeO8GcTvHvVqkP5/t6DMsn0KzhYVcg+s7Ncl5DS8qjKYEeio6Az0Gt6nyBORay5qIlCA==", "cpu": [ "arm64" ], @@ -844,9 +844,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.61.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.61.0.tgz", - "integrity": "sha512-+P49fvkv2dSoeevUW+lgZ/I2JHSsJCK1Lyjj7Cu6E4UHG4tS9XIefzIjo5qhgELjAclnen1rLzK2PMKJdo+Dyg==", + "version": "4.61.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.61.1.tgz", + "integrity": "sha512-qLttcH871ujY4YcVfUSShhOw+CsoTatYz8gRbHO7Bb92QH059/P0y5do1KMs41fY0BpD2x4AJH/gID0zFiqVKQ==", "cpu": [ "x64" ], @@ -858,9 +858,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.61.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.61.0.tgz", - "integrity": "sha512-l3FAAOyKJXH2ea6KNFN+MMgC/rnE94YGLXs2ehYqDcCoHt1DpvgWX75BhUJxN38XojP7Ul+4H8PRn7EdyqSDrw==", + "version": "4.61.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.61.1.tgz", + "integrity": "sha512-fUI4RapGE0Oh3mb8mgfvC1O2nU1RpDZUKnDQm3xB1Ipg7C2wTs5Kstz7G2uWK99a8S2yTMq8/P4uycwNa0nJyw==", "cpu": [ "arm64" ], @@ -872,9 +872,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.61.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.61.0.tgz", - "integrity": "sha512-VokPN3TSctKj65cyCNPaUh4vMFA8awxOot/0sp+4J7ZlNRKQEhXhawqPwajoi8H5ZFt61i0ugZJuTKXBjGJ17Q==", + "version": "4.61.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.61.1.tgz", + "integrity": "sha512-H5YrdvJaDtI/U9/emrD4b++xkvp3y/JvOe4rizHbxvkyMfRS/CiRYdji+Pl8D0brEaNFWUh1drQxgAGIl6Xudw==", "cpu": [ "x64" ], @@ -886,9 +886,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.61.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.61.0.tgz", - "integrity": "sha512-DxH0P3wxm+Yzs/p3zrk9dw1rURu8p0Nv5+MRK/L7OtnLNg5rLZraSBFZ8iUXOd9f2BlhJyEpIZUH/emjq4UJ4g==", + "version": "4.61.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.61.1.tgz", + "integrity": "sha512-Q8CBCCQtDFrYtXoeUXSrnFXKOnyUhx6bz+SkL6A0E7V8kAiCJ5pamq1WtbfpVGhR5TSpXY6ak3avmDc5fHTyJA==", "cpu": [ "arm" ], @@ -900,9 +900,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.61.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.61.0.tgz", - "integrity": "sha512-T6ZvMNe84kAz6TBWHC7hGAoEtzP1LWYw/AqayGWEF6uISt3Abk/st06LqRD9THd7Xz3NxzurUpzAuEAUbZf+nw==", + "version": "4.61.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.61.1.tgz", + "integrity": "sha512-nwnhk1581l0FBVellGcVCAT0Oi06onEA3WB53sf01VO3I0UPBkMH9sXONYME2K0ovXcNayJfNtHfm6mpJElatQ==", "cpu": [ "arm" ], @@ -914,9 +914,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.61.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.61.0.tgz", - "integrity": "sha512-q/4hzvQkDs8b4jIBab1pnLiiM0ayTZsN2amBFPDzuyZxjEd4wDwx0UJFYM3cOZzSf5Kw8fnWSprJzIBMkcR44Q==", + "version": "4.61.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.61.1.tgz", + "integrity": "sha512-x5Xr49hwt3hdW75UOZm3395YwwzPyauktslv29KpWL/T+vVAzoT3azLcTWv0eMciBNrx+DYjH4paehHoLpPvpg==", "cpu": [ "arm64" ], @@ -928,9 +928,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.61.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.61.0.tgz", - "integrity": "sha512-vvYWX3akdEAY6km+9wAqFDnk6pQsbJKVnj7xawcvs/+fdlYBGp+U+Qq/lLfpIxYIZvZLHMAKD9HLdacSx/r3dw==", + "version": "4.61.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.61.1.tgz", + "integrity": "sha512-unMS3H73DpaoPyyEVPjGKleM/s0mkmsauTENpw4INQY8y4+IuLNjkueQ5QCtC0D3N38Y38yhAU8OoZ20S2Tm6w==", "cpu": [ "arm64" ], @@ -942,9 +942,9 @@ ] }, "node_modules/@rollup/rollup-linux-loong64-gnu": { - "version": "4.61.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.61.0.tgz", - "integrity": "sha512-DePa5cqOxDP/Zp0VOXpeWaGew5iIv5DXp9NYbzkX5PFQyWVX9184WCTh3hvr/7lhXo8ZVlbFLkz8+o/q1dU6gA==", + "version": "4.61.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.61.1.tgz", + "integrity": "sha512-zNZzGRnAhwjFEYmvphJRV5XaQGjs62cCmeYYHUT//NbvEnHauw+I85nGG+SiVg5ld4GX8D1IbKIX+ozITQnhMQ==", "cpu": [ "loong64" ], @@ -956,9 +956,9 @@ ] }, "node_modules/@rollup/rollup-linux-loong64-musl": { - "version": "4.61.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.61.0.tgz", - "integrity": "sha512-LV8aWMB8UChglMCEzs7RkN0GsH29RJaLLqwm9fCIjlqwxQTiWAqNcc7wjBkH31hV0PU/yVxGYvrYsgfea2qw6g==", + "version": "4.61.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.61.1.tgz", + "integrity": "sha512-LdpWGL8X209B2SIvWjqlc8VZgM6PKfontSerGepuldQmHYrAOtnMCXeJkxXGbC+PPZVOuu5czJo7fNV6aeW8rQ==", "cpu": [ "loong64" ], @@ -970,9 +970,9 @@ ] }, "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.61.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.61.0.tgz", - "integrity": "sha512-QoNSnwQtaeNu5grdBbsL0tt1uyl5EnS8DA8Mr3nluMXbhdQNyhN+G4tBax7VCdxLKj8YJ0/4OO9Ho84jMnJtKA==", + "version": "4.61.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.61.1.tgz", + "integrity": "sha512-EC5kTtNaNGOmbMGqar8dvJy6y/hg99GAwjfBz++pxZhQATXGcRjd6c5en5wcbru0vkRmiMGsQKdMJOOf6sza4g==", "cpu": [ "ppc64" ], @@ -984,9 +984,9 @@ ] }, "node_modules/@rollup/rollup-linux-ppc64-musl": { - "version": "4.61.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.61.0.tgz", - "integrity": "sha512-/zZp5MKapIIApE8trN8qLGNSiRN9TUoaUZ1cmVu4XnVdd5LQLOXTtyi+vtfUbNnT3iyjzpPqYeKXmvJ+gJGYWw==", + "version": "4.61.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.61.1.tgz", + "integrity": "sha512-8hiwp6D4acEcNK78I4rP0/XtS1sknWIAMJBPdR4l6zUtyTm5KiTDr5bXmWt4foY7nAN7AThDHgkLIEZOWKbzWw==", "cpu": [ "ppc64" ], @@ -998,9 +998,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.61.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.61.0.tgz", - "integrity": "sha512-RbrzcD3aJ1k3UbtMRRBNwojdVVyXjuVAFTfn/xPa6EEl6GE9Sm/akPgFTb9aAC9pMKGJ6CtWxaGrqWcabH+ySg==", + "version": "4.61.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.61.1.tgz", + "integrity": "sha512-10dh/h/BqA7DuMPWSxkR8uks18FRwnwOEqr5zOTEl+NOwP/OMzKX8OFR/Of9xxDA7D5qef1Nzar5WDD2kCCr1g==", "cpu": [ "riscv64" ], @@ -1012,9 +1012,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.61.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.61.0.tgz", - "integrity": "sha512-ZF+onDsBso8PJf1XaG9lB+O9RnBpKGnY6OrzC4CSHrtC1jb6jWLTKK4bRqdoCXHd22gyr2hiYmEAm8Wns/BOCw==", + "version": "4.61.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.61.1.tgz", + "integrity": "sha512-YKJ5lg35DP17gcAOggnihe+APw9HLyj1Xn7gsmGumBJAUDa6NGXNixJzmkWLhcK9TOuuyQjdamzvJefkO7qHZQ==", "cpu": [ "riscv64" ], @@ -1026,9 +1026,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.61.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.61.0.tgz", - "integrity": "sha512-Atk0aSIk5Zx2Wuh9dgRQgLP0Koc8hOeYpbWryMXyk8G8/HmPkwPPkMqIIDhrXHHYqfUzSJA/I7IWSBv8xSmRBA==", + "version": "4.61.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.61.1.tgz", + "integrity": "sha512-Mlil5G2Jj6a7B3LWGctg+XPL9vdXYuzCtNXfxOQ0nPjc2m6ueUktocPGH9bnAM0bNRKb/bAWTujUU7IJQdQA+g==", "cpu": [ "s390x" ], @@ -1040,9 +1040,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.61.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.61.0.tgz", - "integrity": "sha512-0uMOcf3eZ5K+K4cYHkdxShFMPlPXCOdfDFEFn9dNYAEEd2cVvmOfH7zFgRVoDgmtQ1m9k5q7qfrHzyMAubKYUA==", + "version": "4.61.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.61.1.tgz", + "integrity": "sha512-bVWIOIk6pV01p4CdUbPP7CJ/434z+OooYjDuFcR+44N35YvKUC66G8MGnvcWx5mWKW3g61J+t74l3Kj15Kwn2Q==", "cpu": [ "x64" ], @@ -1054,9 +1054,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.61.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.61.0.tgz", - "integrity": "sha512-mvFtE4A/t/7hRJ7X8Ozmu8FsIkAUat2nzl12pgU337BRmq87AQUJztwHz2Zv5/tjo9/C95E66CK03SI/ToEDJw==", + "version": "4.61.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.61.1.tgz", + "integrity": "sha512-qy5pBvZbqNFheBz61R1rzsezjm0J7O2oNGoWtGoY89SZYLUfxAJTBAqDChqAIdB4rCiIbi9nF7yZ83GnNiLwSw==", "cpu": [ "x64" ], @@ -1068,9 +1068,9 @@ ] }, "node_modules/@rollup/rollup-openbsd-x64": { - "version": "4.61.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.61.0.tgz", - "integrity": "sha512-z9b9+aTxvt8n2rNltMPvyaUfB8NJ+CVyOrGK/MdIKHx7B+lXmZpm/XbRsU7Rpf3fRqJ2uS6mBJiJveCtq8LHDg==", + "version": "4.61.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.61.1.tgz", + "integrity": "sha512-E83TXjI4zm0+5f2qO+UOudaCYIhYwpJ5jq6YCZNIZ+6CbfhKrkAGezeiASBL9ElxAxFsRS9ZhESv8mfnj6TKeg==", "cpu": [ "x64" ], @@ -1082,9 +1082,9 @@ ] }, "node_modules/@rollup/rollup-openharmony-arm64": { - "version": "4.61.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.61.0.tgz", - "integrity": "sha512-jXaXFqKMehsOc+g8R6oo33RRC6w07G9jDBxAE5eAKX7mOcCbZloYIPNhfG9Wl+P9O9IWHFO4OJgPi1Ml2qkt7w==", + "version": "4.61.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.61.1.tgz", + "integrity": "sha512-fbWnKqVkjrJN38vNe3ahkbk6iejS/3b0Nt7EEtPpE6RBacZcGXNKbzfHN3GUUlXOPghUg0j6XUGrtjX9z1sIvA==", "cpu": [ "arm64" ], @@ -1096,9 +1096,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.61.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.61.0.tgz", - "integrity": "sha512-OXNWVFocS2IA4+QplhTZZ2a+8hPZR7T8KuozsNmJKK8y7cp83StHvGksfHzPG3wczWTczyWHVQuqeiTUbjiyBg==", + "version": "4.61.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.61.1.tgz", + "integrity": "sha512-ArMl38iVAbk0New1ogihQNY6iphLi4ZaRsa037gUzv5yeKPY8TD3Dmy4x2RNC1VztU/uqm+G+/RwFrSka3Oy2g==", "cpu": [ "arm64" ], @@ -1110,9 +1110,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.61.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.61.0.tgz", - "integrity": "sha512-AlAbNtBO637LxSldqV43z0FfXoGfl2TW1DgAg/bs7aQswFbDewz2SJm3BUhiGfbOVtW571xbc9p+REdxhyN/Eg==", + "version": "4.61.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.61.1.tgz", + "integrity": "sha512-0mYtjHS9ucAbcATycCNK9IGBk/cCe/ma7EmSLGZdsxnOA8cjRIyU04wDpVAD9NiOfLUR9KTxdiO53uOkherqjQ==", "cpu": [ "ia32" ], @@ -1124,9 +1124,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-gnu": { - "version": "4.61.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.61.0.tgz", - "integrity": "sha512-QRSrQXyJ1M4tjNXdR0/G/IgV6lzfQQJYBjlWIEYkY2Xs86DRl/iEpQ4blMDjJxSl7n19eDKKXMg0AmuBVYy8pQ==", + "version": "4.61.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.61.1.tgz", + "integrity": "sha512-gK1iCEPfpoSG9wfBihXxvBMi8ZfcWffYkEsC/Eih+iFENTaewvNcrEQ69lIOWYO5pePHKLHHO7nq5AILGO/HQQ==", "cpu": [ "x64" ], @@ -1138,9 +1138,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.61.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.61.0.tgz", - "integrity": "sha512-tkuFxhvKO/HlGd0VsINF6vHSYH8AF8W0TcNxKDK6JZmrehngFj78pToc8iemtnvwilDjs2G/qSzYFhe9U8q+fw==", + "version": "4.61.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.61.1.tgz", + "integrity": "sha512-X+zaP2x+j4RXGfbp/seSoRHWnPxzApilDszisZxbYH5C/jTxFhCtDNdPGZb9lJyYPs24wGxruPF7Y+sIXt9Gzw==", "cpu": [ "x64" ], @@ -1461,9 +1461,9 @@ } }, "node_modules/baseline-browser-mapping": { - "version": "2.10.33", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.33.tgz", - "integrity": "sha512-bA6+tcSLpz2tIEdDXZPpPTIuxBcC4+w6SieaYyfigIa4h8GlFxbA17v22Vx3JUtuZQj9SgOsnbK+aTBzyDyEuw==", + "version": "2.10.34", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.34.tgz", + "integrity": "sha512-IMDedajPifLnHNY0X9n8hKxRTQ6/eTHwr5bDo04WnuqxyKw6LYtQywCuuqPZwhl3aBXMvQpJov42GLCwRRdQzw==", "dev": true, "license": "Apache-2.0", "bin": { @@ -1508,9 +1508,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001793", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001793.tgz", - "integrity": "sha512-iwSsYWaCOoh26cV8NwNRViHlrfUvYsHDfRVcbtmw0Kg6PJIZZXwMkj1442FYLBGkeUf1juAsU3DTfxW579mrPA==", + "version": "1.0.30001797", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001797.tgz", + "integrity": "sha512-l8xKG+gwAIExZGl9FrF7KUwuOmk6wbEPC9Xoy/RtnWv1XG0Q4LFlagaLpUv3Kiza3W/wm27zy0yWJEieYKAP6w==", "dev": true, "funding": [ { @@ -1554,9 +1554,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.366", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.366.tgz", - "integrity": "sha512-OlRuhb688YTCzzU3gXPLn6nGyd+F+53INE1qaKKlu6kETErE8FYsyDh0XqXEU+uBRn0MpCzz2vfNwORhkap8qg==", + "version": "1.5.369", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.369.tgz", + "integrity": "sha512-XM22K9FNaaCOvMMrBn1caIc8v0g6+pKt660ZbfQqUZvfil0hEzr8ZoiY7VcSLGM3L/x3rz5PqZrk+bKOOmVM9w==", "dev": true, "license": "ISC" }, @@ -1824,9 +1824,9 @@ } }, "node_modules/rollup": { - "version": "4.61.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.61.0.tgz", - "integrity": "sha512-T9mWdbWfQtp0B5lv/HX+wrhYsmXRlcWnXXmJbXqKJhlRaoS6KMhq0gpyzW4UJfclcxrEdLnTgjT2NjruLONu0g==", + "version": "4.61.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.61.1.tgz", + "integrity": "sha512-I4KW6iuRpuu2uHBLraZ1wNZe0DP7lnRha+VJ9tNaYVaVgKhW0aI3h4RYnoRPeql0flHm/Co55b7snEDcOfOJrA==", "dev": true, "license": "MIT", "dependencies": { @@ -1840,31 +1840,31 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.61.0", - "@rollup/rollup-android-arm64": "4.61.0", - "@rollup/rollup-darwin-arm64": "4.61.0", - "@rollup/rollup-darwin-x64": "4.61.0", - "@rollup/rollup-freebsd-arm64": "4.61.0", - "@rollup/rollup-freebsd-x64": "4.61.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.61.0", - "@rollup/rollup-linux-arm-musleabihf": "4.61.0", - "@rollup/rollup-linux-arm64-gnu": "4.61.0", - "@rollup/rollup-linux-arm64-musl": "4.61.0", - "@rollup/rollup-linux-loong64-gnu": "4.61.0", - "@rollup/rollup-linux-loong64-musl": "4.61.0", - "@rollup/rollup-linux-ppc64-gnu": "4.61.0", - "@rollup/rollup-linux-ppc64-musl": "4.61.0", - "@rollup/rollup-linux-riscv64-gnu": "4.61.0", - "@rollup/rollup-linux-riscv64-musl": "4.61.0", - "@rollup/rollup-linux-s390x-gnu": "4.61.0", - "@rollup/rollup-linux-x64-gnu": "4.61.0", - "@rollup/rollup-linux-x64-musl": "4.61.0", - "@rollup/rollup-openbsd-x64": "4.61.0", - "@rollup/rollup-openharmony-arm64": "4.61.0", - "@rollup/rollup-win32-arm64-msvc": "4.61.0", - "@rollup/rollup-win32-ia32-msvc": "4.61.0", - "@rollup/rollup-win32-x64-gnu": "4.61.0", - "@rollup/rollup-win32-x64-msvc": "4.61.0", + "@rollup/rollup-android-arm-eabi": "4.61.1", + "@rollup/rollup-android-arm64": "4.61.1", + "@rollup/rollup-darwin-arm64": "4.61.1", + "@rollup/rollup-darwin-x64": "4.61.1", + "@rollup/rollup-freebsd-arm64": "4.61.1", + "@rollup/rollup-freebsd-x64": "4.61.1", + "@rollup/rollup-linux-arm-gnueabihf": "4.61.1", + "@rollup/rollup-linux-arm-musleabihf": "4.61.1", + "@rollup/rollup-linux-arm64-gnu": "4.61.1", + "@rollup/rollup-linux-arm64-musl": "4.61.1", + "@rollup/rollup-linux-loong64-gnu": "4.61.1", + "@rollup/rollup-linux-loong64-musl": "4.61.1", + "@rollup/rollup-linux-ppc64-gnu": "4.61.1", + "@rollup/rollup-linux-ppc64-musl": "4.61.1", + "@rollup/rollup-linux-riscv64-gnu": "4.61.1", + "@rollup/rollup-linux-riscv64-musl": "4.61.1", + "@rollup/rollup-linux-s390x-gnu": "4.61.1", + "@rollup/rollup-linux-x64-gnu": "4.61.1", + "@rollup/rollup-linux-x64-musl": "4.61.1", + "@rollup/rollup-openbsd-x64": "4.61.1", + "@rollup/rollup-openharmony-arm64": "4.61.1", + "@rollup/rollup-win32-arm64-msvc": "4.61.1", + "@rollup/rollup-win32-ia32-msvc": "4.61.1", + "@rollup/rollup-win32-x64-gnu": "4.61.1", + "@rollup/rollup-win32-x64-msvc": "4.61.1", "fsevents": "~2.3.2" } }, diff --git a/app/frontend/src/services/api.js b/app/frontend/src/services/api.js index 08b762c..035982b 100644 --- a/app/frontend/src/services/api.js +++ b/app/frontend/src/services/api.js @@ -339,7 +339,8 @@ export async function listModelsFromDisk() { } // Generate image (T2I / I2I) -// Handles API calls to sd-server or mocks them if server is unreachable +// Handles API calls to sd-server. If the server is unreachable or returns an error, +// we surface that error to the UI instead of silently returning a fake placeholder. export async function generateImage(prompt, negativePrompt, constraints, activeModelName, inputImageBase64, onProgress, signal) { console.log("Initiating image generation:", { prompt, negativePrompt, constraints, activeModelName }); const startTime = Date.now(); @@ -360,173 +361,6 @@ export async function generateImage(prompt, negativePrompt, constraints, activeM denoising_strength: constraints.denoisingStrength || 0.7, }; - // Mock generation helper for offline/browser execution - const runMockGeneration = async () => { - // Simulate generation steps progress - const stepsCount = payload.steps; - for (let i = 1; i <= stepsCount; i++) { - if (signal && signal.aborted) { - throw new DOMException("The user aborted a request.", "AbortError"); - } - await new Promise(r => setTimeout(r, (3000 / stepsCount))); // 3 seconds total - if (onProgress) { - onProgress(Math.round((i / stepsCount) * 100)); - } - } - - const pLower = prompt.toLowerCase(); - const seedVal = Math.abs(payload.seed) || Math.floor(Math.random() * 1000); - - // Generate a beautiful, local vector SVG representing the requested subject, completely offline-compatible - const primaryBg = "#0F172A"; // dark premium background - let gradientStart = "#3B82F6"; - let gradientEnd = "#8B5CF6"; - let sceneShapes = ""; - let keywordLabel = "Abstract Generation"; - - if (pLower.includes("moon") || pLower.includes("space") || pLower.includes("astronomy") || pLower.includes("sky")) { - gradientStart = "#1E293B"; - gradientEnd = "#0F172A"; - keywordLabel = "Luminous Moon in Starry Sky"; - sceneShapes = ` - - - - - - - - - - - - `; - } else if (pLower.includes("cat") || pLower.includes("kitten") || pLower.includes("feline")) { - gradientStart = "#4F46E5"; - gradientEnd = "#7C3AED"; - keywordLabel = "Stylized Cat Portrait"; - sceneShapes = ` - - - - - - - - - - - - - - - - `; - } else if (pLower.includes("dog") || pLower.includes("puppy") || pLower.includes("canine")) { - gradientStart = "#D97706"; - gradientEnd = "#B45309"; - keywordLabel = "Friendly Dog Portrait"; - sceneShapes = ` - - - - - - - - - - - - - `; - } else if (pLower.includes("city") || pLower.includes("cyberpunk") || pLower.includes("tokyo") || pLower.includes("neon")) { - gradientStart = "#111827"; - gradientEnd = "#311042"; - keywordLabel = "Neon Cyberpunk Skyline"; - sceneShapes = ` - - - - - - - - - - - - - `; - } else if (pLower.includes("car") || pLower.includes("vehicle") || pLower.includes("supercar")) { - gradientStart = "#DC2626"; - gradientEnd = "#991B1B"; - keywordLabel = "Futuristic Concept Car"; - sceneShapes = ` - - - - - - - - - - - - - `; - } else { - // General gradient waves - gradientStart = "#06B6D4"; - gradientEnd = "#0891B2"; - keywordLabel = "Abstract Creative Concept"; - sceneShapes = ` - - - - `; - } - - const svgString = ` - - - - - - - - - - - - - - - - - ${sceneShapes} - - - - - - - ${keywordLabel} - Seed: ${seedVal} • Steps: ${payload.steps} • Scale: ${payload.cfg_scale} - - `; - - const base64Svg = btoa(unescape(encodeURIComponent(svgString))); - const mockImageUrl = `data:image/svg+xml;base64,${base64Svg}`; - const durationSec = parseFloat(((Date.now() - startTime) / 1000).toFixed(1)); - - return { - image: mockImageUrl, - seed: payload.seed, - duration_sec: durationSec, - }; - }; // txt2img uses /v1/images/generations; img2img uses /sdapi/v1/img2img. const isImg2Img = !!payload.image; @@ -601,11 +435,12 @@ export async function generateImage(prompt, negativePrompt, constraints, activeM } } catch (err) { if (err.name === "AbortError" || err.message.startsWith("Generation failed")) throw err; - console.warn("Could not reach local server. Falling back to simulation mode.", err); + console.warn("Could not reach local server.", err); + throw new Error( + "The image generation server is not responding or crashed. " + + "Try restarting the backend from Model Manager, or check the terminal for a backend error." + ); } - - // Fallback to mock generation if server is offline/not reachable - return await runMockGeneration(); } // Perform model file import (copy to USB in Tauri, simulated in Web mode) diff --git a/scripts/build_from_source.sh b/scripts/build_from_source.sh new file mode 100755 index 0000000..f2e3786 --- /dev/null +++ b/scripts/build_from_source.sh @@ -0,0 +1,130 @@ +#!/usr/bin/env bash +# +# Local AI Image Generator - Compile backends from source +# For systems with GLIBC < 2.38 (e.g. Ubuntu 22.04) +# + +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +ROOT_DIR="$(dirname "$SCRIPT_DIR")" +APP_DIR="$ROOT_DIR/app" +BACKEND_DIR="$APP_DIR/backend/linux" +BUILD_DIR="$APP_DIR/tools/build-sd" + +# Pinned release tag +PINNED_TAG="master-685-19bdfe2" + +echo "=== Local AI Image Generator - Build from Source ===" +echo "Target directories:" +echo " CPU Backend -> $BACKEND_DIR/cpu" +echo " Vulkan Backend -> $BACKEND_DIR/vulkan" +echo "" + +# 1. Clone stable-diffusion.cpp +if [ ! -d "$BUILD_DIR" ]; then + echo "Cloning stable-diffusion.cpp..." + git clone https://github.com/leejet/stable-diffusion.cpp.git "$BUILD_DIR" +else + echo "Using existing stable-diffusion.cpp directory." +fi + +cd "$BUILD_DIR" +echo "Checking out pinned tag $PINNED_TAG..." +git fetch origin +git checkout -f "$PINNED_TAG" +git submodule update --init --recursive + +# 2. Build CPU Backend +echo "" +echo "=== Building CPU Backend ===" +rm -rf build-cpu && mkdir build-cpu && cd build-cpu +cmake .. -DSD_BUILD_SHARED_LIBS=ON -DCMAKE_BUILD_TYPE=Release +cmake --build . --config Release -j$(nproc) + +echo "Copying CPU binaries..." +mkdir -p "$BACKEND_DIR/cpu" +if [ -f bin/sd-server ]; then + cp bin/sd-server "$BACKEND_DIR/cpu/sd-cpu" + cp bin/sd-server "$BACKEND_DIR/cpu/sd-server-cpu" +else + echo "ERROR: bin/sd-server was not found!" + exit 1 +fi +if [ -f bin/sd ]; then + cp bin/sd "$BACKEND_DIR/cpu/sd-cli-cpu" +elif [ -f bin/sd-cli ]; then + cp bin/sd-cli "$BACKEND_DIR/cpu/sd-cli-cpu" +fi +# Find and copy libstable-diffusion.so (might be in bin/ or in build root) +SO_PATH=$(find . -name "libstable-diffusion.so" | head -n 1) +if [ -n "$SO_PATH" ]; then + cp "$SO_PATH" "$BACKEND_DIR/cpu/" + echo "Copied libstable-diffusion.so to CPU directory." +else + echo "WARNING: libstable-diffusion.so not found for CPU build!" +fi + +# 3. Build Vulkan Backend +cd "$BUILD_DIR" +echo "" +echo "=== Building Vulkan Backend ===" +if rm -rf build-vulkan && mkdir build-vulkan && cd build-vulkan && \ + cmake .. -DSD_VULKAN=ON -DSD_BUILD_SHARED_LIBS=ON -DCMAKE_BUILD_TYPE=Release && \ + cmake --build . --config Release -j$(nproc); then + + echo "Copying Vulkan binaries..." + mkdir -p "$BACKEND_DIR/vulkan" + if [ -f bin/sd-server ]; then + cp bin/sd-server "$BACKEND_DIR/vulkan/sd-vulkan" + cp bin/sd-server "$BACKEND_DIR/vulkan/sd-server-vulkan" + else + echo "ERROR: bin/sd-server was not found!" + exit 1 + fi + if [ -f bin/sd ]; then + cp bin/sd "$BACKEND_DIR/vulkan/sd-cli-vulkan" + elif [ -f bin/sd-cli ]; then + cp bin/sd-cli "$BACKEND_DIR/vulkan/sd-cli-vulkan" + fi + SO_PATH_VK=$(find . -name "libstable-diffusion.so" | head -n 1) + if [ -n "$SO_PATH_VK" ]; then + cp "$SO_PATH_VK" "$BACKEND_DIR/vulkan/" + echo "Copied libstable-diffusion.so to Vulkan directory." + else + echo "WARNING: libstable-diffusion.so not found for Vulkan build!" + fi +else + echo "WARNING: Vulkan backend build failed. Bypassing Vulkan backend compilation..." +fi +cd "$BUILD_DIR" +echo "" +echo "=== Building CUDA Backend ===" +rm -rf build-cuda && mkdir build-cuda && cd build-cuda +cmake .. -DSD_CUDA=ON -DSD_BUILD_SHARED_LIBS=ON -DCMAKE_BUILD_TYPE=Release +cmake --build . --config Release -j$(nproc) + +echo "Copying CUDA binaries..." +mkdir -p "$BACKEND_DIR/cuda" +if [ -f bin/sd-server ]; then + cp bin/sd-server "$BACKEND_DIR/cuda/sd-cuda" + cp bin/sd-server "$BACKEND_DIR/cuda/sd-server-cuda" +else + echo "ERROR: bin/sd-server was not found!" + exit 1 +fi +if [ -f bin/sd ]; then + cp bin/sd "$BACKEND_DIR/cuda/sd-cli-cuda" +elif [ -f bin/sd-cli ]; then + cp bin/sd-cli "$BACKEND_DIR/cuda/sd-cli-cuda" +fi +SO_PATH_CUDA=$(find . -name "libstable-diffusion.so" | head -n 1) +if [ -n "$SO_PATH_CUDA" ]; then + cp "$SO_PATH_CUDA" "$BACKEND_DIR/cuda/" + echo "Copied libstable-diffusion.so to CUDA directory." +else + echo "WARNING: libstable-diffusion.so not found for CUDA build!" +fi + +echo "" +echo "=== Build from source completed successfully! ===" diff --git a/scripts/reset.sh b/scripts/reset.sh new file mode 100755 index 0000000..81995e1 --- /dev/null +++ b/scripts/reset.sh @@ -0,0 +1,59 @@ +#!/usr/bin/env bash +# +# Local AI Image Generator - Linux Reset Script +# Resets portable app dependencies/builds while preserving user models and outputs. +# + +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +ROOT_DIR="$(dirname "$SCRIPT_DIR")" +APP_DIR="$ROOT_DIR/app" + +echo "" +echo " ============================================================" +echo " Resetting Local-AI-Image-Generator..." +echo " ============================================================" +echo "" + +# Delete tools/node +if [[ -d "$APP_DIR/tools" ]]; then + echo " >> Removing portable tools/ node folder..." + rm -rf "$APP_DIR/tools" +fi + +# Delete backend +if [[ -d "$APP_DIR/backend" ]]; then + echo " >> Removing backend binaries..." + rm -rf "$APP_DIR/backend" +fi + +# Delete dist +if [[ -d "$APP_DIR/dist" ]]; then + echo " >> Removing dist/ build folder..." + rm -rf "$APP_DIR/dist" +fi + +# Preserve models +if [[ -d "$APP_DIR/models" ]]; then + echo " >> Preserving downloaded models in app/models." +fi + +# Delete node_modules in frontend +if [[ -d "$APP_DIR/frontend/node_modules" ]]; then + echo " >> Removing frontend node_modules..." + rm -rf "$APP_DIR/frontend/node_modules" +fi + +# Delete package-lock.json in frontend +if [[ -f "$APP_DIR/frontend/package-lock.json" ]]; then + echo " >> Removing frontend package-lock.json..." + rm -f "$APP_DIR/frontend/package-lock.json" +fi + +echo "" +echo " ============================================================" +echo " Reset complete. Models and generated outputs were preserved." +echo " ============================================================" +echo "" +read -rp " Press Enter to close..." diff --git a/scripts/serve.cjs b/scripts/serve.cjs index dc8993d..c63775e 100644 --- a/scripts/serve.cjs +++ b/scripts/serve.cjs @@ -28,7 +28,10 @@ const BACKEND_PATHS = { cuda: path.join(ROOT, "app", "backend", "win", "cuda", "sd-cuda.exe"), vulkan: path.join(ROOT, "app", "backend", "win", "vulkan", "sd-vulkan.exe"), mac: path.join(ROOT, "app", "backend", "mac", "sd"), - linux: path.join(ROOT, "app", "backend", "linux", "sd-vulkan"), + linuxCpu: path.join(ROOT, "app", "backend", "linux", "cpu", "sd-cpu"), + linuxVulkan: path.join(ROOT, "app", "backend", "linux", "vulkan", "sd-vulkan"), + linuxRocm: path.join(ROOT, "app", "backend", "linux", "rocm", "sd-rocm"), + linuxCuda: path.join(ROOT, "app", "backend", "linux", "cuda", "sd-cuda"), }; let BACKEND_PATH = ""; if (osPlatform === "win32") { @@ -51,7 +54,14 @@ if (osPlatform === "win32") { } else if (osPlatform === "darwin") { BACKEND_PATH = BACKEND_PATHS.mac; } else { - BACKEND_PATH = BACKEND_PATHS.linux; + // Linux: default to Vulkan if available, otherwise CPU + if (fs.existsSync(BACKEND_PATHS.linuxVulkan)) { + BACKEND_PATH = BACKEND_PATHS.linuxVulkan; + } else if (fs.existsSync(BACKEND_PATHS.linuxCpu)) { + BACKEND_PATH = BACKEND_PATHS.linuxCpu; + } else { + BACKEND_PATH = BACKEND_PATHS.linuxVulkan; + } } const MODELS = path.join(ROOT, "app", "models"); if (!fs.existsSync(MODELS)) { @@ -128,6 +138,32 @@ function getCpuUsagePercent() { return Math.max(0, Math.min(100, Math.round((1 - idleDelta / totalDelta) * 1000) / 10)); } +function detectLinuxGpuFromSysfs() { + try { + const pciDir = "/sys/bus/pci/devices"; + if (!fs.existsSync(pciDir)) return null; + const entries = fs.readdirSync(pciDir); + for (const entry of entries) { + const vendorFile = path.join(pciDir, entry, "vendor"); + const deviceFile = path.join(pciDir, entry, "device"); + if (!fs.existsSync(vendorFile)) continue; + const vendor = fs.readFileSync(vendorFile, "utf8").trim(); + let device = ""; + try { device = fs.readFileSync(deviceFile, "utf8").trim(); } catch (_) {} + if (vendor === "0x10de") { + return { name: `NVIDIA GPU (${device || entry})` }; + } + if (vendor === "0x1002") { + return { name: `AMD GPU (${device || entry})` }; + } + if (vendor === "0x8086") { + return { name: `Intel GPU (${device || entry})` }; + } + } + } catch (_) {} + return null; +} + function getGpuInfo() { if (cachedGpuInfo) return cachedGpuInfo; @@ -144,6 +180,14 @@ function getGpuInfo() { } catch (_) {} } + if (osPlatform === "linux") { + const linuxGpu = detectLinuxGpuFromSysfs(); + if (linuxGpu) { + cachedGpuInfo = linuxGpu; + return cachedGpuInfo; + } + } + cachedGpuInfo = { name: "Unavailable" }; return cachedGpuInfo; } @@ -358,7 +402,9 @@ function getSetupPaths() { node: path.join(appDir, "tools", "node-linux", "bin", "node"), npm: path.join(appDir, "tools", "node-linux", "bin", "npm"), distIndex: path.join(DIST, "index.html"), - linuxBackend: BACKEND_PATHS.linux, + linuxCpuBackend: BACKEND_PATHS.linuxCpu, + linuxVulkanBackend: BACKEND_PATHS.linuxVulkan, + linuxRocmBackend: BACKEND_PATHS.linuxRocm, models: MODELS, outputs: OUTPUTS, }; @@ -381,7 +427,9 @@ async function getHealth() { } else if (osPlatform === "darwin") { checks.push(getPathInfo("Mac backend", paths.macBackend)); } else { - checks.push(getPathInfo("Linux backend", paths.linuxBackend)); + checks.push(getPathInfo("Linux CPU backend", paths.linuxCpuBackend)); + checks.push(getPathInfo("Linux Vulkan backend", paths.linuxVulkanBackend)); + checks.push(getPathInfo("Linux ROCm backend", paths.linuxRocmBackend)); } let backendInstalled = false; @@ -391,11 +439,15 @@ async function getHealth() { } else if (osPlatform === "darwin") { backendInstalled = checks.find((check) => check.label === "Mac backend")?.exists; } else { - backendInstalled = checks.find((check) => check.label === "Linux backend")?.exists; + backendInstalled = + checks.find((check) => check.label === "Linux CPU backend")?.exists || + checks.find((check) => check.label === "Linux CPU backend")?.exists || + checks.find((check) => check.label === "Linux Vulkan backend")?.exists || + checks.find((check) => check.label === "Linux ROCm backend")?.exists; } const criticalOk = checks - .filter((check) => !["CUDA backend", "Vulkan backend", "Linux backend", "Mac backend"].includes(check.label)) + .filter((check) => !["CUDA backend", "Vulkan backend", "Linux CPU backend", "Linux Vulkan backend", "Linux ROCm backend", "Mac backend"].includes(check.label)) .every((check) => check.ok) && backendInstalled; const ports = { @@ -408,7 +460,7 @@ async function getHealth() { ports.backend.ok = true; const issues = checks - .filter((check) => !check.ok && !["CUDA backend", "Vulkan backend", "Linux backend", "Mac backend"].includes(check.label)) + .filter((check) => !check.ok && !["CUDA backend", "Vulkan backend", "Linux CPU backend", "Linux Vulkan backend", "Linux ROCm backend", "Mac backend"].includes(check.label)) .map((check) => `${check.label} is missing or not writable.`); if (!backendInstalled) { issues.push(`No ${osPlatform === "win32" ? "Windows" : osPlatform === "darwin" ? "macOS" : "Linux"} backend binary is installed.`); @@ -513,20 +565,35 @@ function hasNvidiaGpu() { } } +function hasAmdGpu() { + const info = getGpuInfo().name.toLowerCase(); + return info.includes("amd") || info.includes("advanced micro devices") || info.includes("radeon"); +} + function getBackendOptions() { if (cachedBackendOptions) return cachedBackendOptions; - const cudaAvailable = osPlatform === "win32" && hasNvidiaGpu() && backendAccepts(BACKEND_PATHS.cuda, "cuda"); - const cudaInstalled = osPlatform === "win32" && fs.existsSync(BACKEND_PATHS.cuda); + const cudaInstalled = (osPlatform === "win32" && fs.existsSync(BACKEND_PATHS.cuda)) || + (osPlatform === "linux" && fs.existsSync(BACKEND_PATHS.linuxCuda)); + const cudaAvailable = cudaInstalled && hasNvidiaGpu() && backendAccepts( + osPlatform === "win32" ? BACKEND_PATHS.cuda : BACKEND_PATHS.linuxCuda, + "cuda" + ); const vulkanInstalled = (osPlatform === "win32" && fs.existsSync(BACKEND_PATHS.vulkan)) || - (osPlatform === "linux" && fs.existsSync(BACKEND_PATHS.linux)); + (osPlatform === "linux" && fs.existsSync(BACKEND_PATHS.linuxVulkan)); const vulkanAvailable = vulkanInstalled && backendAccepts( - osPlatform === "win32" ? BACKEND_PATHS.vulkan : BACKEND_PATHS.linux, + osPlatform === "win32" ? BACKEND_PATHS.vulkan : BACKEND_PATHS.linuxVulkan, "vulkan" ); + const rocmInstalled = osPlatform === "linux" && fs.existsSync(BACKEND_PATHS.linuxRocm); + const rocmAvailable = rocmInstalled && hasAmdGpu() && backendAccepts(BACKEND_PATHS.linuxRocm, "rocm"); + const cpuInstalled = osPlatform === "linux" && fs.existsSync(BACKEND_PATHS.linuxCpu); + const options = [{ id: "cpu", label: "CPU", available: true }]; if (vulkanAvailable) options.push({ id: "vulkan", label: "Vulkan GPU", available: true }); + if (rocmAvailable) options.push({ id: "rocm", label: "ROCm GPU (AMD)", available: true }); if (cudaAvailable) options.push({ id: "cuda", label: "CUDA GPU", available: true }); + const unavailable = []; if (vulkanInstalled && !vulkanAvailable) { unavailable.push({ id: "vulkan", label: "Vulkan GPU", reason: "Installed, but this binary did not register a Vulkan backend on this machine." }); @@ -534,6 +601,10 @@ function getBackendOptions() { if (cudaInstalled && !cudaAvailable) { unavailable.push({ id: "cuda", label: "CUDA GPU", reason: "Installed, but CUDA backend validation failed." }); } + if (rocmInstalled && !rocmAvailable) { + unavailable.push({ id: "rocm", label: "ROCm GPU (AMD)", reason: "Installed, but ROCm backend validation failed." }); + } + let defaultBackend = "cpu"; if (cudaAvailable) { const gpuName = String(getGpuInfo().name).toLowerCase(); @@ -543,6 +614,8 @@ function getBackendOptions() { } else { defaultBackend = "cuda"; } + } else if (rocmAvailable) { + defaultBackend = "rocm"; } else if (vulkanAvailable) { defaultBackend = "vulkan"; } @@ -552,6 +625,7 @@ function getBackendOptions() { unavailable, cudaAvailable, vulkanAvailable, + rocmAvailable, defaultBackendType: defaultBackend, }; return cachedBackendOptions; @@ -560,17 +634,36 @@ function getBackendOptions() { function backendAccepts(binaryPath, backendName) { if (!binaryPath || !fs.existsSync(binaryPath)) return false; try { - const result = spawnSync(binaryPath, [ + const probeArgs = [ "--backend", backendName, "--params-backend", backendName, "--model", path.join(MODELS, "__backend_probe_missing__.safetensors"), "--listen-port", "18082", - ], { encoding: "utf8", timeout: 5000 }); - const output = `${result.stdout || ""}\n${result.stderr || ""}`; - if (output.includes("backend config failed") || output.includes(`backend '${backendName}' was not found`)) { + ]; + let result = spawnSync(binaryPath, probeArgs, { encoding: "utf8", timeout: 5000 }); + let output = `${result.stdout || ""}\n${result.stderr || ""}`; + + // Some binaries do not support --backend. If we see "unknown argument", + // retry without backend flags so we can still verify the binary launches. + if (output.includes("unknown argument") && output.includes("--backend")) { + const fallbackArgs = [ + "--model", path.join(MODELS, "__backend_probe_missing__.safetensors"), + "--listen-port", "18082", + ]; + result = spawnSync(binaryPath, fallbackArgs, { encoding: "utf8", timeout: 5000 }); + output = `${result.stdout || ""}\n${result.stderr || ""}`; + } + + const lower = output.toLowerCase(); + if (lower.includes("backend config failed") || output.includes(`backend '${backendName}' was not found`)) { return false; } - return output.includes("file") || output.includes("not found") || output.includes("loading model"); + // Reject binaries that fail at the dynamic linker / glibc level. + if (lower.includes("glibc") || lower.includes("libc.so") || lower.includes("libstdc++") || lower.includes("cannot open shared object")) { + return false; + } + // A healthy binary prints project-specific log lines when it tries to load the model. + return lower.includes("stable-diffusion.cpp") || lower.includes("loading model"); } catch (_) { return false; } @@ -578,12 +671,28 @@ function backendAccepts(binaryPath, backendName) { function selectBackendPath(useGpu, backendType = "auto") { const resolvedType = resolveBackendType(useGpu, backendType); - if (osPlatform === "win32" && resolvedType === "cuda" && fs.existsSync(BACKEND_PATHS.cuda)) { - return BACKEND_PATHS.cuda; + if (osPlatform === "win32") { + if (resolvedType === "cuda" && fs.existsSync(BACKEND_PATHS.cuda)) return BACKEND_PATHS.cuda; + if (fs.existsSync(BACKEND_PATHS.vulkan)) return BACKEND_PATHS.vulkan; + return BACKEND_PATH; } - if (osPlatform === "win32" && fs.existsSync(BACKEND_PATHS.vulkan)) { - return BACKEND_PATHS.vulkan; + if (osPlatform === "linux") { + let finalType = resolvedType; + if (finalType === "cuda") { + if (fs.existsSync(BACKEND_PATHS.linuxCuda)) { + return BACKEND_PATHS.linuxCuda; + } + finalType = "vulkan"; + } + if (finalType === "rocm" && fs.existsSync(BACKEND_PATHS.linuxRocm)) return BACKEND_PATHS.linuxRocm; + if (resolvedType === "vulkan" && fs.existsSync(BACKEND_PATHS.linuxVulkan)) return BACKEND_PATHS.linuxVulkan; + if (resolvedType === "cpu" && fs.existsSync(BACKEND_PATHS.linuxCpu)) return BACKEND_PATHS.linuxCpu; + if (fs.existsSync(BACKEND_PATHS.linuxVulkan)) return BACKEND_PATHS.linuxVulkan; + if (fs.existsSync(BACKEND_PATHS.linuxCpu)) return BACKEND_PATHS.linuxCpu; + return BACKEND_PATH; } + // macOS fallback + if (fs.existsSync(BACKEND_PATHS.mac)) return BACKEND_PATHS.mac; return BACKEND_PATH; } @@ -598,6 +707,7 @@ function getBackendMode(backendPath, useGpu, backendType = "auto") { if (useGpu === false || backendType === "cpu") return "CPU"; const name = path.basename(backendPath || "").toLowerCase(); if (name.includes("cuda")) return "CUDA GPU"; + if (name.includes("rocm")) return "ROCm GPU"; if (name.includes("vulkan")) return "Vulkan GPU"; return "GPU"; } @@ -758,12 +868,20 @@ async function startBackend(settings = {}) { "--sampler-rng", "cpu", ); } else if (requestedBackend === "cuda") { + // CUDA is only supported on Windows. Linux has no reliable prebuilt CUDA binary. args.push( "--backend", "cuda0", "--params-backend", "cuda0", "--rng", "cuda", "--sampler-rng", "cuda", ); + } else if (requestedBackend === "rocm") { + args.push( + "--backend", "rocm0", + "--params-backend", "rocm0", + "--rng", "cpu", + "--sampler-rng", "cpu", + ); } if (currentSettings.vaeTiling) { @@ -773,10 +891,30 @@ async function startBackend(settings = {}) { args.push("--vae-on-cpu"); } + // Build environment for Linux backends so bundled .so libraries are found. + // Official Linux releases ship libstable-diffusion.so next to the executable. + const spawnEnv = { ...process.env }; + if (osPlatform === "linux") { + const extraLibs = []; + if (requestedBackend === "rocm") { + extraLibs.push(path.dirname(BACKEND_PATHS.linuxRocm)); + } else if (requestedBackend === "vulkan") { + extraLibs.push(path.dirname(BACKEND_PATHS.linuxVulkan)); + } else if (requestedBackend === "cpu") { + extraLibs.push(path.dirname(BACKEND_PATHS.linuxCpu)); + } else if (requestedBackend === "cuda") { + extraLibs.push(path.dirname(BACKEND_PATHS.linuxCuda)); + } + if (extraLibs.length > 0) { + const existing = spawnEnv.LD_LIBRARY_PATH || ""; + spawnEnv.LD_LIBRARY_PATH = extraLibs.join(":") + (existing ? ":" + existing : ""); + } + } + console.log(" [backend] Starting:", path.basename(backendPath), args.join(" ")); backendReady = false; - backendProc = spawn(backendPath, args, { stdio: "pipe" }); + backendProc = spawn(backendPath, args, { stdio: "pipe", env: spawnEnv }); startBackendReadyPoll(); backendProc.stdout.on("data", d => { @@ -873,6 +1011,10 @@ async function startBackend(settings = {}) { backendLoadState.backendMode = "Vulkan GPU"; currentSettings.backendMode = "Vulkan GPU"; } + if (cleanOutput.includes("ggml_hip") || cleanOutput.includes("ggml_rocm")) { + backendLoadState.backendMode = "ROCm GPU"; + currentSettings.backendMode = "ROCm GPU"; + } if (cleanOutput.includes("[ERROR]")) { const nextError = describeBackendError(cleanOutput.trim(), currentSettings.model); const hasSpecificFileError = String(backendError || "").includes("incomplete or corrupted"); diff --git a/scripts/setup.sh b/scripts/setup.sh new file mode 100755 index 0000000..8c47af1 --- /dev/null +++ b/scripts/setup.sh @@ -0,0 +1,327 @@ +#!/usr/bin/env bash +# +# Local AI Image Generator - Linux Setup Script +# Self-contained: no apt/yum/pacman, no global Node.js install. +# + +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +ROOT_DIR="$(dirname "$SCRIPT_DIR")" +APP_DIR="$ROOT_DIR/app" +FRONTEND_DIR="$APP_DIR/frontend" +TOOLS_DIR="$APP_DIR/tools" +NODE_DIR="$TOOLS_DIR/node-linux" +NODE_BIN="$NODE_DIR/bin/node" +NPM_BIN="$NODE_DIR/bin/npm" +DIST_DIR="$APP_DIR/dist" +BACKEND_DIR="$APP_DIR/backend/linux" + +# Release pins +SD_RELEASE="master-685-19bdfe2" +SD_SHORT_HASH="${SD_RELEASE##*-}" +SD_BASE_URL="https://github.com/leejet/stable-diffusion.cpp/releases/download/$SD_RELEASE" +NODE_VERSION="22.12.0" +NODE_TARBALL="node-v${NODE_VERSION}-linux-x64.tar.xz" +NODE_URL="https://nodejs.org/dist/v${NODE_VERSION}/$NODE_TARBALL" + +# Flags +MAX_PERF=0 +if [[ "${1:-}" == "--max-perf" ]]; then + MAX_PERF=1 +fi + +# ── Helpers ───────────────────────────────────────────────────────────────── +print_header() { + clear 2>/dev/null || true + echo "" + echo " ============================================================" + echo " LOCAL AI IMAGE GENERATOR - Linux First-Time Setup" + echo " 100% Self-Contained | No System Install Required" + echo " ============================================================" + echo "" +} + +print_step() { + local n="$1" total="$2" title="$3" + echo "" + echo " [$n/$total] $title" + echo " ------------------------------------------------------------" +} + +print_ok() { echo " OK $1"; } +print_info() { echo " >> $1"; } +print_warn() { echo " !! $1"; } +print_fail() { echo " XX $1"; } + +format_bytes() { + local b="${1:-0}" + if command -v bc >/dev/null 2>&1; then + if (( b > 1073741824 )); then printf "%.2f GB" "$(echo "scale=4; $b / 1073741824" | bc)"; return; fi + if (( b > 1048576 )); then printf "%.1f MB" "$(echo "scale=4; $b / 1048576" | bc)"; return; fi + if (( b > 1024 )); then printf "%.0f KB" "$(echo "scale=4; $b / 1024" | bc)"; return; fi + else + if (( b > 1073741824 )); then printf "%.2f GB" "$(awk "BEGIN {printf \"%.2f\", $b/1073741824}")"; return; fi + if (( b > 1048576 )); then printf "%.1f MB" "$(awk "BEGIN {printf \"%.1f\", $b/1048576}")"; return; fi + if (( b > 1024 )); then printf "%.0f KB" "$(awk "BEGIN {printf \"%.0f\", $b/1024}")"; return; fi + fi + printf "%s B" "$b" +} + +# Rich download with progress bar +download_file() { + local url="$1" dest="$2" label="$3" + print_info "Downloading: $label" + echo "" + + local tmp_dest="${dest}.part" + rm -f "$tmp_dest" + + curl -fSL --progress-bar "$url" -o "$tmp_dest" || { + print_fail "Download failed: $url" + rm -f "$tmp_dest" + return 1 + } + + mv "$tmp_dest" "$dest" + echo "" + local fsize + fsize="$(stat -c%s "$dest" 2>/dev/null || stat -f%z "$dest" 2>/dev/null || echo 0)" + print_ok "Downloaded $(format_bytes "$fsize")" +} + +# Extract ZIP using Python zipfile (preferred), unzip, or Node.js adm-zip +extract_zip() { + local zip_path="$1" dest="$2" label="$3" + print_info "Extracting: $label" + mkdir -p "$dest" + + # Prefer Python zipfile (most reliable, no host deps beyond python3) + if command -v python3 >/dev/null 2>&1; then + python3 -c " +import zipfile, sys, os +with zipfile.ZipFile(sys.argv[1], 'r') as z: + for member in z.namelist(): + z.extract(member, sys.argv[2]) +" "$zip_path" "$dest" && return 0 + fi + + if command -v unzip >/dev/null 2>&1; then + unzip -o -q "$zip_path" -d "$dest" && return 0 + fi + + if command -v python >/dev/null 2>&1; then + python -c "import zipfile, sys; zipfile.ZipFile(sys.argv[1], 'r').extractall(sys.argv[2])" "$zip_path" "$dest" && return 0 + fi + + print_fail "No ZIP extractor available (tried python3, unzip, python)." + return 1 +} + +# Extract tar.xz +extract_tarxz() { + local tar_path="$1" dest="$2" label="$3" + print_info "Extracting: $label" + mkdir -p "$dest" + tar -xf "$tar_path" -C "$dest" + print_ok "Extracted $label" +} + +detect_gpu_vendor() { + local vendor="" + if [[ -d /sys/bus/pci/devices ]]; then + for vfile in /sys/bus/pci/devices/*/vendor; do + if [[ -f "$vfile" ]]; then + local vid + vid="$(cat "$vfile" 2>/dev/null || true)" + case "$vid" in + "0x10de") vendor="nvidia" ;; + "0x1002") vendor="amd" ;; + "0x8086") [[ -z "$vendor" ]] && vendor="intel" ;; + esac + fi + done + fi + echo "$vendor" +} + +# Official Linux binaries are built on Ubuntu 24.04 and link against glibc 2.38+. +# This routine prints a warning on older distributions so users know upfront. +check_glibc() { + local required="2.38" + local current="" + if command -v ldd >/dev/null 2>&1; then + current="$(ldd --version 2>/dev/null | head -n1 | grep -oP '[0-9]+\.[0-9]+' | head -n1 || true)" + fi + if [[ -z "$current" ]]; then + print_warn "Could not detect glibc version. Prebuilt Linux backends require glibc $required+ (Ubuntu 24.04)." + return + fi + if [[ "$(printf '%s\n' "$required" "$current" | sort -V | head -n1)" != "$required" ]]; then + print_warn "Detected glibc $current. Prebuilt Linux backends require glibc $required+ (Ubuntu 24.04)." + print_info "You can still use the app, but the downloaded backends will not start on this system." + print_info "To fix: upgrade to Ubuntu 24.04+ or build stable-diffusion.cpp from source (see README)." + fi +} + +copy_binaries_from_extracted() { + local extracted_dir="$1" dest_dir="$2" main_name="$3" server_name="$4" + + while IFS= read -r -d '' f; do + local base + base="$(basename "$f")" + case "$base" in + sd|sd-cli) cp "$f" "$dest_dir/$main_name" ;; + sd-server) cp "$f" "$dest_dir/$server_name" ;; + esac + done < <(find "$extracted_dir" -type f \( -name "sd" -o -name "sd-cli" -o -name "sd-server" \) -print0 2>/dev/null) + + # Copy any .so files + find "$extracted_dir" -type f -name "*.so" -exec cp {} "$dest_dir/" \; 2>/dev/null || true +} + +# ════════════════════════════════════════════════════════════════════════════ +print_header + +check_glibc + +TOTAL_STEPS=4 + +# ── Step 1: Portable Node.js ──────────────────────────────────────────────── +print_step 1 $TOTAL_STEPS "Setting up portable Node.js (app/tools/node-linux/)" + +if [[ -x "$NODE_BIN" && -x "$NPM_BIN" ]]; then + VERSION=$("$NODE_BIN" --version) + print_ok "Portable Node.js already ready: $VERSION" +else + mkdir -p "$TOOLS_DIR" + NODE_TAR_PATH="$TOOLS_DIR/$NODE_TARBALL" + + download_file "$NODE_URL" "$NODE_TAR_PATH" "Node.js v${NODE_VERSION} LTS (Portable tarball)" + extract_tarxz "$NODE_TAR_PATH" "$TOOLS_DIR" "Node.js" + rm -f "$NODE_TAR_PATH" + + EXTRACTED_DIR="$(find "$TOOLS_DIR" -maxdepth 1 -type d -name 'node-v*-linux-x64' | head -n 1)" + if [[ -d "$EXTRACTED_DIR" ]]; then + rm -rf "$NODE_DIR" + mv "$EXTRACTED_DIR" "$NODE_DIR" + fi + + if [[ ! -x "$NODE_BIN" || ! -x "$NPM_BIN" ]]; then + print_fail "Portable Node.js install is incomplete." + exit 1 + fi + + VERSION=$("$NODE_BIN" --version) + print_ok "Portable Node.js ready: $VERSION" +fi + +# ── Step 2: stable-diffusion.cpp Backends ─────────────────────────────────── +VENDOR="$(detect_gpu_vendor)" +print_step 2 $TOTAL_STEPS "Detecting GPU vendor: ${VENDOR:-none}" + +mkdir -p "$BACKEND_DIR" + +# CPU backend (always) +CPU_BACKEND_DIR="$BACKEND_DIR/cpu" +if [[ ! -f "$CPU_BACKEND_DIR/sd-cpu" ]]; then + mkdir -p "$CPU_BACKEND_DIR" + CPU_ZIP="$TOOLS_DIR/sd-cpu.zip" + download_file "$SD_BASE_URL/sd-master-${SD_SHORT_HASH}-bin-Linux-Ubuntu-24.04-x86_64.zip" "$CPU_ZIP" "stable-diffusion.cpp CPU Backend (Linux x86_64)" + extract_zip "$CPU_ZIP" "$CPU_BACKEND_DIR/extracted" "CPU Backend" + rm -f "$CPU_ZIP" + copy_binaries_from_extracted "$CPU_BACKEND_DIR/extracted" "$CPU_BACKEND_DIR" "sd-cpu" "sd-server-cpu" + rm -rf "$CPU_BACKEND_DIR/extracted" + chmod +x "$CPU_BACKEND_DIR/sd-cpu" 2>/dev/null || true + print_ok "CPU backend installed." +else + print_ok "CPU backend already ready." +fi + +# Vulkan backend (always - cross-vendor GPU fallback) +VULKAN_BACKEND_DIR="$BACKEND_DIR/vulkan" +if [[ ! -f "$VULKAN_BACKEND_DIR/sd-vulkan" ]]; then + mkdir -p "$VULKAN_BACKEND_DIR" + VULKAN_ZIP="$TOOLS_DIR/sd-vulkan.zip" + download_file "$SD_BASE_URL/sd-master-${SD_SHORT_HASH}-bin-Linux-Ubuntu-24.04-x86_64-vulkan.zip" "$VULKAN_ZIP" "stable-diffusion.cpp Vulkan Backend (Linux x86_64)" + extract_zip "$VULKAN_ZIP" "$VULKAN_BACKEND_DIR/extracted" "Vulkan Backend" + rm -f "$VULKAN_ZIP" + copy_binaries_from_extracted "$VULKAN_BACKEND_DIR/extracted" "$VULKAN_BACKEND_DIR" "sd-vulkan" "sd-server-vulkan" + rm -rf "$VULKAN_BACKEND_DIR/extracted" + chmod +x "$VULKAN_BACKEND_DIR/sd-vulkan" 2>/dev/null || true + print_ok "Vulkan backend installed." +else + print_ok "Vulkan backend already ready." +fi + +# ROCm backend (optional --max-perf, or auto-detected AMD) +ROCM_BACKEND_DIR="$BACKEND_DIR/rocm" +if [[ $MAX_PERF -eq 1 ]] && [[ "$VENDOR" == "amd" || "$VENDOR" == "" ]]; then + if [[ ! -f "$ROCM_BACKEND_DIR/sd-rocm" ]]; then + mkdir -p "$ROCM_BACKEND_DIR" + ROCM_ZIP="$TOOLS_DIR/sd-rocm.zip" + print_warn "ROCm backend is ~1.2 GB. This may take a while..." + download_file "$SD_BASE_URL/sd-master-${SD_SHORT_HASH}-bin-Linux-Ubuntu-24.04-x86_64-rocm-7.13.0.zip" "$ROCM_ZIP" "stable-diffusion.cpp ROCm Backend (Linux x86_64)" + extract_zip "$ROCM_ZIP" "$ROCM_BACKEND_DIR/extracted" "ROCm Backend" + rm -f "$ROCM_ZIP" + copy_binaries_from_extracted "$ROCM_BACKEND_DIR/extracted" "$ROCM_BACKEND_DIR" "sd-rocm" "sd-server-rocm" + rm -rf "$ROCM_BACKEND_DIR/extracted" + chmod +x "$ROCM_BACKEND_DIR/sd-rocm" 2>/dev/null || true + print_ok "ROCm backend installed." + else + print_ok "ROCm backend already ready." + fi +fi + +# CUDA backend on Linux is intentionally disabled. +# upstream leejet/stable-diffusion.cpp does not publish official Linux CUDA binaries +# (see https://github.com/leejet/stable-diffusion.cpp/issues/1291), and the only +# third-party build we evaluated (leaxer-ai/leaxer-stable-diffusion v0.1.0) loads +# models but segfaults during generation. Until a reliable Linux CUDA binary is +# available, Linux NVIDIA systems fall back to the Vulkan backend, which uses the +# same GPU via the vendor's Vulkan driver. +if [[ $MAX_PERF -eq 1 ]] && [[ "$VENDOR" == "nvidia" ]]; then + print_info "Linux CUDA backend is disabled pending a reliable upstream binary." + print_info "NVIDIA GPUs on Linux will use the Vulkan backend instead." +fi + +# ── Step 3: npm install ───────────────────────────────────────────────────── +print_step 3 $TOTAL_STEPS "Installing frontend dependencies (app/frontend/)" + +if [[ ! -x "$NPM_BIN" ]]; then + print_fail "Portable npm was not found at $NPM_BIN" + exit 1 +fi + +cd "$FRONTEND_DIR" +export PATH="$NODE_DIR/bin:$PATH" + +if "$NPM_BIN" install --prefer-offline; then + print_ok "Dependencies installed!" +else + print_fail "npm install failed." + exit 1 +fi + +# ── Step 4: Build frontend ────────────────────────────────────────────────── +print_step 4 $TOTAL_STEPS "Building frontend -> app/dist/" + +if "$NPM_BIN" run build; then + print_ok "Frontend built!" +else + print_fail "Frontend build failed." + exit 1 +fi + +# ── Done ──────────────────────────────────────────────────────────────────── +echo "" +echo " ============================================================" +echo " Setup complete! Run ./start.sh to launch." +echo " ============================================================" +echo "" + +if [[ $MAX_PERF -eq 0 ]] && [[ "$VENDOR" == "nvidia" || "$VENDOR" == "amd" ]]; then + echo " Tip: For maximum GPU performance, re-run with:" + echo " ./scripts/setup.sh --max-perf" + echo "" +fi diff --git a/start.sh b/start.sh new file mode 100755 index 0000000..399e82f --- /dev/null +++ b/start.sh @@ -0,0 +1,134 @@ +#!/usr/bin/env bash +# +# Local AI Image Generator - Linux Launcher +# Double-click or run: ./start.sh +# Use --max-perf to enable ROCm/CUDA backend downloads on first setup. +# + +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +APP_DIR="$SCRIPT_DIR/app" +NODE_DIR="$APP_DIR/tools/node-linux" +NODE_BIN="$NODE_DIR/bin/node" +DIST_INDEX="$APP_DIR/dist/index.html" +SETUP_SCRIPT="$SCRIPT_DIR/scripts/setup.sh" +SERVE_SCRIPT="$SCRIPT_DIR/scripts/serve.cjs" + +FRONTEND_PORT="${FRONTEND_PORT:-1420}" +SETUP_REASON="" +SETUP_MODE="Repair" +MAX_PERF_FLAG="" + +# Parse args +if [[ "${1:-}" == "--max-perf" ]]; then + MAX_PERF_FLAG="--max-perf" +fi + +# ── First-time setup check ───────────────────────────────────────────────── +if [[ ! -d "$NODE_DIR" ]]; then + SETUP_MODE="First-Time Setup" +fi + +if [[ ! -x "$NODE_BIN" ]]; then + SETUP_REASON="Portable Node.js is missing." +fi + +if [[ ! -f "$DIST_INDEX" ]]; then + SETUP_REASON="Frontend build is missing." +fi + +# At minimum we need CPU or Vulkan backend on Linux +if [[ ! -f "$APP_DIR/backend/linux/cpu/sd-cpu" && ! -f "$APP_DIR/backend/linux/vulkan/sd-vulkan" ]]; then + SETUP_REASON="No Linux backend binary is installed." +fi + +if [[ -n "$SETUP_REASON" ]]; then + echo "" + echo " ============================================================" + echo " LOCAL AI IMAGE GENERATOR | $SETUP_MODE" + echo " ============================================================" + echo "" + if [[ "$SETUP_MODE" == "First-Time Setup" ]]; then + echo " This looks like your first run. Setting up automatically..." + else + echo " Local AI Image Generator needs a quick repair before launch." + fi + echo " Reason: $SETUP_REASON" + echo " Models are not downloaded during setup. Download or import them in the app." + echo "" + read -rp " Press Enter to continue, or Ctrl+C to cancel." + + # Clear any existing frontend server process + if command -v fuser >/dev/null 2>&1; then + fuser -k "${FRONTEND_PORT}/tcp" >/dev/null 2>&1 || true + fi + + if ! bash "$SETUP_SCRIPT" $MAX_PERF_FLAG; then + echo "" + echo " [ERROR] Setup failed. Please check the output above." + read -rp " Press Enter to close..." + exit 1 + fi +fi + +# ── Launch ───────────────────────────────────────────────────────────────── +clear 2>/dev/null || true +echo "" +echo " ============================================================" +echo " LOCAL AI IMAGE GENERATOR | Launching..." +echo " ============================================================" +echo "" + +# Clear frontend port +if command -v fuser >/dev/null 2>&1; then + fuser -k "${FRONTEND_PORT}/tcp" >/dev/null 2>&1 || true +fi + +# Start the server +echo " Starting Local AI Image Generator..." +export PATH="$NODE_DIR/bin:$PATH" +export FRONTEND_PORT="$FRONTEND_PORT" + +# Run server in background and capture PID +"$NODE_BIN" "$SERVE_SCRIPT" & +SERVER_PID=$! + +# Wait for server to be ready +sleep 2 + +# Open browser +if command -v xdg-open >/dev/null 2>&1; then + echo " Opening browser at http://localhost:${FRONTEND_PORT}" + xdg-open "http://localhost:${FRONTEND_PORT}" >/dev/null 2>&1 & +else + echo " Open your browser to: http://localhost:${FRONTEND_PORT}" +fi + +echo "" +echo " ============================================================" +echo " Running!" +echo " Web UI: http://localhost:${FRONTEND_PORT}" +echo " GPU API: Auto-selected by the app (starts at 8080)" +echo "" +echo " Press Ctrl+C in this window to stop all services." +echo " ============================================================" +echo "" + +# Cleanup on exit +cleanup() { + echo "" + echo " Shutting down..." + if kill -0 "$SERVER_PID" >/dev/null 2>&1; then + kill -TERM "$SERVER_PID" >/dev/null 2>&1 || true + sleep 1 + kill -KILL "$SERVER_PID" >/dev/null 2>&1 || true + fi + echo " Done. Goodbye!" + exit 0 +} +trap cleanup SIGINT SIGTERM + +# Keep script alive +wait "$SERVER_PID" || true +cleanup