Adds an opt-in High Quality mode to the Object Eraser, backed by a new inpaint-hq feature bundle (Stable Diffusion 1.5 inpainting via diffusers). The default fast LaMa path is unchanged. Both arch archives are published to deepsafe/feature-bundles and the manifest carries their real sha256/sizes.
Verified end to end: a fresh container pulls the bundle from HuggingFace, checksum-verifies it, extracts torch/diffusers plus the fp16 model, and the HQ sidecar erases a large object with a plausible fill.
Refs #141
* fix(passport-photo): require the face-detection bundle, not just background-removal
Passport Photo runs face-landmark detection (face_landmarks.py, gated to the
face-detection bundle) before background removal (background-removal bundle),
but it was only declared under and guarded against background-removal. A user
who installed only Background Removal passed every JS-side check, then hit a
late "feature_not_installed" from the Python dispatcher gate when the analyze
step ran face landmarks, and the UI never told them Face Detection was needed.
- shared: add TOOL_EXTRA_BUNDLES + getRequiredBundlesForTool so a tool can
declare more than one required bundle (passport-photo needs background-removal
and face-detection). enablesTools is untouched, so the one-tool-per-bundle
invariant still holds.
- api: isToolInstalled() now checks every required bundle; add
getFirstMissingBundleForTool() so the analyze and base routes, pipeline (both
guards) and batch report the bundle the user actually still needs.
- web: the proactive install prompt (tool-page) and features-store treat a tool
as installed only when all required bundles are present, and point the prompt
at the first missing one (sequential install, no new UI).
Refs #327
* test(passport-photo): deterministic integration coverage for the two-bundle guard
Boots the real API with an isolated DATA_DIR and controls installed.json to
prove the HTTP route behavior end-to-end:
- nothing installed -> 501 naming background-removal
- only background-removal installed -> 501 naming face-detection (issue #327)
- both installed -> guard passes (not 501)
- base route reports face-detection too
Refs #327