Detection, metadata reading, trigger word cache, and prompt injection
for ComfyUI-Lora-Manager. All functions return empty results when
LoraManager is not installed.
* refactor(api): add multi-root output dir infrastructure (#126)
- Change _gallery_cache from None to {} (dict keyed by path string)
- Update invalidate_gallery_cache() to clear dict instead of setting None
- Add _get_all_output_dirs() helper as single source of truth for
resolving configured + fallback output directories
- Update _enrich_prompt_images() to iterate all output roots when
computing relative paths and thumbnail URLs
* feat(api): support multiple gallery scan paths in settings endpoint (#126)
* feat(ui): dynamic multi-path settings with add/remove buttons (#126)
* cleanup: remove dead galleryRootPath assignment in loadSettings
* feat(api): multi-directory gallery scan with subfolder filter and multi-root serve (#126)
* feat(db): add folder filter to search_prompts and get_prompt_subfolders (#126)
* feat(api): add subfolders endpoint and folder filter to prompt search (#126)
* feat(ui): add folder dropdown filter to search bar (#126)
* fix: escape LIKE wildcards in folder filter and remove dead _gallery_cache_time field
* feat(scan): scan all media types across all output dirs with batched extraction (#126)
* chore: gitignore SQLite WAL-mode temp files
* fix: enrich prompt images with URLs and check all output dirs for serving
- Extract _enrich_images() for flat image lists, used by get_prompt_images
- get_prompt_images now adds url/thumbnail_url (fixes stuck "Loading images...")
- serve_image checks all output dirs not just first (fixes 403 on multi-path)
- Fix diagnostics monitor check to read current module attribute, not stale import
* feat(ui): add version-scoped update notice popup for rescan (#126)
* chore: bump version to 3.2.0
* fix: diagnostics, backup, and restore now respect config.json db path (#132)
* test: add regression tests for config-aware diagnostics and backup (#132)
* fix(test): use fresh event loop to avoid aiohttp test pollution
* fix: don't kill singleton image monitor when node instance is garbage collected
The __del__ method was calling stop_monitoring() on the shared singleton
ImageMonitor, killing it for ALL nodes whenever any single node instance
was garbage collected between workflow runs. This caused the monitor to
restart on every execution and miss image save events due to race conditions.
* test: add regression tests for image monitor singleton lifecycle
Ensures cleanup/del never stops the shared monitor, singleton is
thread-safe, and observer survives across node instance lifecycles.
* style: address PR review — log suppressed exceptions, remove unused imports
* feat(ui): show prompt metadata sidebar in filmstrip viewer (#124)
The filmstrip viewer opened images without any metadata or prompt
display. Added shown/viewed callbacks to attach the existing metadata
sidebar with prompt text and copy button. Also added hidden callback
to both admin viewers for proper sidebar cleanup on close.
* chore: bump version to 3.1.6
* fix(ui): scope metadata sidebar to active viewer container (#124)
addMetadataSidebar() used querySelector('.viewer-container') which
grabbed the first match in the DOM. If a gallery viewer was opened
previously, its stale hidden container would be selected instead of
the active filmstrip viewer. Now iterates all containers and picks
the visible one.
* fix: resolve database path from config.json (#119)
PromptDatabase() was hardcoded to "prompts.db" relative to CWD,
ignoring the DEFAULT_DB_PATH setting from config.json. Added
_resolve_db_path() that reads from PromptManagerConfig when available
and resolves relative paths against the extension root directory.
This fixes Docker deployments where the CWD differs from the extension.
* test: add unit tests for database path resolution (#119)
Cover explicit absolute/relative paths, config fallback, relative
config paths resolved to extension root, and PromptDatabase constructor
integration with _resolve_db_path.
* docs: update database path configuration instructions (#119)
Replace outdated advice to edit py/config.py with correct config.json
approach. Add Docker-specific guidance for absolute paths.
* chore: bump version to 3.1.5
* fix: remove unused import and variables from test (#119)
Address code review: remove unused MagicMock import and unused db
local variables in constructor tests.
* fix(ui): enable click-to-close on all image viewers (#125)
The admin gallery viewer had backdrop: 'static' which prevented closing
by clicking the dark overlay. Changed to backdrop: true and added
explicit button: true across all three ViewerJS instances so users can
close the viewer by clicking outside or using the close button.
* chore: bump version to 3.1.4
* fix: initialize extended_tags before conditional block (#123)
extended_tags was only assigned inside the `if storage_text` block,
causing UnboundLocalError when text input is empty or whitespace-only.
Initialize to empty list before the conditional in both PromptManager
and PromptManagerText nodes.
* test: add unit tests for empty text input handling (#123)
Cover empty string, whitespace-only, empty with prepend/append, and
normal text for both PromptManagerText and PromptManager nodes.
* fix: use parts-based join to prevent double space on empty text (#123)
When main text is empty with prepend/append connected, the old string
concatenation produced "before after" (double space). Switch to
building a parts list and joining with single space so empty text is
cleanly skipped.
* test: add concatenation tests for prepend/append with empty text (#123)
Cover double-space regression, all-parts-present case, and
prepend-only with empty text for both node variants.
* fix: preserve connected input values in widget sync and queue hooks (#123)
The queuePrompt interceptor, syncPromptManagerWidgets, and serialize
hook were overwriting connected input link references with the widget's
empty DOM value. When text is connected from another node, ComfyUI puts
a link reference array in the output — these hooks now check for
connections before syncing, so externally connected text flows through.
* test: add connected-input contract tests for text + prepend + append (#123)
Verifies that externally connected text appears in the final output
alongside prepend/append — the exact scenario from the QA screenshot.
Covers both PromptManagerText and PromptManager (CLIP) variants.
* chore: bump version to 3.1.3
ComfyUI's execution engine walks backwards from output nodes. Without
OUTPUT_NODE = True, our nodes could be silently skipped when downstream
nodes are cached — even when IS_CHANGED returns a new value.
Since all three nodes have side effects (database writes, execution
tracking), they must be marked as output nodes so ComfyUI always
includes them in the execution graph.
Adds regression tests for OUTPUT_NODE and IS_CHANGED contracts.
Bumps version to 3.1.2.
Wrap float() casts for general_threshold and character_threshold in
try/except so malformed values return a structured 400 error instead
of an uncaught ValueError causing a 500.
Addresses review feedback on PR #114.
- Add append: to autotag skip-tagged filter alongside prepend:
- Update tag chip styling to dark fill with white text
- Add v3.1.0 changelog entry covering all changes since v3.0.26
Add two WD14 classifier models as alternatives to JoyCaption LLM taggers.
WD14 models are ~400MB ONNX classifiers that output Danbooru tags with
confidence scores — much faster inference, no prompt needed.
Backend:
- Add wd14-swinv2 and wd14-vit entries to MODELS dict
- Add check/download/load/generate methods for ONNX-based WD14 inference
- Add general_threshold and character_threshold params to generate_tags()
- Filter "prepend:*" tags from exclude prefixes and skip-tagged logic
Frontend:
- Add WD14 radio buttons with download status in both admin and gallery
- Toggle prompt textarea vs threshold sliders based on model selection
- Pass thresholds to API for batch and single-image tagging
- Extract _setModelStatus() helper using safe DOM methods
Dependencies: onnxruntime (optional, with clear error message)
- Remove unused `patch` import from test_output_dir.py
- Add debug log message to ImportError handler instead of bare pass
- Invalidate gallery file listing cache alongside output dir cache
when the user changes gallery_root_path in settings
_find_comfyui_output_dir() now checks GalleryConfig.MONITORING_DIRECTORIES
first before falling back to filesystem auto-detection. Also invalidates
the cached directory when the user changes the setting via save_settings().
Closes#108
- Move utils imports to module-level with try/except for relative
(ComfyUI) and absolute (test runner) import contexts in prompts.py.
Fixes 500 errors on rating update, prompt save, and prompt edit.
- Add missing None for rating parameter in image scan's save_prompt
call, which was passing the notes string as rating causing a type
comparison error during image scanning.
bg-opacity-N is ignored in Tailwind v4, causing overlays to render
as solid black rectangles (hiding gallery modal images). Converted
all bg-black bg-opacity-N to bg-black/N across admin.js, gallery.js,
and gallery.html.
The Python API only has static file routes for /prompt_manager/lib/
and /prompt_manager/js/ — no route exists for /css/. The theme CSS
was returning 404, causing all --pm-* variables to be undefined
(white/transparent rendering). Moved to lib/tailwind/ where the
existing route serves it correctly.
- Remove viewer-dark-theme class from ViewerJS init (overrides now global)
- Remove custom-scrollbar class usage (scrollbar styles now global)
- No dark: prefixes or class="dark" remain in codebase
Migrate all remaining hardcoded Tailwind color classes to --pm-* design
tokens across gallery.html, metadata.html, admin.js, gallery.js, and
tags-page.js. Zero hardcoded color classes remain in HTML/JS files.
- gallery.html: remove inline styles (now in comfyui-theme.css), strip
gradients/decorative elements, tighten spacing for ComfyUI density
- metadata.html: add theme imports, replace all color classes
- admin.js: replace 164 color occurrences in template literals, convert
raw hex values to CSS variable references
- gallery.js: replace 161 color occurrences in template literals
- tags-page.js: replace 30 color occurrences in template literals
start_monitoring() used an absolute import (from py.config) to read
MONITORING_DIRECTORIES, which either failed with ImportError or loaded
a separate module instance with empty defaults. The configured custom
directory was never used, and auto-detection always kicked in.
Fixed by consolidating into the single relative import (from ..py.config)
that was already used for the MONITORING_ENABLED check.
- Black (auto-fix formatting on commit)
- Flake8 (block on syntax errors and undefined names)
- Bandit (security scan, non-blocking to match CI)
- Tests (run on pre-push only)
- Apply Black formatting fixes caught by the new hooks
- Fix XSS in showFullPrompt() across admin.js, gallery.js, metadata.html
by replacing HTML string interpolation with DOM manipulation (createElement
+ textContent), eliminating unsafe user content injection
- Fix stack trace exposure in py/api error responses by replacing str(e)
with generic messages and adding logger.exception() for server-side
traceability