- Remove VARIANT/GPU build args, single image for all platforms
- amd64: nvidia/cuda base with GPU Python packages
- arm64: node base with CPU Python packages
- Add tini as PID 1 for proper signal handling
- Replace npx tsx with node --import tsx
- Split pip install into base + tool layers for better caching
- Add NVIDIA_VISIBLE_DEVICES env vars for container toolkit
- Suppress Python ML library log noise
- Increase healthcheck start-period to 60s
- Remove STIRLING_VARIANT env var
- Remove lama-cleaner from pip installs
Downloads all rembg models (6), RealESRGAN_x4plus.pth weights,
PaddleOCR models for all 7 supported languages, verifies MediaPipe
bundles its face detection models. Runs a final smoke test importing
every ML library. Any failure exits non-zero, failing the Docker build.
lama-cleaner is pip-installed but never imported in any Python script.
inpaint.py uses OpenCV TELEA. Removing saves ~100+ MB of image size.
Also added seam-carving to requirements-gpu.txt where it was missing.
model_path was None, so the model had random weights and always fell back
to Lanczos. Now loads RealESRGAN_x4plus.pth from /opt/models/realesrgan/
(configurable via REALESRGAN_MODEL_PATH env var). Only falls back to
Lanczos on ImportError, not blanket Exception.
User-uploaded files were stored in /app/data/files (container writable layer)
instead of /data/files (persistent volume) because the env var was not set in
the Dockerfile. Files were lost on container recreation.
Replace static llms.txt and llms-full.txt with auto-generated versions
that stay in sync with docs on every build. The plugin also generates
per-page .md files for individual page fetching by LLMs.
New tool for joining images horizontally or vertically,
distinct from the grid-based collage tool. Preserves aspect
ratios with fit/original resize modes, optional gap, and
multi-format output.
Users running lite mode had no way to tell why AI tools were greyed out.
Now the public health endpoint reports the variant, and a visible banner
appears in the tool panel when running in lite mode.
- Replace OpenCV Haar Cascades with MediaPipe for face detection, using
short-range model first with full-range fallback for better accuracy
- Add auto-orient to remove-background route for EXIF-rotated photos
- Change default background removal model from u2net to birefnet-general-lite
- Fix flaky test by setting SQLite busy_timeout before journal_mode pragma
Co-authored-by: Siddharth Kumar Sah <siddharth123sk@gmail.com>
Batch progress was broken because JobProgress events lacked a `type`
field. The frontend checks `data.type === "batch"` to distinguish batch
from single-file SSE events, so batch progress was silently discarded
and multi-file processing appeared stuck at 15%.
Also improves the processing UX for non-AI (Sharp-based) tools: the
progress bar now pulses during the server processing phase and shows
a "This may take a moment" hint after 10 seconds.
Co-authored-by: Siddharth Kumar Sah <siddharth123sk@gmail.com>
AI routes (remove-background, erase-object, ocr, blur-faces, upscale)
were silently swallowing errors - failures returned HTTP 422 to the
client but never appeared in server logs. This made it impossible for
self-hosters to diagnose issues like 504 timeouts from reverse proxies.
Adds request.log.info() at processing start (tool name, image size, key
settings) and request.log.error() in catch blocks, matching the existing
tool-factory pattern.
Co-authored-by: Siddharth Kumar Sah <siddharth123sk@gmail.com>
Prevent silent data corruption when the API is called directly
(bypassing UI guards). Binary/complex EXIF fields like MakerNote
are now filtered from fieldsToRemove in the image-engine operation.
Move sanitizeValue, parseExif, parseGps, parseXmp into the shared
image-engine package so both strip-metadata and edit-metadata can
reuse them. Includes 13 unit tests covering all four functions.